package net.minecraft.src;

import java.util.*;
import org.lwjgl.input.Keyboard;

import net.minecraft.client.Minecraft;

/**
 * powerCraft's Mobile module<br>
 * Provides power crystals (+generation), miner, activation crystal, power dust,
 * fishing machine and ore sniffer.
 * 
 * @author MightyPork
 * @copy (c) 2012
 * 
 */
public class mod_PCmobile extends BaseMod {
	/**
	 * Textures folder for this module, ending with slash.
	 */
	public static String imgDir = "/PowerCraft/mobile/";

	/**
	 * Configuration file
	 */
	public static PCMP conf = new PCMP("/config/PC_MOBILE.properties", "PowerCraft mobile [vehicles] plugin - setup file\n");


	@Override
	public String getPriorities() {
		return "after:mod_PCcore";
	}


	@Override
	public String getVersion() {
		return mod_PCcore.VERSION;
	}

	static {
		conf.put("ITEM_Activator", 19001, PCMPType.ITEM);
		conf.put("ITEM_PowerDust", 19002, PCMPType.ITEM);
		conf.put("ITEM_OreSniffer", 19004, PCMPType.ITEM);
		conf.put("BLOCK_PowerCrystal", 232, PCMPType.BLOCK);

		conf.put("WORLDGEN_PowerCrystal_Enabled", true, PCMPType.BOOL);
		conf.put("RECIPES_EasyCrystals_Enabled", false, PCMPType.BOOL);

		conf.put("KEY_Forward", Keyboard.KEY_NUMPAD8, PCMPType.KEY);
		conf.put("KEY_Left", Keyboard.KEY_NUMPAD4, PCMPType.KEY);
		conf.put("KEY_Right", Keyboard.KEY_NUMPAD6, PCMPType.KEY);
		conf.put("KEY_Backward", Keyboard.KEY_NUMPAD2, PCMPType.KEY);
		conf.put("KEY_TurnAround", Keyboard.KEY_NUMPAD5, PCMPType.KEY);
		conf.put("KEY_Down", Keyboard.KEY_SUBTRACT, PCMPType.KEY);
		conf.put("KEY_Up", Keyboard.KEY_ADD, PCMPType.KEY);

		conf.put("KEY_BridgeOn", Keyboard.KEY_O, PCMPType.KEY);
		conf.put("KEY_BridgeOff", Keyboard.KEY_P, PCMPType.KEY);
		conf.put("KEY_RunProgramNEW", Keyboard.KEY_NUMPADENTER, PCMPType.KEY);

		conf.put("KEY_Deposit", Keyboard.KEY_DECIMAL, PCMPType.KEY);
		conf.put("KEY_TurnIntoBlocks", Keyboard.KEY_NUMPAD1, PCMPType.KEY);
		conf.put("KEY_MiningOn", Keyboard.KEY_NUMPAD7, PCMPType.KEY);
		conf.put("KEY_MiningOff", Keyboard.KEY_NUMPAD9, PCMPType.KEY);

		conf.put("KEY_CancelOp", Keyboard.KEY_DELETE, PCMPType.KEY);
		conf.put("crystal_BRIGHTNESS", 15, PCMPType.INT);

		conf.apply();
	}

	/** Activation Crystal item */
	public static Item activator = new PCmo_ItemActivator(conf.getInt("ITEM_Activator")).setIconIndex(37).setItemName("PCmoActivatorItem");

	/** Power Dust item (fuel) */
	public static Item powerDust = new PCmo_ItemPowerDust(conf.getInt("ITEM_PowerDust")).setIconCoord(13, 9).setItemName("PCmoPowerDust");

	/** Ore Sniffer item */
	public static Item oreSniffer = new PCmo_ItemOreSniffer(conf.getInt("ITEM_OreSniffer")).setIconIndex(37).setItemName("PCmoOreSnifferItem");

	/** Power Crystal block */
	public static Block powerCrystal = new PCmo_BlockPowerCrystal(conf.getInt("BLOCK_PowerCrystal"), 49).setHardness(0.5F).setResistance(0.5F).setBlockName("PCmoPowerCrystal")
			.setStepSound(Block.soundGlassFootstep).setLightValue(conf.getInt("crystal_BRIGHTNESS") * 0.0625F);


