package com.github.aureliano.evtbridge.app.helper;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.github.aureliano.evtbridge.app.command.Commands;
import com.github.aureliano.evtbridge.app.command.HelpCommand;
import com.github.aureliano.evtbridge.app.command.ICommand;
import com.github.aureliano.evtbridge.app.command.VersionCommand;
import com.github.aureliano.evtbridge.common.helper.StringHelper;
import com.github.aureliano.evtbridge.converter.ConfigurationSourceType;

import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

public final class CliHelper {

	private CliHelper() {}
	
	public static String supportedFileTypes() {
		ConfigurationSourceType[] availableTypes = ConfigurationSourceType.values();
		List<String> types = new ArrayList<String>(availableTypes.length);
		
		for (ConfigurationSourceType type : ConfigurationSourceType.values()) {
			types.add(type.name().toLowerCase());
		}
		
		return StringHelper.join(types, ", ");
	}
	
	public static ICommand buildCommand(String[] args) {
		final String unknownCommand = "Don't know how to handle the command: " + StringHelper.join(args, " ");
		
		OptionParser parser = parseOptions();
		OptionSpec<String> nonOptions = parser.nonOptions().ofType(String.class);
		OptionSet options = parser.parse(args);
		
		List<String> command = nonOptions.values(options);
		ICommand commandExecutor = null;
		
		if (command.isEmpty()) {
			commandExecutor = buildLooseCommands(options);
		} else {
			commandExecutor = buildAppCommand(options, command);
		}
		
		if (commandExecutor == null) {
			System.err.println(unknownCommand);
		}
		
		return commandExecutor;
	}
	
	protected static OptionParser parseOptions() {
		OptionParser parser = new OptionParser();
		
		parser.accepts("help", "Show this message");
		parser.accepts("version", "Show project version");
		parser.nonOptions().ofType(File.class);
		
		return parser;
	}
	
	protected static ICommand buildCommand(String[] args, OptionSet options) {
		if (options.has("help")) {
			return new HelpCommand();
		} else if (options.has("version")) {
			return new VersionCommand();
		}
		
		System.err.println("Don't know how to handle the command: " + StringHelper.join(args, " "));
		return null;
	}
	
	private static ICommand buildAppCommand(OptionSet options, List<String> command) {
		if (Commands.HELP.getId().equals(command.get(0))) {
			return help(command);
		} else if (Commands.VERSION.getId().equals(command.get(0))) {
			return version(command);
		}
		
		return null;
	}
	
	private static ICommand buildLooseCommands(OptionSet options) {
		if (options.has("help")) {
			return new HelpCommand();
		} else if (options.has("version")) {
			return new VersionCommand();
		}
		
		return null;
	}
	
	private static ICommand help(List<String> command) {
		if (command.size() > 2) {
			return null;
		} else if (command.size() == 1) {
			return new HelpCommand();
		}
		
		return new HelpCommand().withCommand(command.get(1));
	}
	
	private static ICommand version(List<String> command) {
		if (command.size() > 1) {
			return null;
		}
		
		return new VersionCommand();
	}
}
@@ -293,32 +293,99 @@
 mmand.ICommand;%0A
+import com.github.aureliano.evtbridge.app.command.SchemataCommand;%0A
 import com.githu
@@ -1875,22 +1875,37 @@
 accepts(
-%22help%22
+Commands.HELP.getId()
 , %22Show 
@@ -1937,25 +1937,40 @@
 accepts(
-%22version%22
+Commands.VERSION.getId()
 , %22Show 
@@ -1984,24 +1984,108 @@
  version%22);%0A
+%09%09parser.accepts(Commands.SCHEMATA.getId(), %22List all configuration schema names%22);%0A
 %09%09parser.non
@@ -2225,38 +2225,53 @@
 if (options.has(
-%22help%22
+Commands.HELP.getId()
 )) %7B%0A%09%09%09return n
@@ -2309,33 +2309,48 @@
 options.has(
-%22version%22
+Commands.VERSION.getId()
 )) %7B%0A%09%09%09retu
@@ -2366,32 +2366,120 @@
 rsionCommand();%0A
+%09%09%7D else if (options.has(Commands.SCHEMATA.getId())) %7B%0A%09%09%09return new SchemataCommand();%0A
 %09%09%7D%0A%09%09%0A%09%09System.
@@ -2831,32 +2831,126 @@
 rsion(command);%0A
+%09%09%7D else if (Commands.SCHEMATA.getId().equals(command.get(0))) %7B%0A%09%09%09return schemata(command);%0A
 %09%09%7D%0A%09%09%0A%09%09return 
@@ -3047,14 +3047,29 @@
 has(
-%22help%22
+Commands.HELP.getId()
 )) %7B
@@ -3127,17 +3127,32 @@
 has(
-%22version%22
+Commands.VERSION.getId()
 )) %7B
@@ -3176,32 +3176,120 @@
 rsionCommand();%0A
+%09%09%7D else if (options.has(Commands.SCHEMATA.getId())) %7B%0A%09%09%09return new SchemataCommand();%0A
 %09%09%7D%0A%09%09%0A%09%09return 
@@ -3672,9 +3672,155 @@
 d();%0A%09%7D%0A
+%09%0A%09private static ICommand schemata(List%3CString%3E command) %7B%0A%09%09if (command.size() %3E 1) %7B%0A%09%09%09return null;%0A%09%09%7D%0A%09%09%0A%09%09return new SchemataCommand();%0A%09%7D%0A
 %7D

Create schemata command interface.