/*
 * Copyright 2008 nori090
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.coderepos.nori090;

import java.io.File;
import java.io.UnsupportedEncodingException;

/**
 * PCRaw.dllのJavaBridgeサンプルです。
 * 
 * @author nori090
 * @version $Rev: 13 $ $Date: 2008-03-25 22:41:28 +0900 (Tue, 25 Mar 2008) $
 */
public class PCRawJavaBridge {
    static {
        System.loadLibrary( "PCRawJavaBridge" );
    }

    /**
     * PCRaw.dllのフルパスを指定して、DLLを読み込みます。<BR>
     * また、PCRawからwinsockを使うためにネットワークの準備を行います。
     * 
     * @param path
     * @return 適当な値。マイナスだと失敗してると思う。
     */
    public static native int LoadPCRawDLL( String path );

    /**
     * LoadPCRawDLLで読み込んだDLLをFreeします。<BR>
     * また、ネットワークの終了処理を行います。
     */
    public static native void UnLoadPCRawDLL();

    /**
     * PCRawCreateにUTF-8な文字列を投げ込みます。<BR>
     * 動作未検証。
     * 
     * @param url rawモードのstream url
     * @return
     */
    public static native int PCRawCreate1( String url );

    /**
     * 動作確認を行ったPCRawCreateメソッド。<BR>
     * PCRawCreate1と同様ですが、byte配列を渡します。<BR>
     * 
     * @param url(rawモードのstream url。byte配列の末尾は\0で終わるべき。)
     * @return HANDLEが返ります。以後の処理は、この戻り値を(void*)として扱います。
     */
    public static native int PCRawCreate2( byte[] url );

    /**
     * PCRawCloseです。PCRawCreateしたインスタンスの終了処理と、<BR>
     * {@link PCRawJavaBridge#UnLoadPCRawDLL()}と同様の処理を行います。
     * 
     * @param handle PCRawCreateしたハンドル。
     */
    public static native void PCRawClose( int handle );

    /**
     * PCRawGetLengthそのままです。基本的にLockしてから使うべきです。って、書いてありました。
     * 
     * @param handle
     * @return PCRawGetLength
     */
    public static native int PCRawGetLength( int handle );

    /**
     * PCRawGetDataそのままです。基本的にLockしてから使うべきです。って、書いてありました。<BR>
     * index.txtは基本的にUTF-8なので、返ってきた値は、UTF-8で読むと問題ないと思います。
     * 
     * @param handle ハンドル
     * @param buf 書き込むバイト配列
     * @param len 書き込むサイズ
     * @return 実際に書き込んだサイズ。
     */
    public static native int PCRawGetData( int handle, byte[] buf, int len );

    /**
     * PCRawGetLastErrorそのままです。
     * 
     * @param handle
     * @return
     */
    public static native int PCRawGetLastError( int handle );

    /**
     * PCRawGetUpdateTimeそのままですが、DWORDをintとして返しています。
     * 
     * @param handle
     * @return
     */
    public static native int PCRawGetUpdateTime( int handle );

    /**
     * PCRawDataLockそのままです。受信データを触るときに実施すると良いそうです。
     * 
     * @param handle
     */
    public static native void PCRawDataLock( int handle );

    /**
     * PCRawDataUnlockそのままです。受信データを触り終わったら実施すると良いそうです。
     * 
     * @param handle
     */
    public static native void PCRawDataUnlock( int handle );

    /**
     * PCRawCheckVersionですが、PCRaw.dllからバージョンを取ってくるだけで、 比較処理は行いません。<BR>
     * DWORDを単純にintとして返しているので、真面目にバイト配列を読んだ方がいいかもしれません。
     * 
     * @return
     */
    public static native int PCRawCheckVersion();

    public static void main( String[] args )
        throws UnsupportedEncodingException, InterruptedException {
        /*
         * このプロジェクト直下にあるpcraw.dllのFileオブジェクトを生成します。
         */
        File f = new File( "pcraw.dll" );
        /*
         * ネイティブライブラリにフルパスを渡して読み込みます。
         */
        LoadPCRawDLL( f.getAbsolutePath() );
        /*
         * rawモードのストリームURLを準備します。末尾は\0で埋めています。
         */
        String s = "http://localhost:7144/stream/115981D07499140CB2F5E109AA09C79C?tip=extremeyp.ath.cx:37144\0";
        /*
         * 何故かUS-ASCIIで渡してます。適当です。動いたからいいです。
         */
        int handle = PCRawCreate2( s.getBytes( "US-ASCII" ) );
        /*
         * 読み込むバッファを確保します。
         */
        byte[] bs = new byte[1024];
        while ( true ) {
            /*
             * 本当はロックして、サイズに応じてバッファを確保したのちに、 GetDataを呼び出し、バッファサイズ分読み込む方が良いと思います。 読み込んだ後は、アンロックします。
             */
            if ( PCRawGetLength( handle ) > 0 ) {
                int size = PCRawGetData( handle, bs, bs.length );
                if ( size > 0 ) {
                    /*
                     * 読み込んだバイト配列をUTF-8として表示します。
                     */
                    System.out.println( new String( bs, 0, size, "UTF-8" ) );
                    break;
                }
            }
            else {
                Thread.sleep( 1000 );
            }
        }
        /*
         * 終了する際は、必ずクローズしてください。try {create()}finally{close()}が良いかもしれません。
         */
        PCRawClose( handle );
    }
}
