/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * RecogManager for Galatea DM
 *
 * (c)2004 Takuya NISHIMOTO (nishi@hil.t.u-tokyo.ac.jp)
 *
 *  $Id: RecogManager.java,v 1.4 2006/11/17 05:07:40 nishi Exp $
 */

package galatea.recogman;

import java.nio.charset.Charset;
import java.util.regex.*;

import galatea.dialog.Tstamp;
import galatea.util.*;


public class RecogManager implements RecogInterpreterListener
{
	private AMBuffer ambuf_;
	private RecogInterpreter recogInterpreter_;
	
	static String  xmlContent_ = "";
	private static boolean debugMode = false;
	
	private void _debugPrint(String str)
	{
		if (debugMode) {
			System.err.println(str);
		}
	}
	
	
	public RecogManager()
	{
	}
	
	
	public void run()
	{
		recogInterpreter_ = new RecogInterpreter();
		recogInterpreter_.setListener(this);
		ambuf_ = new AMBuffer(Util.getSystemDefaultCharset()); 
		
		Pattern pattern1 = Pattern.compile("^From @SRM tell [1-9][0-9][0-9] (<.*)$");
		Pattern pattern2 = Pattern.compile("^From @SRM tell (<.*)$");
		
		boolean multiLineMessage = false;
		while (true) {
			String str = ambuf_.receive();
			if (str.length() > 0) {
				
				if (multiLineMessage) {
					String s = str.replaceAll("From @SRM ", "");
					_fromSRMtell(s);
				} else if (str.startsWith("From @SRM tell << EOM")) {
					multiLineMessage = true;
					_debugPrint("[SIM] multiLine Start ");
				} else if (str.startsWith("From @SRM EOM")) {
					multiLineMessage = false;
					_debugPrint("[SIM] multiLine End");
				} else {
					// "From @SRM 100 tell"
					// "From @SRM 201 tell"
					Matcher matcher1 = pattern1.matcher(str);
					if (matcher1.matches()) {
						_fromSRMtell(matcher1.group(1));
					}
					Matcher matcher2 = pattern2.matcher(str);
					if (matcher2.matches()) {
						_fromSRMtell(matcher2.group(1));
					}
				}
				
				_debugPrint(str);
				
				// "set AAA = bbb"
				String s;
				
				if ((s = Util.getFirstGroup("set DialogName = (.*)$", str)) != null) {
					recogInterpreter_.setDialogName(s);
					
				} else if ((s = Util.getFirstGroup("set SlotAlias = (.*)$", str)) != null) {
					if (s.equals("RESET")) {
						recogInterpreter_.resetSlotAlias();
					} else {
						recogInterpreter_.setSlotAlias(s);
					}
					
				} else if ((s = Util.getFirstGroup("set Script = (.*)$", str)) != null) {
					// set Script = interval.js
					recogInterpreter_.setScript(s);
				} else if ((s = Util.getFirstGroup("set EventHandler = (.*)$", str)) != null) {
					recogInterpreter_.setEventHandler(s);
				}
				
			}
			
			try {
				Thread.sleep(1);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
	private void _send(String str)
	{
		ambuf_.send(str);
	}
	
	private void _sendRecogState(int s)
	{
		_send("to @DIM set RecogState = " + s);
	}
	
	private void _sendUserSpeakState(int s)
	{
		_send("to @DIM set UserSpeakState = " + s);
	}
	
	public void recogListenStarted() // implements RecogListener
	{
		_sendUserSpeakState(0);
		// _send("to @DM From @SIM tell 201 LISTEN");
	}
	
	public void recogRecordStarted() // implements RecogListener
	{
		_sendUserSpeakState(1);
	}
	
	public void recogRecordFinished() // implements RecogListener
	{
		_sendUserSpeakState(0);
	}
	
	public void recogPass1Finished() // implements RecogListener
	{
	}
	
	public void recogPass2Finished() // implements RecogListener
	{
		String sc = recogInterpreter_.getScript();
		String text = recogInterpreter_.getText();
		_speechRecognized(text, sc);
	}
	
	public void recogFailed() // implements RecogListener
	{
	}
	
	public void recogException(Exception e, String str) // implements RecogListener
	{
		_debugPrint("[SIM] recogException(" + str +")");
		e.printStackTrace();
	}
	
	private void _fromSRMtell(String s)
	{
		_debugPrint("[SIM] [" + xmlContent_ + "] [" + s + "]");
		
		if (s.startsWith("<STARTPROC/>")) {
			_debugPrint("[SIM] ignored " + s);
			return;
		}
		if (s.startsWith("<GMM ")) {
			_debugPrint("[SIM] ignored " + s);
			return;
		}
		// TODO: handle <GRAMMAR STATUS="RECEIVED"/>
		s = s.replaceAll("<GRAMMAR STATUS=\"RECEIVED\"/>","");
		
		if (xmlContent_.length() > 0 || s.startsWith("<")) {
			xmlContent_ += s;
			// TODO: validation 
			if (/* xmlContent_.endsWith("/>") || */ 
					xmlContent_.endsWith("</RECOGOUT>") 
					|| xmlContent_.endsWith("</GRAMINFO>") 
			) {
				try {
					recogInterpreter_.receiveRecogMessage(xmlContent_);
				} catch (Exception e) {
					if (debugMode) {
						e.printStackTrace();
					}
				}
				xmlContent_ = "";
			}
			/****
			 } else if (s.matches("^[1-9][0-9][0-9] .*$")) {
			 _send("to @DM From @SIM tell " + s);
			 ***/
		}
	}
	
	
	private void _speechRecognized(String text, String script)
	{
		_send("to @DM From @SIM tell 300 <ev src=\"SRM\" type=\"INPUT\"><interpreted>"
				+"<text>" + text + "</text>"
				+"<script>" + script + "</script></interpreted></ev>");
	}
	
	
	public static void main(String argv[])
	{
    	Getopt g = new Getopt("", argv, "vd");
    	g.setOpterr(false);
    	int c;
    	while ((c = g.getopt()) != -1){
    		switch (c)	{
    		case 'v':
    			showVersion();
    			break;
    		case 'd':
    			debugMode = true;
    			break;
    		}
    	}
    	
		RecogManager recogManager = new RecogManager();
		recogManager.run();
	}
	
	public static final String COPYRIGHT = 
		"(c)2003-2006 Takuya NISHIMOTO (nishi@hil.t.u-tokyo.ac.jp)\n";
	
	public static void showVersion() {
		System.err.println("RecogManager");
		System.err.println(galatea.dialog.Tstamp.TSTAMP);
		System.err.print(COPYRIGHT);
		System.err.println();
	}
	
	public static void showUsage() {
//		System.err.println("Usage:\tgalatea [options] document.vxml");
//		System.err.println("\t -c file : config file");
//		System.err.println("\t -v      : show version");
//		System.err.println("\t -p      : print translation results");
//		System.err.println();
	}
	
}
