/*
 * $Id: JuliusClient.java,v 1.10 2008/02/12 06:15:29 nishi Exp $
 */

package galatea.recogman;

import galatea.util.AMBuffer;
import galatea.util.Util;

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.Iterator;


public class JuliusClient 
{
	private String ADDRESS = "localhost"; // "192.168.1.20"
	private int PORT = 10500;
	
	private SocketChannel channel;
	private Selector selector;
	private ByteBuffer byteBuffer = ByteBuffer.allocateDirect(2048);
	private String inputBuffer = "";
	
	private Charset charset;
	private CharsetDecoder decoder;
	private CharsetEncoder encoder;
	
	public JuliusClient(String addr, int port/*, String enc*/)
	{
		//ENCODING = enc;
		ADDRESS = addr;
		PORT = port;
	}
	
	
	public void send(String str) throws IOException 
	{
		byteBuffer.clear();
		encoder.reset();
		encoder.encode(CharBuffer.wrap(str), byteBuffer, true);
		byteBuffer.flip();
		channel.write(byteBuffer);
//		try {
//			byteBuffer.clear();
//			encoder.reset();
//			encoder.encode(CharBuffer.wrap(str), byteBuffer, true);
//			byteBuffer.flip();
//			channel.write(byteBuffer);
//		} catch (IOException ex) {
//			ex.printStackTrace();
//		}
	}
	
	
//	private String chomp(String src)
//	{
//		if (src == null || src.length() < 2) return "";
//		return src.substring(0, src.length() - 1);
//	}
	
	
	public String getMessage()
	{
		String ret = "";
		int pos = inputBuffer.indexOf(">.");
		if (pos > 0) {
			ret = inputBuffer.substring(0, pos+1);
			inputBuffer = inputBuffer.substring(pos+2);
		}
		return ret;
	}
	
	
	public void open() throws IOException
	{
		charset = Util.getSystemDefaultCharset(); //Charset.forName(ENCODING);
		decoder = charset.newDecoder();
		encoder = charset.newEncoder();
		channel = SocketChannel.open();
		selector = Selector.open();
		InetSocketAddress address = new InetSocketAddress(ADDRESS, PORT);
		boolean connected = false;
		while (!connected) {
			try {
				channel.connect(address);
				connected = true;
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		channel.configureBlocking(false);
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	
	public void receive() throws CharacterCodingException, IOException
	{
		if (selector.selectNow() > 0) {
			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			while (it.hasNext()) {
				SelectionKey key = (SelectionKey)it.next();
				it.remove();
				if (key.isReadable()) {
					byteBuffer.clear();
					channel.read(byteBuffer);
					byteBuffer.flip();
					decoder.reset();
					String str = decoder.decode(byteBuffer).toString();
					// System.err.println("[receive] " + str);
					str = str.replaceAll("\\s+<", "<");
					str = str.replaceAll("\n", "");
					inputBuffer += str;
				}
			}
		}
	}
	
	
	public void close()
	{
		try {
			channel.close();
			selector.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	
	/**
	 * $ cd phoenix
	 * $ java -cp classes galatea/JuliusClient
	 */
	public static void main(String[] args) 
	{
		AMBuffer ambuf = new AMBuffer(Util.getSystemDefaultCharset());
		JuliusClient client = new JuliusClient("localhost", 10500);
		try {
			client.open();
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		ambuf.send("open");
		while (true) {
			String msg;
			try {
				client.receive();
			} catch (CharacterCodingException e1) {
				e1.printStackTrace();
				break;
			} catch (IOException e1) {
				e1.printStackTrace();
				break;
			}
			while ((msg = client.getMessage()).length() > 0) {
				ambuf.send("tell " + msg);
			}
			String in = ambuf.receive();
			if (in.length() > 0) {
				if (in.equals(".")) {
					break;
				} else {
					String cmd = in + "\n"; 
					try {
						client.send(cmd);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			try { Thread.sleep(1); } catch (Exception e) {}
		}
		client.close();
	}
}
