package com.anxpp.io.calculator.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
 * NIOͻ
 * @author yangtao__anxpp.com
 * @version 1.0
 */
public class ClientHandle implements Runnable{
	private String host;
	private int port;
	private Selector selector;
	private SocketChannel socketChannel;
	private volatile boolean started;

	public ClientHandle(String ip,int port) {
		this.host = ip;
		this.port = port;
		try{
			//ѡ
			selector = Selector.open();
			//򿪼ͨ
			socketChannel = SocketChannel.open();
			//Ϊ trueͨģʽΪ falseͨڷģʽ
			socketChannel.configureBlocking(false);//ģʽ
			started = true;
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
	}
	public void stop(){
		started = false;
	}
	@Override
	public void run() {
		try{
			doConnect();
		}catch(IOException e){
			e.printStackTrace();
			System.exit(1);
		}
		//ѭselector
		while(started){
			try{
				//Ƿжд¼selectorÿ1sһ
				selector.select(1000);
				//,ֻеһע¼ʱŻ.
//				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> it = keys.iterator();
				SelectionKey key = null;
				while(it.hasNext()){
					key = it.next();
					it.remove();
					try{
						handleInput(key);
					}catch(Exception e){
						if(key != null){
							key.cancel();
							if(key.channel() != null){
								key.channel().close();
							}
						}
					}
				}
			}catch(Exception e){
				e.printStackTrace();
				System.exit(1);
			}
		}
		//selectorرպԶͷԴ
		if(selector != null)
			try{
				selector.close();
			}catch (Exception e) {
				e.printStackTrace();
			}
	}
	private void handleInput(SelectionKey key) throws IOException{
		if(key.isValid()){
			SocketChannel sc = (SocketChannel) key.channel();
			if(key.isConnectable()){
				if(sc.finishConnect());
				else System.exit(1);
			}
			//Ϣ
			if(key.isReadable()){
				//ByteBufferһ1MĻ
				ByteBuffer buffer = ByteBuffer.allocate(1024);
				//ȡضȡֽ
				int readBytes = sc.read(buffer);
				//ȡֽڣֽڽб
				if(readBytes>0){
					//ǰlimitΪposition=0ںԻĶȡ
					buffer.flip();
					//ݻɶֽֽ
					byte[] bytes = new byte[buffer.remaining()];
					//ɶֽ鸴Ƶ½
					buffer.get(bytes);
					String result = new String(bytes,"UTF-8");
					System.out.println("ͻյϢ" + result);
				}
				//ûжȡֽ 
//				else if(readBytes==0);
				//·ѾرգͷԴ
				else if(readBytes<0){
					key.cancel();
					sc.close();
				}
			}
		}
	}
	//첽Ϣ
	private void doWrite(SocketChannel channel,String request) throws IOException{
		//ϢΪֽ
		byte[] bytes = request.getBytes();
		//ByteBuffer
		ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
		//ֽ鸴Ƶ
		writeBuffer.put(bytes);
		//flip
		writeBuffer.flip();
		//ͻֽ
		channel.write(writeBuffer);
		//****˴дĴ
	}
	private void doConnect() throws IOException{
		if(socketChannel.connect(new InetSocketAddress(host,port)));
		else socketChannel.register(selector, SelectionKey.OP_CONNECT);
	}
	public void sendMsg(String msg) throws Exception{
		socketChannel.register(selector, SelectionKey.OP_READ);
		doWrite(socketChannel, msg);
	}
}