/*
 * Galatea Dialog Manager:
 * (c)2003 Takuya NISHIMOTO (nishi@hil.t.u-tokyo.ac.jp)
 *
 * $Id: PDoc.java,v 1.9 2008/02/14 02:00:07 nishi Exp $
 */

package galatea.document;

import galatea.command.AddOutItemCommand;
import galatea.command.Command;
import galatea.command.CompositeCommand;
import galatea.command.EndCommand;
import galatea.command.EvaluateCommand;
import galatea.command.GotoCommand;
import galatea.command.SetNextCommand;
import galatea.command.StopOutputCommand;
import galatea.logger.Logger;
import galatea.outitem.AudioOutItem;
import galatea.outitem.BreakOutItem;
import galatea.outitem.GrammarOutItem;
import galatea.outitem.LogOutItem;
import galatea.outitem.NativeOutItem;
import galatea.outitem.OutItem;
import galatea.outitem.VoiceOutItem;
import galatea.relaxer.pdoc.IPdocAddChoice;
import galatea.relaxer.pdoc.IPdocCmdContentsChoice;
import galatea.relaxer.pdoc.PdocAdd;
import galatea.relaxer.pdoc.PdocAudio;
import galatea.relaxer.pdoc.PdocBody;
import galatea.relaxer.pdoc.PdocBreak;
import galatea.relaxer.pdoc.PdocCatch;
import galatea.relaxer.pdoc.PdocCmd;
import galatea.relaxer.pdoc.PdocEnd;
import galatea.relaxer.pdoc.PdocGoto;
import galatea.relaxer.pdoc.PdocGrammarout;
import galatea.relaxer.pdoc.PdocLog;
import galatea.relaxer.pdoc.PdocNative;
import galatea.relaxer.pdoc.PdocNext;
import galatea.relaxer.pdoc.PdocPdoc;
import galatea.relaxer.pdoc.PdocScript;
import galatea.relaxer.pdoc.PdocState;
import galatea.relaxer.pdoc.PdocStopoutput;
import galatea.relaxer.pdoc.PdocVoice;

import java.util.ArrayList;

import org.w3c.dom.Element;

public class PDoc implements IAbstractDoc
{
	private Logger dbg = new Logger("PDoc");
	private String docAddress_;
//	private Element element_;
	private StateMap stateMap_;
	
	public StateMap getStateMap()
	{
		return stateMap_;
	}
	
	public String getDocAddress()
	{
		return docAddress_;
	}
	
