/**
 *
 * Galatea Dialog Manager:
 * (c)2003 Takuya NISHIMOTO (nishi@hil.t.u-tokyo.ac.jp)
 *
 *  $Id: DialogManager.java,v 1.32 2008/04/09 10:06:53 nishi Exp $
 */

package galatea.dialog;

import galatea.dialog.window.DialogManagerWindow;
import galatea.dialog.window.IDMWindowActionListener;
import galatea.document.ContentState;
import galatea.document.DocError;
import galatea.document.DocLoader;
import galatea.document.StateMap;
import galatea.httpclient.NetUtil;
import galatea.httpserver.HttpServer;
import galatea.logger.Logger;
import galatea.scripting.ECMAScript;
import galatea.util.Getopt;
import galatea.util.Messages;
import galatea.util.Property;
import galatea.util.Util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;


/**
 * @author nishi
 *
 */
public class DialogManager {
	private static final String propertiesPath = "/res/config/dialog.properties";
	private static final String messagesPath = "res.messages.messages";

	private Logger dbg;
	
	private IC theIC_;
	private IInteractionController interactionController_;
	private IControllerModeManager modeManager_;
	private String filename;
	private String poststring;
	
	/**
	 * @param res
	 * @return
	 */
	public static String getResourceAsString(String res) {
		InputStream is = DialogManager.class.getResourceAsStream(res);
		String str = Util.readInputStream(is, Charset.forName("UTF-8"));
		return str;
	}
	
	public static void main(String argv[]) {
		DialogManager dm = new DialogManager();
		dm._setup(argv);
		dm._waitDevicesForReady();
		dm._execute();
		Util.halt("Galatea Dialog Manager terminated.");	
	}
	
	public DialogManager() {
		dbg = new Logger("DM");
	}

	/**
	 * @param argv
	 * -v (show version) 
	 * -p (print only)
	 * -c my_gdm.conf
	 * -D name=value
	 */
	private void _setup(String[] argv) {
		Messages.setup(messagesPath);

		//String conf = "gdm.conf";
		boolean isPrintOnly = false;
		ArrayList<String> confFileNames = new ArrayList<String>();
		ArrayList<String> overrideParams = new ArrayList<String>();
		
		Getopt g = new Getopt("", argv, "c:vpD:");
		g.setOpterr(false);
		int c;
		while ((c = g.getopt()) != -1){
			switch (c)	{
			case 'c':
				confFileNames.add(g.getOptarg());
				break;
			case 'v':
				showVersion();
				showUsage();
				System.exit(1);
				break; // ignored
			case 'p':
				isPrintOnly = true;
				break;
			case 'D':
				overrideParams.add(g.getOptarg());
				break;
			}
		}
		
		Properties props = new Properties(System.getProperties());
		InputStream is = DialogManager.class.getResourceAsStream(propertiesPath);
		try {
			props.load(is);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(0);
		}
		for (String conf : confFileNames) {
			File conffile = new File(conf);
			if (conffile.canRead()) {
				try {
					props.load(new FileInputStream(conffile));
				} catch(Exception e) {
					e.printStackTrace();
					// System.exit(0);
				}
			}
		}
		for (String s : overrideParams) {
			ArrayList<String> v = Util.makeTokenizedList(s, "=");
			if (v.size() == 2) {
				props.setProperty(v.get(0), v.get(1));
			}
		}
		System.setProperties(props);
		
//		for (Enumeration<Object> en = System.getProperties().keys(); en.hasMoreElements(); ) {
//			String key = (String)(en.nextElement());
//			String val = System.getProperty(key);
//			System.err.printf("%s=%s\n", key, val);
//		}
		
		if ( isPrintOnly ) {
			System.out.print(DocLoader.convert(argv[g.getOptind()]));
			System.exit(0);
		}
		
		if (argv.length - g.getOptind() != 1){
			filename = null; // _getDefaultFile();
		} else {
			filename = argv[g.getOptind()];
			filename = Util.getNormalizedFileName(filename);
		}
		
		// 
		String workdir = Property.getForPlatformAsStr("Grammar.WorkDir", "/tmp");
		File file = new File(workdir);
		if (!file.exists()) {
			file.mkdir();
			//System.err.println("no directory : " + workdir);
			//System.exit(0);
		}

		theIC_ = new IC();
		theIC_.start();
		if ( Property.getAsBoolean("ShowVersion", true) ) {
			showVersion();
			System.err.println(theIC_.getScriptVersionAndCopyright());
		}
		interactionController_ = theIC_;
		modeManager_ = theIC_;
	}

	public void showVersion() {
		System.err.println(galatea.dialog.Tstamp.TSTAMP);
		System.err.println(galatea.dialog.Tstamp.COPYRIGHT);
	}
	
	public 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();
	}
	
	private void _waitDevicesForReady() {
		interactionController_.waitDevicesForReady();
	}
	
	private void _execute() {
		NetUtil.createCookieManager();
		while (true) {
			try {
				if (filename != null && filename.length() > 0 ) {
					dbg.print("filename:" + filename);
					modeManager_.setStatelessMode(false);
					String path = Util.getUriWithoutFragment(filename);
					String dialog = Util.getUriFragment(filename);
					DocLoader loader = new DocLoader(filename, path, dialog, poststring);
					StateMap stateMap = loader.getStateMap();
					if ( stateMap == null ) {
						throw new DocError("Document not found: " + filename);
					}
					interactionController_.setStateMap(stateMap);
					String state = "[Load] " + filename + " [post] " + poststring;
					String src = loader.getSrcAsString();
					String trans = 
						// loader.getWarnings() + "\n" + 
						loader.getTranslatedAsString();
					interactionController_.dispDocInfo(filename, state, src, trans);
				} else {
					dbg.print("StatelessMode=true");
					interactionController_.dispDocInfo("", "(no dialog)", "", "");
					modeManager_.setStatelessMode(true);
				}
				interactionController_.mainLoop();
				filename = interactionController_.getNextDocFile();
				poststring = interactionController_.getPostString();
				interactionController_.resetNextDocFile();
//			} catch(java.io.FileNotFoundException e){
//				System.err.println("caught " + e.toString());
//				modeManager_.setStatelessMode(true);
//				modeManager_.setPauseMode(true);
//				interactionController_.dispDocInfo("", "(stateless)", "", "");
//				interactionController_.resetNextDocFile();
//				filename = "";
//			} catch(org.xml.sax.SAXParseException e){
//				System.err.println("caught " + e.toString());
//				interactionController_.resetNextDocFile();
//			} catch(galatea.document.DocError e){
//				System.err.println("caught " + e.toString());
//				modeManager_.setStatelessMode(true);
//				modeManager_.setPauseMode(true);
//				interactionController_.dispDocInfo("", "(stateless)", "", "");
//				interactionController_.resetNextDocFile();
//			} catch(galatea.dialog.RuntimeError e){
//				System.err.println("caught " + e.toString());
//				modeManager_.setStatelessMode(true);
//				modeManager_.setPauseMode(true);
//				interactionController_.dispDocInfo("", "(stateless)", "", "");
//				interactionController_.resetNextDocFile();
			} catch(java.lang.Exception e){
//				System.err.println("caught " + e.toString());
//				interactionController_.resetNextDocFile();
				System.err.println("caught " + e.toString());
				modeManager_.setStatelessMode(true);
				modeManager_.setPauseMode(true);
				interactionController_.dispDocInfo("", "(no dialog)", "", "");
				interactionController_.resetNextDocFile();
				filename = "";
			}
		}
	}

}