	@Override
	public int addFuel(int i, int j) {
		return (i == powerDust.shiftedIndex) ? 2200 : 0;
	}

	public static int rendererCrystal = 0;


	public mod_PCmobile() {
	}


	@Override
	public void load() {

		// init names from a file
		((PCmo_ItemOreSniffer) oreSniffer).initNames();

		// preload textures
		Minecraft mc = ModLoader.getMinecraftInstance();

		mc.renderEngine.getTexture(imgDir + "tiles.png");
		mc.renderEngine.getTexture(imgDir + "gui_miner.png");
		mc.renderEngine.getTexture(imgDir + "miner_base.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_1.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_2.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_3.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_4.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_5.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_6.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_7.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_8.png");
		mc.renderEngine.getTexture(imgDir + "miner_overlay_keyboard.png");

		mc.renderEngine.getTexture(imgDir + "fisher.png");

		activator.setIconIndex(ModLoader.addOverride("/gui/items.png", imgDir + "activator.png"));
		oreSniffer.setIconIndex(ModLoader.addOverride("/gui/items.png", imgDir + "sniffer.png"));

		rendererCrystal = ModLoader.getUniqueBlockModelID(this, true);

		ModLoader.setInGameHook(this, true, true);

		ModLoader.addName(activator, "Activation Crystal");
		ModLoader.addName(powerCrystal, "Power Crystal");
		ModLoader.addName(powerDust, "Power Dust");
		ModLoader.addName(oreSniffer, "Ore Sniffer");

		ModLoader.registerBlock(powerCrystal);
		Item.itemsList[powerCrystal.blockID] = null;
		Item.itemsList[powerCrystal.blockID] = (new PCmo_ItemBlockPowerCrystal(powerCrystal.blockID - 256)).setItemName("PCmoPowerCrystal");

		ModLoader.registerEntityID(net.minecraft.src.PCmo_EntityMiner.class, "PCmo_Miner", ModLoader.getUniqueEntityId());
		ModLoader.registerEntityID(net.minecraft.src.PCmo_EntityFishingMachine.class, "PCmo_FishingMachine", ModLoader.getUniqueEntityId());

		if (conf.getBool("RECIPES_EasyCrystals_Enabled")) {
			ModLoader.addSmelting(Item.diamond.shiftedIndex, new ItemStack(powerCrystal, 1));
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 1), new Object[] { new ItemStack(powerCrystal, 1, 0) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 2), new Object[] { new ItemStack(powerCrystal, 1, 1) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 3), new Object[] { new ItemStack(powerCrystal, 1, 2) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 4), new Object[] { new ItemStack(powerCrystal, 1, 3) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 5), new Object[] { new ItemStack(powerCrystal, 1, 4) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 6), new Object[] { new ItemStack(powerCrystal, 1, 5) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 7), new Object[] { new ItemStack(powerCrystal, 1, 6) });
			ModLoader.addShapelessRecipe(new ItemStack(powerCrystal, 1, 0), new Object[] { new ItemStack(powerCrystal, 1, 7) });
			ModLoader.addShapelessRecipe(new ItemStack(powerDust, 48, 0), new Object[] { new ItemStack(powerCrystal, 1, -1), new ItemStack(powerCrystal, 1, -1) });
		} else {
			ModLoader.addShapelessRecipe(new ItemStack(powerDust, 24, 0), new Object[] { new ItemStack(powerCrystal, 1, -1) });
		}

		ModLoader.addRecipe(new ItemStack(oreSniffer, 1, 0),
				new Object[] { " G ", "GCG", " G ", Character.valueOf('C'), new ItemStack(powerCrystal, 1, -1), Character.valueOf('G'), Item.ingotGold });

		ModLoader.addRecipe(new ItemStack(activator, 1), new Object[] { "C", "I", Character.valueOf('C'), new ItemStack(powerCrystal, 1, -1), Character.valueOf('I'), Item.ingotIron });

		ModLoader.addLocalization("tile.PCmoPowerCrystal.color0.name", "\u03b1 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color1.name", "\u03b2 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color2.name", "\u03b3 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color3.name", "\u03b4 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color4.name", "\u03d1 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color5.name", "\u03b6 Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color6.name", "\u03be Power Crystal");
		ModLoader.addLocalization("tile.PCmoPowerCrystal.color7.name", "\u03d7 Power Crystal");

		// TMI
		net.minecraft.src.PCco_Utils.TMI_rangeDamage(powerCrystal.blockID, 0, 7);
	}


	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void addRenderer(Map map) {
		map.put(PCmo_EntityMiner.class, new PCmo_RenderMiner());
		map.put(PCmo_EntityFishingMachine.class, new PCmo_RenderFishingMachine());
	}


	@Override
	public boolean renderWorldBlock(RenderBlocks renderblocks, IBlockAccess iblockaccess, int i, int j, int k, Block block, int renderType) {
		RenderEngine renderengine = ModLoader.getMinecraftInstance().renderEngine;
		Tessellator tessellator = Tessellator.instance;
		if (renderType == rendererCrystal && block instanceof PCco_ISwapTerrain) {
			tessellator.draw();
			tessellator.startDrawingQuads();
			renderengine.bindTexture(renderengine.getTexture(((PCco_ISwapTerrain) block).getTerrainFile()));

			boolean gf = RenderBlocks.cfgGrassFix;
			RenderBlocks.cfgGrassFix = false;

			Random posRand = new Random(i + i * j * k + k + iblockaccess.getBlockMetadata(i, j, k));

			for (int q = 3 + posRand.nextInt(2); q > 0; q--) {
				float x, y, z, a, b, c;

				x = posRand.nextFloat() * 0.6F;
				y = (q == 2 ? 0.001F : posRand.nextFloat() * 0.6F);
				z = posRand.nextFloat() * 0.6F;

				a = x + 0.3F + posRand.nextFloat() * (0.7F - x);
				b = y + 0.3F + posRand.nextFloat() * (0.7F - y);
				c = z + 0.3F + posRand.nextFloat() * (0.7F - z);

				block.setBlockBounds(x, y, z, a, b, c);
				renderblocks.renderStandardBlock(block, i, j, k);
			}
			block.setBlockBounds(0, 0, 0, 1, 1, 1);

			RenderBlocks.cfgGrassFix = gf;

			tessellator.draw();
			tessellator.startDrawingQuads();
			renderengine.bindTexture(renderengine.getTexture("/terrain.png"));

			return true;
		}
		return false;
	}


	@Override
	public void renderInvBlock(RenderBlocks renderblocks, Block block, int i, int rtype) {
		RenderEngine renderengine = ModLoader.getMinecraftInstance().renderEngine;

		if (rtype == rendererCrystal) {
			renderengine.bindTexture(renderengine.getTexture(((PCco_ISwapTerrain) block).getTerrainFile()));

			Random posRand = new Random(i);

			for (int q = 3 + posRand.nextInt(3); q > 0; q--) {
				float x, y, z, a, b, c;
				x = 0.0F + posRand.nextFloat() * 0.6F;
				y = 0.0F + posRand.nextFloat() * 0.6F;
				z = 0.0F + posRand.nextFloat() * 0.6F;

				a = 0.2F + Math.max(posRand.nextFloat() * (0.7F - x), 0.3F);
				b = 0.2F + Math.max(posRand.nextFloat() * (0.7F - y), 0.3F);
				c = 0.2F + Math.max(posRand.nextFloat() * (0.7F - z), 0.3F);

				block.setBlockBounds(x, y, z, x + a, y + b, z + c);
				PCco_Renderer.renderInvBox(renderblocks, block, i);
			}
			block.setBlockBounds(0, 0, 0, 1, 1, 1);
			renderengine.bindTexture(renderengine.getTexture("/terrain.png"));

			return;
		}
	}


	@Override
	public void generateSurface(World world, Random random, int chunkX, int chunkZ) {
		if (!conf.getBoolean("WORLDGEN_PowerCrystal_Enabled")) return;

		int posX;
		int posY;
		int posZ;

		for (int q = 0; q < 4; q++) {
			int maxBlocks = random.nextInt(3) + 2;

			posX = chunkX + random.nextInt(16);
			posY = random.nextInt(10) + 6;
			posZ = chunkZ + random.nextInt(16);

			new WorldGenMinable(powerCrystal.blockID, maxBlocks).generate(world, random, posX, posY, posZ);
		}
	}

	// Miner control stuff

	/** list of keyboard controlled miners */
	public static List<PCmo_EntityMiner> controlledMiners = new ArrayList<PCmo_EntityMiner>();

	private static World lastKCWorld = null;


	/**
	 * Add this Miner to list of keyboard-controlled
	 * 
	 * @param miner
	 *            the miner entity
	 * @param silent
	 *            don't show chat message
	 */
	public static void setMinerForKeyboardControl(PCmo_EntityMiner miner, boolean silent) {
		lastKCWorld = ModLoader.getMinecraftInstance().theWorld;
		if (!controlledMiners.contains(miner)) controlledMiners.add(miner);

		if (!silent) PCco_Utils.chatMsg("Miner " + miner.level + " connected to keyboard.", true);
	}


	/**
	 * Remove this Miner from list of keyboard-controlled
	 * 
	 * @param miner
	 *            the miner entity
	 * @param silent
	 *            don't show chat message
	 */
	public static void disconnectMinerFromKeyboardControl(PCmo_EntityMiner miner, boolean silent) {
		lastKCWorld = ModLoader.getMinecraftInstance().theWorld;
		if (controlledMiners.contains(miner)) controlledMiners.remove(miner);

		if (!silent) PCco_Utils.chatMsg("Miner " + miner.level + " disconnected from keyboard.", true);
	}

	/** cooldown timer for repeated keypresses */
	private static int[] keyPressTimer = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	/** number of ticks before the key is accepted again */
	private static final int CooldownTime = 8;


	@Override
	public boolean onTickInGame(float f, Minecraft minecraft) {
		if (lastKCWorld != ModLoader.getMinecraftInstance().theWorld) {
			controlledMiners.clear();
			lastKCWorld = ModLoader.getMinecraftInstance().theWorld;
		}

		if (ModLoader.getMinecraftInstance().currentScreen != null) return true;
		// keyboard control

		for (int i = 0; i <= 8; i++) {
			if (keyPressTimer[i] > 0) keyPressTimer[i]--;
		}

		if (ModLoader.getMinecraftInstance().theWorld != null && lastKCWorld == ModLoader.getMinecraftInstance().theWorld) {
			if (conf.isKeyDown("KEY_Forward")) {
				if (keyPressTimer[0] == 0) {
					keyPressTimer[0] = CooldownTime;
					sendCommandToMiners(PCmo_Command.FORWARD);
				}
				return true;
			}
			if (conf.isKeyDown("KEY_Left")) {
				if (keyPressTimer[1] == 0) {
					keyPressTimer[1] = CooldownTime;
					sendCommandToMiners(PCmo_Command.LEFT);
				}
				return true;
			}
			if (conf.isKeyDown("KEY_Right")) {
				if (keyPressTimer[2] == 0) {
					keyPressTimer[2] = CooldownTime;
					sendCommandToMiners(PCmo_Command.RIGHT);
				}
				return true;
			}
			if (conf.isKeyDown("KEY_TurnAround")) {
				if (keyPressTimer[3] == 0) {
					keyPressTimer[3] = CooldownTime;
					sendSequenceToMiners("RR");
				}
				return true;
			}
			if (conf.isKeyDown("KEY_Backward")) {
				if (keyPressTimer[4] == 0) {
					keyPressTimer[4] = CooldownTime;
					sendCommandToMiners(PCmo_Command.BACKWARD);
				}
				return true;
			}

			if (conf.isKeyDown("KEY_Down")) {
				if (keyPressTimer[5] == 0) {
					keyPressTimer[5] = CooldownTime;
					sendCommandToMiners(PCmo_Command.DOWN);
				}
				return true;
			}
			if (conf.isKeyDown("KEY_Up")) {
				if (keyPressTimer[6] == 0) {
					keyPressTimer[6] = CooldownTime;
					sendCommandToMiners(PCmo_Command.UP);
				}
				return true;
			}

			if (conf.isKeyDown("KEY_BridgeOn")) {
				if (sendCommandToMiners(PCmo_Command.BRIDGE_ENABLE)) PCco_Utils.chatMsg("Bridge building enabled.", true);
				return true;
			}

			if (conf.isKeyDown("KEY_BridgeOff")) {
				if (sendCommandToMiners(PCmo_Command.BRIDGE_DISABLE)) PCco_Utils.chatMsg("Bridge building disabled.", true);
				return true;
			}

			if (conf.isKeyDown("KEY_Deposit")) {
				if (keyPressTimer[7] == 0) {
					keyPressTimer[7] = CooldownTime;
					sendCommandToMiners(PCmo_Command.DEPOSIT);
				}
				return true;
			}

			if (conf.isKeyDown("KEY_RunProgramNEW")) {
				if (keyPressTimer[8] == 0) {
					keyPressTimer[8] = CooldownTime;
					if (sendSafelyUrgentCommandToMiners(PCmo_Command.RUN_PROGRAM)) PCco_Utils.chatMsg("Miners launched and disconnected.", true);
				}
				return true;
			}

			if (conf.isKeyDown("KEY_TurnIntoBlocks")) {
				sendUrgentCommandToMiners(PCmo_Command.DISASSEMBLY);
				return true;
			}

			if (conf.isKeyDown("KEY_MiningOn")) {
				if (sendCommandToMiners(PCmo_Command.MINING_ENABLE)) PCco_Utils.chatMsg("Mining enabled.", true);
				return true;
			}

			if (conf.isKeyDown("KEY_MiningOff")) {
				if (sendCommandToMiners(PCmo_Command.MINING_DISABLE)) PCco_Utils.chatMsg("Mining disabled.", true);
				return true;
			}

			if (conf.isKeyDown("KEY_CancelOp")) {
				if (sendUrgentCommandToMiners(PCmo_Command.RESET)) PCco_Utils.chatMsg("All operations cancelled.", true);
				return true;
			}
		}
		return true;
	}


	/**
	 * Send given command to all connected miners<br>
	 * Some miners may reject it.
	 * 
	 * @param cmd
	 *            command index
	 * @return true if at least one miner accepted it
	 */
	private boolean sendCommandToMiners(int cmd) {
		boolean flag = false;
		for (PCmo_EntityMiner miner : controlledMiners) {
			if (miner.readyForKeyboardCommand()) {
				flag = true;
				miner.sendKeyboardCommand(cmd);
			}
		}
		return flag;
	}


	/**
	 * Send urgent command to all connected miners.<br>
	 * Miners will do their best top accept it
	 * 
	 * @param cmd
	 *            command index
	 * @return true if at least one miner accepted it
	 */
	private boolean sendUrgentCommandToMiners(int cmd) {
		boolean flag = false;
		for (PCmo_EntityMiner miner : controlledMiners) {
			if (miner.readyForUrgentKeyboardCommand()) {
				flag = true;
				miner.sendKeyboardCommand(cmd);
			}
		}
		return flag;
	}


	/**
	 * Send urgent command to all connected miners.<br>
	 * This method works for commands that involve disconnecting from keyboard
	 * control.
	 * 
	 * @param cmd
	 *            command index
	 * @return true if at least one miner accepted it
	 */
	private boolean sendSafelyUrgentCommandToMiners(int cmd) {
		boolean flag = false;

		List<PCmo_EntityMiner> controlled2 = new ArrayList<PCmo_EntityMiner>();

		for (PCmo_EntityMiner miner : controlledMiners) {
			controlled2.add(miner);
		}

		for (PCmo_EntityMiner miner : controlled2) {
			if (miner.readyForUrgentKeyboardCommand()) {
				flag = true;
				miner.sendKeyboardCommand(cmd);
			}
		}
		return flag;
	}


	/**
	 * Send command sequence to all connected miners
	 * 
	 * @param seq
	 *            String with command characters
	 * @return true if at least one miner accepted it
	 */
	private boolean sendSequenceToMiners(String seq) {
		boolean flag = false;
		for (PCmo_EntityMiner miner : controlledMiners) {
			if (miner.readyForKeyboardCommand()) {
				flag = true;
				try {
					miner.appendCode(seq);
				} catch (PCmo_CommandException ce) {
					System.out.println("Error in keybd command!");
					return false;
				}
			}
		}
		return flag;
	}
}
