package;
import java.nio.channels.*;
import java.nio.ByteBuffer;
import java.net.*;
import java.io.IOException;
import bluntirc.App;

class Plugin implements base.SelectorItem{
	static String request="GET / HTTP/1.0\r\nHost: yahoo.co.jp\r\n\r\n";

	SelectionKey key;
	SocketChannel channel;
	ByteBuffer read_result=ByteBuffer.allocate(4096);
	ByteBuffer write_result=ByteBuffer.wrap( request.getBytes("UTF8"));

	public Plugin(bluntirc.ScriptManager manager){
		// アドレスの解決
		InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("yahoo.co.jp"),80);
		// ソケットの作成
		channel =SocketChannel.open();
		// 非同期にしてセレクタに登録
		channel.configureBlocking(false);
		key = App.selector.register(this,channel);
		// 接続開始
		channel.connect(remote);
		App.Log("waiting connect");
	}
	public void unload(){
		close("unload");
	}

	public boolean onAcceptable (SelectableChannel which){ return true;}

	public boolean onConnectable(SelectableChannel which){
		try{
			if(channel.finishConnect()){
				// 接続した
				interest_ops_for_write=SelectionKey.OP_WRITE|SelectionKey.OP_READ;
				key.interestOps(interest_ops_for_write);

				return false;
			}
			return false;
		}catch(IOException e){ return closeByError(e,"connect"); }
	}

	public boolean onWritable(SelectableChannel which){
		try{
			channel.write(write_result);
			if(!write_result.hasRemaining()){
				key.interestOps(SelectionKey.OP_READ);
				return true;
			}
			return false;
		}catch(IOException e){ return closeByError(e,"write"); }
	}

	public boolean onReadable(SelectableChannel which){
		try{
			int r= channel.read(read_result);
			if(r==-1) return close("end of input stream");
			if(r<= 0) return false;
			if(!read_result.hasRemaining() ){
				App.Log("buffer length"+(new String(read_result.array(),"EUC-JP")).length());
				read_result.clear();
			}
			return false;
		}catch(IOException e){ return closeByError(e,"read"); }
	}

	public boolean closeByError(Throwable e,String reason){
		reason+=" error";
		App.Log(reason+": "+e.toString());
		return close(reason);
	}

	public boolean close(String reason){
		if(channel!=null){
			// バッファに呼んだ残りを出力
			read_result.flip();
			if( read_result.hasRemaining() ){
				byte[] b = new byte[read_result.limit()];
				read_result.get(b);
				App.Log("buffer length"+(new String(b,"EUC-JP")).length());
				read_result.clear();
			}
			// 閉じる
			try{
				channel.close();
			}catch(Throwable e){
				App.Log(e.toString());
			}
			channel=null;
			App.Log("close. reason="+reason);
		}
		return true;
	}
}
