
/**
 * JMichelle (Java Midori Shell)
 * Copyright (C) 2000 Midori IGA 
 *   (http://www01.u-page.so-net.ne.jp/db3/midori/midosoft.html)
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package jp.ne.nifty.iga.midori.shell.eng;

import jp.ne.nifty.iga.midori.shell.*;
import jp.ne.nifty.iga.midori.shell.io.*;
import jp.ne.nifty.iga.midori.shell.util.*;
import java.io.*;
import java.text.Collator;
import java.text.CollationKey;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import java.util.Vector;

public class MdShellEngine
{
	private MdShellEnv shellenv;

	/**
	 * History
	 */
	private Vector vecCommandHistory=new Vector(1024);

	public MdShellEngine(MdShellEnv shellenv)
	{
		this.shellenv=shellenv;

		init();
	}

	public void init()
	{
		shellenv.init();

		//vecCommandHistory.addElement("javac jp\\ne\\nifty\\iga\\midori\\shell\\*.java jp\\ne\\nifty\\iga\\midori\\shell\\eng\\*.java jp\\ne\\nifty\\iga\\midori\\shell\\io\\*.java jp\\ne\\nifty\\iga\\midori\\shell\\util\\*.java");
	}

	public void close()
	{
	}

	/**
	 * entry point for this class.
	 */
	public int process()
	{
		try{
			shellenv.getOut().println(MdShellDef.PRODUCT_NAME+" "+MdShellVersion.getVersion()+", "+MdShellDef.COPYRIGHT);
			for(;;)
			{
				Thread.yield();
				shellenv.getOut().print(shellenv.getCurrentDirectory().getName()+"> ");

				shellenv.clearLine();
				String strRead=shellenv.getNextLine();

				if(strRead==null)
				{
					// Next.
					continue;
				}
				try{
					if(processCommand(shellenv.getIn(),strRead))
					{
						// Finish!!!
						break;
					}
				}catch(MdShellCancelException ex){
					if(MdShellDef.IS_DEBUG)System.out.println("canceled: "+ex.toString());
					//ex.printStackTrace();
				}catch(MdShellException ex){
					if(MdShellDef.IS_DEBUG)System.out.println("exited: "+ex.toString());
					//ex.printStackTrace();
				}
			}
		}catch(IOException ex){
			shellenv.getOut().println(ex.toString());
			ex.printStackTrace();
		}
		return 0;
	}

	/**
	 * Process command.
	 * @return true menas finish.
	 */
	public boolean processCommand(InputStream inStream,String strReadLine)
		throws MdShellException,IOException
	{
		Collator collator=shellenv.getCollatorInstance();

		String strCommand=MdShellUtilString.readFirstCommandToken(strReadLine);
		if(strCommand==null)
		{
			return false;
		}

		if(collator.equals(strCommand,"!!"))
		{
			if(vecCommandHistory.size()<=0)
			{
				return false;
			}
			String strHistoryCommand=(String)vecCommandHistory.elementAt(vecCommandHistory.size()-1);
			return processCommand(inStream,strHistoryCommand);
		}
		else if(strCommand.length()>=2
		&& strCommand.charAt(0)=='!')
		{
			// It goes into history treatment.
			MdShellDefaultStringFormatter formatter=new MdShellDefaultStringFormatter();
			String strHistoryCommand=formatter.format(MdShellListSelection.selectFromList(shellenv,vecCommandHistory,formatter,strCommand.substring(1)));
			if(strHistoryCommand==null)
			{
				throw new MdShellCancelException();
			}
			return processCommand(inStream,strHistoryCommand);
		}

		// ;;;

		{
			MdShellDefaultStringFormatter formatter=new MdShellDefaultStringFormatter();
			Object objFilledCommand=MdShellListSelection.fullfillByList(shellenv,shellenv.getCommandList().getImplementedCommandList(),formatter,"^"+strCommand);
			if(objFilledCommand!=null)
			{
				strCommand=formatter.format(objFilledCommand);
			}
		}

		if(collator.equals(strCommand,"exit")
		|| collator.equals(strCommand,"quit"))
		{
			return true;
		}
		else if(collator.equals(strCommand,"exec"))
		{
			shellenv.getOut().print("input command: ");
			String strSubCommand=shellenv.getNextLine();
			if(strSubCommand==null)
			{
				throw new MdShellCancelException();
			}

			if(collator.equals(strSubCommand,""))
			{
				showCommandHistory();
				shellenv.getOut().print("select command: ");
				MdShellDefaultStringFormatter formatter=new MdShellDefaultStringFormatter();
				strSubCommand=formatter.format(MdShellListSelection.selectFromList(shellenv,vecCommandHistory,formatter,shellenv.getNextLine()));
				if(strSubCommand==null)
				{
					throw new MdShellCancelException();
				}
				shellenv.getOut().println("get from history ["+strSubCommand+"]");
			}
			else
			{
				strSubCommand=shellenv.getOriginalReadLine();
			}

			MdShellUtilExec.exec(shellenv,strSubCommand);
			//shellenv.closeChildProcessInputStream();
		}
		else if(collator.equals(strCommand,"history")
		     || collator.equals(strCommand,"!"))
		{
			showCommandHistory();
		}
		else if(collator.equals(strCommand,"menu"))
		{
			Vector vecMenu=shellenv.getCommandList().getFilteredCommandListForDisplay();
			Vector vecMenuCommand=shellenv.getCommandList().getFilteredCommandList();

			MdShellListSelection.showVectorListWithNumberAndString(shellenv,vecMenu,new MdShellDefaultStringFormatter());
			shellenv.getOut().print("select menu: ");
			MdShellDefaultStringFormatter formatter=new MdShellDefaultStringFormatter();
			String strMenu=formatter.format(MdShellListSelection.selectFromList(shellenv,vecMenuCommand,formatter,shellenv.getNextLine()));
			if(strMenu!=null)
			{
				return processCommand(inStream,strMenu);
			}
		}
		else if(shellenv.getCommandList().processCommand(shellenv,strCommand))
		{
			// It has already disposed of it in the if sentence. Nothing is done. 
			// The treatment that varies very much in this if sentence is done.
		}
		else
		{
			if(collator.equals(strCommand,""))
			{
				//showCommandHistory();
				return false;
			}

			MdShellUtilExec.exec(shellenv,shellenv.getOriginalReadLine());
		}

		// It is this, for the first time, history memory.
		vecCommandHistory.addElement(strReadLine);

		return false;
	}

	/**
	 * Show command history.
	 */
	public void showCommandHistory()
	{
		MdShellListSelection.showVectorListWithNumberAndString(shellenv,vecCommandHistory,new MdShellDefaultStringFormatter());
	}
}