	public void setDocAddress(String adrs)
	{
		docAddress_ = adrs;
	}
	
	
	private Command getCompositeCommand( PdocCmd composite ) throws Exception
	{
		ArrayList<Command> vec = new ArrayList<Command>();
		
		for ( int j = 0; j < composite.sizeCmdContents(); j++ ) {
			IPdocCmdContentsChoice cc = composite.getCmdContents(j);
			if ( cc instanceof PdocAdd ) {
				PdocAdd add = (PdocAdd)cc;
				String cond = ((PdocAdd)cc).getCond();
				
				ArrayList<OutItem> items = new ArrayList<OutItem>();
				IPdocAddChoice aclist[] = add.getContent();
				for ( int k = 0; k < aclist.length; k++ ) {
					IPdocAddChoice ac = aclist[k];
					if ( ac instanceof PdocAudio ) {
						String src = ((PdocAudio)ac).getContent();
						AudioOutItem o = new AudioOutItem(src);
						//o.setBargein(((PdocAudio)ac).getBargein());
						items.add(o);
					} else if ( ac instanceof PdocBreak ) {
						BreakOutItem o = new BreakOutItem(((PdocBreak)ac));
						items.add(o);
					} else if ( ac instanceof PdocLog ) {
						String with = ((PdocLog)ac).getWith();
						String text = ((PdocLog)ac).getContent();
						LogOutItem o = new LogOutItem(text, with);
						items.add(o);
					} else if ( ac instanceof PdocNative ) {
						String with = ((PdocNative)ac).getWith();
						String text = ((PdocNative)ac).getContent();
						NativeOutItem o = new NativeOutItem(text, with);
						items.add(o);
					} else if ( ac instanceof PdocVoice ) {
						String with = ((PdocVoice)ac).getWith();
						String text = ((PdocVoice)ac).getContent();
						VoiceOutItem o = new VoiceOutItem(text, with);
						//o.setBargein(((PdocVoice)ac).getBargein());
						items.add(o);
					} else if ( ac instanceof PdocGrammarout ) {
						String gramstr = ((PdocGrammarout)ac).getContent();
						String name = ((PdocGrammarout)ac).getName();
//						String dir = ((PdocGrammarout)ac).getDir();
//						GrammarOutItem o = new GrammarOutItem(gramstr, name, dir);
						// TODO use dir
						GrammarOutItem o = new GrammarOutItem(gramstr, name);
						items.add(o);
					}
				} // for k
				Command c = (Command)( new AddOutItemCommand(items, cond) );
				vec.add(c);
				
			} else if ( cc instanceof PdocCmd ) {
				Command c = getCompositeCommand((PdocCmd)cc); // recursive
				vec.add(c);
			} else if ( cc instanceof PdocEnd ) {
				String next = ((PdocEnd)cc).getContent();
				boolean now = ((PdocEnd)cc).getNow();
				String cond = ((PdocEnd)cc).getCond();
				Command c = (Command)( new EndCommand(next, cond, now) );
				vec.add(c);
			} else if ( cc instanceof PdocGoto ) {
				String next = ((PdocGoto)cc).getContent();
				String cond = ((PdocGoto)cc).getCond();
				Command c = (Command)( new GotoCommand(next, cond) );
				vec.add(c);
			} else if ( cc instanceof PdocNext ) {
				String next = ((PdocNext)cc).getContent();
				String cond = ((PdocNext)cc).getCond();
				Command c = (Command)( new SetNextCommand(next, cond) );
				vec.add(c);
			} else if ( cc instanceof PdocScript ) {
				String content = ((PdocScript)cc).getContent();
				String with = ((PdocScript)cc).getWith();
				String cond = ((PdocScript)cc).getCond();
				Command c = (Command)( new EvaluateCommand(content, with, cond) );
				vec.add(c);
			} else if ( cc instanceof PdocStopoutput ) {
				String cond = ((PdocStopoutput)cc).getCond();
				Command c = (Command)( new StopOutputCommand(cond) );
				vec.add(c);
			}
		}
		
		String cmdcond = composite.getCond();
		return (Command) new CompositeCommand(vec, cmdcond);
	}
	
	
	public PDoc(Element e, String path, String fragment) throws Exception
	{
//		element_ = e;
		docAddress_ = path;
		
		if (PdocPdoc.isMatch(e) == false) {
			throw new DocError("Not a valid <pdoc> document: " + path);
		}
		PdocPdoc pdoc = new PdocPdoc(e);
		
		stateMap_ = new StateMap();
		stateMap_.setPdocVersion(pdoc.getVersion());
		
		///
		PdocBody body = pdoc.getBody();
		
		String start = body.getStart();
		stateMap_.setFirstStateName(start);
		
		for ( int i = 0; i < body.sizeState(); i++ ) {
			PdocState state = body.getState(i);
			dbg.print(i+">"+state.toString());
			String stateId = state.getId();
			stateMap_.newState(stateId);
			
			PdocCmd cmd = state.getCmd();
			Command c = getCompositeCommand(cmd);
			stateMap_.addCommand(stateId, c);
			
			for ( int j = 0; j < state.sizeCatch(); j++ ) {
				PdocCatch pcatch = state.getCatch(j);
				String event = pcatch.getEvent();
				if (event == null) {
					event = ".*";
				}
				String next  = pcatch.getNext();
				if (next != null) {
					stateMap_.addTrans(stateId, next, event);
				}
			}
		}
	}

	public String getDocWarnings() {
		return "";
	}
	
}
