package com.dokukino.genkidama;

import java.io.PrintStream;
import java.util.List;
import java.util.Map;

import ow.dht.DHT;
import ow.tool.dhtshell.commands.ClearCommand;
import ow.tool.dhtshell.commands.GetCommand;
import ow.tool.dhtshell.commands.HaltCommand;
import ow.tool.dhtshell.commands.HelpCommand;
import ow.tool.dhtshell.commands.InitCommand;
import ow.tool.dhtshell.commands.LocaldataCommand;
import ow.tool.dhtshell.commands.PutCommand;
import ow.tool.dhtshell.commands.QuitCommand;
import ow.tool.dhtshell.commands.RemoveCommand;
import ow.tool.dhtshell.commands.ResumeCommand;
import ow.tool.dhtshell.commands.SetSecretCommand;
import ow.tool.dhtshell.commands.SetTTLCommand;
import ow.tool.dhtshell.commands.StatusCommand;
import ow.tool.dhtshell.commands.SuspendCommand;
import ow.tool.util.shellframework.Command;
import ow.tool.util.shellframework.MessagePrinter;
import ow.tool.util.shellframework.Shell;
import ow.tool.util.shellframework.ShellServer;

@SuppressWarnings("unchecked")
public class DHTShellServer {
	private final static int SHELL_PORT = -1;
	private final static Class[] COMMANDS = {
			StatusCommand.class, InitCommand.class, GetCommand.class,
			PutCommand.class, RemoveCommand.class, SetTTLCommand.class,
			SetSecretCommand.class, LocaldataCommand.class,
			// SourceCommand.class,
			HelpCommand.class, QuitCommand.class, HaltCommand.class,
			ClearCommand.class, SuspendCommand.class, ResumeCommand.class };

	private final static List<Command<DHT<String>>> commandList = ShellServer.createCommandList(COMMANDS);
	private final static Map<String, Command<DHT<String>>> commandTable = ShellServer.createCommandTable(commandList);

	public static void start(DHT<String> dht) {
		// start a ShellServer
		ShellServer<DHT<String>> shellServ = new ShellServer<DHT<String>>(
				commandTable, commandList, new ShowPromptPrinter(),
				new NoCommandPrinter(), null, dht, SHELL_PORT, null);

		Shell<DHT<String>> stdioShell = new Shell<DHT<String>>(
				System.in, System.out, shellServ, dht, true);
		Thread shellThread = new Thread(stdioShell);
		shellThread.start();
	}
	
	private static class ShowPromptPrinter implements MessagePrinter {
		public void execute(PrintStream out, String hint) {
			out.print("Ready." + Shell.CRLF);
			out.flush();
		}
	}

	private static class NoCommandPrinter implements MessagePrinter {
		public void execute(PrintStream out, String hint) {
			out.print("No such command");

			if (hint != null)
				out.print(": " + hint);
			else
				out.print(".");
			out.print(Shell.CRLF);

			out.flush();
		}
	}
}
