package org.postgresforest.tool.cli;

import java.sql.SQLException;

import org.postgresforest.tool.Logger;
import org.postgresforest.tool.cli.action.BrokenLogActions;
import org.postgresforest.tool.cli.action.ConfigActions;
import org.postgresforest.tool.cli.action.DbActions;
import org.postgresforest.tool.cli.action.GscActions;
import org.postgresforest.tool.cli.action.HashActions;
import org.postgresforest.tool.cli.action.HelpActions;
import org.postgresforest.tool.cli.action.InstanceActions;
import org.postgresforest.tool.cli.action.TableActions;
import org.postgresforest.tool.lib.GSCdata;
import org.postgresforest.tool.util.CommandHistory;
import org.postgresforest.tool.util.CommandParser;
import org.postgresforest.tool.util.MessagesCommandLine;
import org.postgresforest.tool.util.ReWriter;

/**
 * コマンドラインクラス コマンドの受けつけ、割り振りを行う。
 */
abstract public class AbstractCommandProcessor {

	protected GSCdata m_gsc = null;
	protected CommandHistory m_commandHistory;

	/**
	 * 
	 * @param gsc
	 */
	public AbstractCommandProcessor(GSCdata gsc) {
	
		m_gsc = gsc;
		m_commandHistory = new CommandHistory(30);
		
	}
	
	/**
	 * プロンプトの表示
	 *
	 */
	abstract protected void printPrompt();
	
	/**
	 * コマンド処理
	 * 
	 * GSCモードとUserDBモードの処理が記述される。
	 * DB　オープン/クローズで処理クラスを切り替えて返す。
	 * DB　オープン/クローズ以外は自インスタンスを返す。
	 * 
	 * @param cp	コマンド解析結果
	 * @param command	コマンド
	 * @return	次のコマンド処理クラス
	 */
	abstract protected AbstractCommandProcessor executeCommand(CommandParser cp, String command) ;

	abstract protected void processSlashCommandTable(String line) ;

	abstract protected void processSlashCommandPriority(String line) ;

	/**
	 * コマンドの実行
	 * CommandParserによるパース結果に基づいて、各ロジックに処理を割り振る。
	 * @return void
	 * @param command コマンド
	 */
	public AbstractCommandProcessor executeCommand(String command) {
		//History格納
		m_commandHistory.add(command);
		return _executeCommand(command);
	}
	/**
	 * コマンドの実行
	 * CommandParserによるパース結果に基づいて、各ロジックに処理を割り振る。
	 * @return void
	 * @param command コマンド
	 */
	protected AbstractCommandProcessor _executeCommand(String command) {

		// コマンドのパース
		CommandParser cp = null;
		try {
			command = ReWriter.toLowerSql(command);
			cp = new CommandParser(command);
		} catch (Exception e1) {
			//			System.out.println(MessagesCommandLine.getString("cui.error.parser")); //$NON-NLS-1$
			//			e1.printStackTrace();
			return this;
		}
		//環境構築コマンドタイプの取得
		int cpType = cp.getType();

		// コマンドタイプ別のパース
		if (cp.isHelpCommand()){
			HelpActions.show(cp);	
		} else if (cpType == CommandParser.SHOW_HELP){
			Logger.println(MessagesCommandLine.getString("cui.help.command.show")) ; //$NON-NLS-1$
 		} else if (cp.isHelpCommand()){
			Logger.println(MessagesCommandLine.getString("cui.help.help.show")) ; //$NON-NLS-1$
		} else {
			//コマンド実行
			return executeCommand(cp,command);
		}
		
		return this;
		
	}

	/**
	 * バックスラッシュコマンド(\q,\i,\fi,\fg\,\fu,\fc,\fh\,fb,\ft,\fp,\h)を処理する This process /
	 * commands (for now just /d)
	 * 
	 * @return void
	 * @param line
	 *            コマンドラインより入力された文字列
	 * @throws SQLException
	 * 
	 */
	public void processSlashCommand(String line) throws SQLException {

		// PostgresForest CommandLineTool用のバックスラッシュコマンド
		if (line.startsWith("\\fi")) { //$NON-NLS-1$
			// インスタンスの表示
			InstanceActions.show(m_gsc);
		} else if (line.startsWith("\\fg")) { //$NON-NLS-1$
			// GSCの表示
			GscActions.show(m_gsc);
		} else if (line.startsWith("\\fd")) { //$NON-NLS-1$
			// DBの表示
			DbActions.show(m_gsc);
		} else if (line.startsWith("\\fc")) { //$NON-NLS-1$
			// コンフィグの表示
			ConfigActions.show(m_gsc);
		} else if (line.startsWith("\\fh")) { //$NON-NLS-1$
			// ハッシュの表示
			HashActions.show(m_gsc);
		} else if (line.startsWith("\\fb")) { //$NON-NLS-1$
			// ログの表示
			BrokenLogActions.show(m_gsc);
		} else if (line.startsWith("\\ft")) { //$NON-NLS-1$
			// テーブルの表示
			processSlashCommandTable(line);
			
		} else if (line.startsWith("\\fp")) { //$NON-NLS-1$
			// 優先度の表示
			processSlashCommandPriority(line);

		
		} else {
			Logger.error(MessagesCommandLine.getString("cui.error.back.f"));
			Logger.println(MessagesCommandLine.getString("cui.help.back.f"));
		}
	}
	
	
	
	/**
	 * 
	 * @param command
	 * @return
	 */
	public AbstractCommandProcessor processSlashCommandHistory(String line) {

		if (line.startsWith("\\h ")) { //$NON-NLS-1$
			// 履歴番号取得
			String index = CommandParser.extractSlashCmdArgument(line, 3);
			if (!index.equals("")) { //$NON-NLS-1$
				int indexNum;
				try {
					indexNum = Integer.parseInt(index);
				} catch (NumberFormatException e) {
					Logger.error("Invalid argument(s).");
					Logger.error(e.getMessage());
					Logger.trace(e);
					return this;
				}
				String command = m_commandHistory.get(indexNum);
				//履歴実行
				return _executeCommand(command);
			}
		}
		
		//履歴表示
		m_commandHistory.printHistory();

		return this;
		
		
	}
	
		
	
	
	
}
