package org.ultramine.mods.hawkeye;

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

import org.ultramine.commands.CommandContext;
import org.ultramine.commands.HandlerBasedCommand;
import org.ultramine.commands.ICommandHandler;
import org.ultramine.mods.hawkeye.commands.BaseCommand;
import org.ultramine.mods.hawkeye.commands.DeleteCommand;
import org.ultramine.mods.hawkeye.commands.HelpCommand;
import org.ultramine.mods.hawkeye.commands.HereCommand;
import org.ultramine.mods.hawkeye.commands.PageCommand;
import org.ultramine.mods.hawkeye.commands.PreviewApplyCommand;
import org.ultramine.mods.hawkeye.commands.PreviewCancelCommand;
import org.ultramine.mods.hawkeye.commands.PreviewCommand;
import org.ultramine.mods.hawkeye.commands.RebuildCommand;
import org.ultramine.mods.hawkeye.commands.RollbackCommand;
import org.ultramine.mods.hawkeye.commands.SearchCommand;
import org.ultramine.mods.hawkeye.commands.ToolBindCommand;
import org.ultramine.mods.hawkeye.commands.ToolCommand;
import org.ultramine.mods.hawkeye.commands.ToolResetCommand;
import org.ultramine.mods.hawkeye.commands.TptoCommand;
import org.ultramine.mods.hawkeye.commands.UndoCommand;
import org.ultramine.mods.hawkeye.database.DataManager;
import org.ultramine.mods.hawkeye.listeners.MonitorBlockListener;
import org.ultramine.mods.hawkeye.listeners.MonitorEntityListener;
import org.ultramine.mods.hawkeye.listeners.MonitorPlayerListener;
import org.ultramine.mods.hawkeye.listeners.ToolListener;
import org.ultramine.mods.hawkeye.util.HawkUtil;
import org.ultramine.server.ConfigurationHandler;
import org.ultramine.server.util.BasicTypeParser;
import org.ultramine.server.util.ItemStackHashSet;
import org.ultramine.server.util.YamlConfigProvider;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLModIdMappingEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppedEvent;
import net.minecraft.block.Block;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.MinecraftForge;

@Mod(modid = "HawkEye", name = "HawkEye", version = "1.0.7b", acceptableRemoteVersions = "*")
public class HawkEye implements ICommandHandler
{
	public static HawkEye instance;

	public HawkConfig config;
	public MonitorBlockListener monitorBlockListener = new MonitorBlockListener();
	public MonitorEntityListener monitorEntityListener = new MonitorEntityListener();
	public MonitorPlayerListener monitorPlayerListener = new MonitorPlayerListener();
	public ToolListener toolListener = new ToolListener();
	public static List<BaseCommand> commands = new ArrayList<BaseCommand>();
	//public static WorldEditPlugin worldEdit = null;
	public static ContainerAccessManager containerManager;
	
	private final ItemStackHashSet blockFilter = new ItemStackHashSet();

	@EventHandler
	public void init(FMLInitializationEvent ev)
	{
		instance = this;

		if(ev.getSide().isClient())
			return;
		HawkUtil.info("Starting HawkEye initiation process...");

		File configFile = new File(ConfigurationHandler.getSettingDir(), "hawkeye.yml");
		if(configFile.exists())
		{
			config = YamlConfigProvider.readConfig(configFile, HawkConfig.class);
		}
		else
		{
			System.out.println("No config foud"); //create here
			return;
		}
		
		new SessionManager();

		//Initiate database connection
		try
		{
			new DataManager(this);
		}
		catch(Exception e)
		{
			HawkUtil.error("Error initiating HawkEye database connection, disabling logging", e);
			return;
		}

		containerManager = new ContainerAccessManager();
		registerListeners();
		registerCommands();
	}

	@EventHandler
	public void start(FMLServerStartingEvent e)
	{
		e.registerCommand(
			new HandlerBasedCommand.Builder("hawk", "hawkeye", this)
			.setAliases("hawkeye", "he", "hk", "ha")
			.setPermissions("hawkeye.search", "hawkeye.tpto", "hawkeye.rollback", "hawkeye.tool", "hawkeye.notify", "hawkeye.preview", "hawkeye.page", "hawkeye.tool.bind")
			.build());
	}
	
	@EventHandler
	public void stop(FMLServerStoppedEvent e)
	{
		DataManager.close();
	}
	
	@EventHandler
	public void remap(FMLModIdMappingEvent e)
	{
		for(String str : config.blockFilter)
		{
			try
			{
				blockFilter.add(BasicTypeParser.parseStackType(str));
			} catch(Exception ignored){}
		}
	}

	private void registerListeners()
	{
		MinecraftForge.EVENT_BUS.register(monitorBlockListener);
		MinecraftForge.EVENT_BUS.register(monitorPlayerListener);
		FMLCommonHandler.instance().bus().register(monitorPlayerListener);
		MinecraftForge.EVENT_BUS.register(monitorEntityListener);
		MinecraftForge.EVENT_BUS.register(toolListener);
	}

	private void registerCommands()
	{
		//Add commands
		commands.add(new HelpCommand());
		commands.add(new ToolBindCommand());
		commands.add(new ToolResetCommand());
		commands.add(new ToolCommand());
		commands.add(new SearchCommand());
		commands.add(new PageCommand());
		commands.add(new TptoCommand());
		commands.add(new HereCommand());
		commands.add(new PreviewApplyCommand());
		commands.add(new PreviewCancelCommand());
		commands.add(new PreviewCommand());
		commands.add(new RollbackCommand());
//		if (worldEdit != null) commands.add(new WorldEditRollbackCommand());
		commands.add(new UndoCommand());
		commands.add(new RebuildCommand());
		commands.add(new DeleteCommand());

	}

	@Override
	public void processCommand(CommandContext ctx)
	{
		String[] args = ctx.getArgs();
		if(args.length == 0)
		{
			args = new String[] { "help" };
		}

		outer:
		for(BaseCommand command : commands)
		{
			String[] cmds = command.name.split(" ");
			for(int i = 0; i < cmds.length; i++)
			{
				if(i >= args.length || !cmds[i].equalsIgnoreCase(args[i]))
				{
					continue outer;
				}
			}

			command.run(this, ctx.getSender(), args, ctx.getCommand().getCommandName());
			return;
		}

		commands.get(0).run(this, ctx.getSender(), args, ctx.getCommand().getCommandName());
	}

	public HawkConfig getConfig()
	{
		return config;
	}

	public static WorldServer getWorld(int id)
	{
		return MinecraftServer.getServer().getMultiWorld().getWorldByID(id);
	}
	
	public boolean isBlockFiltered(Block block, int meta)
	{
		return blockFilter.contains(block, meta);
	}
}
