package net.minecraft.src;

import java.util.List;
import java.util.Map;
import java.util.Random;

import org.lwjgl.input.Keyboard;

/**
 * PowerCraft's core module<br>
 * This module is an integral part of PowerCraft.
 * 
 * @author MightyPork
 * @copy (c) 2012
 */
public class mod_PCcore extends PC_Module implements PC_IActivatorListener {

	/** the mod instance */
	public static mod_PCcore instance;

	/** mod version, shared by other modules */
	public static final String VERSION = "3.4";

	/**
	 * Get images directory, ending with slash
	 * 
	 * @return the directory
	 */
	public static String getImgDir() {
		return "/PowerCraft/core/";
	}

	/**
	 * Get terrain file path (png)
	 * 
	 * @return the file path
	 */
	public static String getTerrainFile() {
		return getImgDir() + "tiles.png";
	}

	// CORE must override this, others don't.
	@Override
	public String getPriorities() {
		return "before:*";
	}

	@Override
	public String getModuleName() {
		return "CORE";
	}
	
	// Add fuels.
	@Override
	public int addFuel(int i, int j) {
		return (i == powerDust.shiftedIndex) ? 2200 : 0;
	}
	
	// *** BLOCKS & ITEMS ***

	/** gate crafting tool */
	public static Item craftingTool;
	
	/** Activation Crystal item */
	public static Item activator;

	/** Power Dust item (fuel) */
	public static Item powerDust;

	/** Ore Sniffer item */
	public static PCco_ItemOreSniffer oreSniffer;

	/** Power Crystal block */
	public static Block powerCrystal;

	
	
	
	/* Property keys */

	/* settings for the crafting tool */
	/** <i>Crafting Tool</i> - recursive crafting enabled */
	public static Boolean recursive_crafting;
	/** <i>Crafting Tool</i> - cheating in survival enabled */
	public static Boolean survival_cheating;

	// property keys
	/** Key used to build in reversed direction */
	public static final String pk_ReverseKey = "key.reverse_placing";
	private static final String pk_RecRecyclation = "opt.new_recipes.recyclation";
	private static final String pk_RecSpawner = "opt.new_recipes.spawner";
	private static final String pk_craftingTool = "id.item.crafting_tool";
	private static final String pk_craft_recursive = "opt.crafting_tool.recursive";
	private static final String pk_craft_cheating = "opt.crafting_tool.cheat_in_survival";

	private static final String pk_crystalsInChunk = "opt.worldgen.crystals.in_chunk";
	private static final String pk_crystalsDepositMaxCount = "opt.worldgen.crystals.deposit_max_size";
	private static final String pk_crystalsMinY = "opt.worldgen.crystals.min_y";
	private static final String pk_crystalsMaxY = "opt.worldgen.crystals.max_y";
	private static final String pk_crystal_gen = "opt.worldgen.crystals.enabled";

	private static final String pk_crystal = "id.block.power_crystal";
	private static final String pk_ironFrame = "id.block.iron_frame";

	private static final String pk_RecEasyCrystals = "opt.cheat.easy_crystals";
	private static final String pk_crystal_brightness = "brightness.power_crystal";

	private static final String pk_iactivator = "id.item.activation_crystal";
	private static final String pk_ipowerDust = "id.item.power_dust";
	private static final String pk_isniffer = "id.item.ore_sniffer";
	
	
	
	
	@Override
	public void preInit() {
		instance = this;
	}

	@Override
	public void initProperties() {
		
		conf = new PC_PropertyManager("/config/PowerCraft/module_core.cfg", "PowerCraft CORE module\nconfiguration file");

		conf.putKey(pk_ReverseKey, Keyboard.KEY_LCONTROL);
		conf.putBoolean(pk_RecRecyclation, true);
		conf.putBoolean(pk_RecSpawner, true);
		conf.putItem(pk_craftingTool, 19003);

		conf.putItem(pk_iactivator, 19001);
		conf.putItem(pk_ipowerDust, 19002);
		conf.putItem(pk_isniffer, 19004);

		conf.putBlock(pk_crystal, 232);
		conf.putBlock(pk_ironFrame, 233);

		conf.putBoolean(pk_crystal_gen, true, "Generate Power Crystals in the world?");
		conf.putInteger(pk_crystal_brightness, 15, "Power Crystal block brightness, scale 0-15.");

		conf.putBoolean(pk_RecEasyCrystals, false, "Get power crystals by smelting diamonds,\nchange crystals color by crafting.");
		conf.putInteger(pk_crystalsInChunk, 3, "Number of deposits in each 16x16 chunk.");
		conf.putInteger(pk_crystalsDepositMaxCount, 4, "Highest crystal count in one deposit");
		conf.putInteger(pk_crystalsMinY, 5, "Min Y coordinate of crystal deposits.");
		conf.putInteger(pk_crystalsMaxY, 15, "Max Y coordinate of crystal deposits.");

		//@formatter:off
		conf.putBoolean(pk_craft_recursive, false, 
				"Let's you craft using the Crafting Tool not only items you can atm,\n" +
				"but also items you could after crafting different items\n" +
				"(example: having torch, some redstone and few stones lets you craft\n" +
				"negated gates by one click, and the 'NOT' gate will be crafted silently in background)\n");
		
		conf.putBoolean(pk_craft_cheating, false, 
				"Makes the Crafting Tool work like TMI in Survival,\n" +
				"giving you everything with no resources consumed.");
		//@formatter:on

		conf.apply();

		recursive_crafting = conf.getBoolean(pk_craft_recursive);
		survival_cheating = conf.getBoolean(pk_craft_cheating);
		
	}

	@Override
	public void registerEntities(List<PC_Struct3<Class<? extends Entity>, String, Integer>> list) {}

	@Override
	public void registerTileEntities(List<PC_Struct3<Class<? extends TileEntity>, String, TileEntitySpecialRenderer>> list) {}

	@Override
	public void registerBlockRenderers() {
		PC_Renderer.swapTerrainRenderer = ModLoader.getUniqueBlockModelID(this, true);
		PC_Renderer.rotatedBoxRenderer = ModLoader.getUniqueBlockModelID(this, true);
		PCco_Renderer.crystalRenderer = ModLoader.getUniqueBlockModelID(this, true);
	}

	@Override
	public void registerBlocks(List<Block> list) {
		
		// @formatter:off
		
		powerCrystal = new PCco_BlockPowerCrystal(conf.num(pk_crystal), 49)
				.setHardness(0.5F)
				.setResistance(0.5F)
				.setBlockName("PCcoPowerCrystal")
				.setStepSound(Block.soundGlassFootstep)
				.setLightValue(conf.num(pk_crystal_brightness) * 0.0625F);
		
		// @formatter:on
		
		
		list.add(powerCrystal);
	}

	@Override
	public void registerItems() {
		
		// @formatter:off
		
		craftingTool = new PCco_ItemCraftingTool(conf.num(pk_craftingTool))
				.setItemName("PCcoGateCrafter");
		
		activator = new PCco_ItemActivator(conf.num(pk_iactivator))
				.setIconIndex(37)
				.setItemName("PCcoActivatorItem");

		powerDust = new PCco_ItemPowerDust(conf.num(pk_ipowerDust))
				.setIconCoord(13, 9)
				.setItemName("PCcoPowerDust");

		oreSniffer = (PCco_ItemOreSniffer) new PCco_ItemOreSniffer(conf.num(pk_isniffer))
				.setIconIndex(37)
				.setItemName("PCcoOreSnifferItem");
		
		replaceBlockItem(powerCrystal.blockID, new PCco_ItemBlockPowerCrystal(powerCrystal.blockID - 256));
		
		// @formatter:on
	}

	@Override
	public void preloadTextures(List<String> list) {
		list.add(getTerrainFile());
	}

	@Override
	public void setTextures() {
		craftingTool.setIconIndex(ModLoader.addOverride("/gui/items.png", getImgDir() + "gatecrafter.png"));
		activator.setIconIndex(ModLoader.addOverride("/gui/items.png", getImgDir() + "activator.png"));
		oreSniffer.setIconIndex(ModLoader.addOverride("/gui/items.png", getImgDir() + "sniffer.png"));
	}

	@Override
	public void setNames(Map<Object, String> map) {
		
		map.put(craftingTool, "PowerCraft's Crafting Tool");

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

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

	}

	@Override
	public void addRecipes() {
		//@formatter:off
		
		ModLoader.addRecipe(
				new ItemStack(craftingTool, 1, 0),
				new Object[] { " r ", "rIr", " r ",
					Character.valueOf('r'), Item.redstone, Character.valueOf('I'), Block.blockSteel });
		
		// TODO remove!
		ModLoader.addRecipe(
				new ItemStack(craftingTool, 1, 0),
				new Object[] { "d", Character.valueOf('d'), Block.dirt });
		
		// new recipes
		if (conf.getBoolean(pk_RecRecyclation)) {
			ModLoader.addShapelessRecipe(new ItemStack(Block.sand, 4), new Object[] { Block.sandStone });
			ModLoader.addShapelessRecipe(new ItemStack(Block.planks, 6), new Object[] { Item.doorWood });
			ModLoader.addShapelessRecipe(new ItemStack(Block.planks, 8), new Object[] { Block.chest });
			ModLoader.addShapelessRecipe(new ItemStack(Block.planks, 4), new Object[] { Block.workbench });
			ModLoader.addShapelessRecipe(new ItemStack(Block.planks, 2), new Object[] { Block.pressurePlatePlanks });
			ModLoader.addShapelessRecipe(new ItemStack(Block.stone, 2), new Object[] { Block.pressurePlateStone });
			ModLoader.addShapelessRecipe(new ItemStack(Block.stone, 2), new Object[] { Block.button });
			ModLoader.addShapelessRecipe(new ItemStack(Item.stick, 3), new Object[] { Block.fence });
			ModLoader.addShapelessRecipe(new ItemStack(Item.stick, 2), new Object[] { Block.ladder });
			ModLoader.addShapelessRecipe(new ItemStack(Block.planks, 6), new Object[] { Item.sign });
			ModLoader.addShapelessRecipe(new ItemStack(Item.ingotIron, 6), new Object[] { Item.doorSteel });
			ModLoader.addShapelessRecipe(new ItemStack(Item.ingotIron, 4), new Object[] { Item.compass });
			ModLoader.addShapelessRecipe(new ItemStack(Item.ingotGold, 4), new Object[] { Item.pocketSundial });
			ModLoader.addShapelessRecipe(new ItemStack(Block.cobblestone, 8), new Object[] { Block.stoneOvenIdle });
		}		

		// crafting recipe for spawner
		if (conf.getBoolean(pk_RecSpawner)) {
			ModLoader.addRecipe(
					new ItemStack(Block.mobSpawner, 1),
					new Object[] { "SIS", "I I", "SIS", Character.valueOf('I'), Item.ingotIron, Character.valueOf('S'), Block.cobblestoneMossy });
			
		}
		
		
		// crystal changing color, crystal from smelted diamonds
		if (conf.getBoolean(pk_RecEasyCrystals)) {
			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) });
			
			// two crystals of any color -> two portions of PowerDust
			ModLoader.addShapelessRecipe(
					new ItemStack(powerDust, 48, 0),
					new Object[] { new ItemStack(powerCrystal, 1, -1),	new ItemStack( powerCrystal, 1, -1) });
			
		} else {
			
			// Normal recipe for power dust
			ModLoader.addShapelessRecipe(new ItemStack(powerDust, 24, 0), new Object[] { new ItemStack(powerCrystal, 1, -1) });
		}
		
		// sniffer		
		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 });

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

	@Override
	public void postInit() {
		
		// @formatter:off
		
		// load crops and generate default file
		PC_CropManager.loadCrops();	
		
		// register activator listener (for spawner GUI)
		PC_Module.registerActivatorListener(this);
		
		oreSniffer.initNames();


		// set invedit groups and exceptions
		PC_InveditManager.setDamageRange(powerCrystal.blockID, 0, 7);

		PC_InveditManager.setItemCategory(powerCrystal.blockID, "Power crystals");
		PC_InveditManager.setItemCategory(powerDust.shiftedIndex, "Power crystals");

		PC_InveditManager.setItemCategory(craftingTool.shiftedIndex, "Handheld devices");
		PC_InveditManager.setItemCategory(activator.shiftedIndex, "Handheld devices");
		
		PC_InveditManager.setItemCategory(oreSniffer.shiftedIndex, "Handheld devices");



		// adding stuff to crafting tool
		ItemStack[] crystals = new ItemStack[9];
		for (int i = 0; i < 8; i++) {
			crystals[i] = new ItemStack(powerCrystal, 1, i);
		}
		crystals[8] = new ItemStack(powerDust, 24, 0);
		addStacksToCraftingTool(PC_CraftingToolGroup.DECORATIVE, crystals);

		
		addStacksToCraftingTool(
				PC_CraftingToolGroup.HANDHELD,
				new ItemStack(activator,1,0),
				new ItemStack(oreSniffer,1,0),
				new ItemStack(craftingTool,1,0)
			);
		
		addStacksToCraftingTool(
				PC_CraftingToolGroup.VANILLA, 
				new ItemStack(Block.obsidian, 1, 0),
				new ItemStack(Block.stoneBrick, 4, 0),
				new ItemStack(Item.redstoneRepeater, 1, 0),
				new ItemStack(Block.torchRedstoneActive, 1, 0),
				new ItemStack(Block.lever, 1, 0),
				new ItemStack(Block.button, 1, 0),
				new ItemStack(Block.pressurePlateStone, 1, 0),
				new ItemStack(Block.pressurePlatePlanks, 1, 0),
				new ItemStack(Block.pistonBase, 1, 0),
				new ItemStack(Block.pistonStickyBase, 1, 0),
				new ItemStack(Block.tnt, 1, 0),
				new ItemStack(Block.redstoneLampIdle, 1, 0),
				new ItemStack(Block.chest, 1, 0),
				new ItemStack(Block.blockSteel, 1, 0),
				new ItemStack(Block.stoneOvenIdle, 1, 0),
				new ItemStack(Block.music, 1, 0),
				new ItemStack(Block.dispenser, 1, 0),
				new ItemStack(Block.trapdoor, 2, 0),
				new ItemStack(Item.doorSteel, 1, 0),
				new ItemStack(Item.doorWood, 1, 0),
				new ItemStack(Item.redstone, 1, 0)
			);
		
		// @formatter:on

	}
	

	// *** HANDLING RENDERERS ***

	@Override
	public boolean renderWorldBlock(RenderBlocks renderblocks, IBlockAccess blockAccess, int i, int j, int k, Block block, int rtype) {
		boolean flag = false;
		flag |= PC_Renderer.renderBlockByType(renderblocks, blockAccess, i, j, k, block, rtype);
		flag |= PCco_Renderer.renderBlockByType(renderblocks, blockAccess, i, j, k, block, rtype);
		return flag;
	}

	@Override
	public void renderInvBlock(RenderBlocks renderblocks, Block block, int i, int rtype) {
		PC_Renderer.renderInvBlockByType(renderblocks, block, i, rtype);
		PCco_Renderer.renderInvBlockByType(renderblocks, block, i, rtype);
	}


	// Generate the power crystals if enabled.
	@Override
	public void generateSurface(World world, Random random, int chunkX, int chunkZ) {
		if (!conf.flag(pk_crystal_gen)) { return; }

		int posX;
		int posY;
		int posZ;

		for (int q = 0; q < conf.num(pk_crystalsInChunk); q++) {
			int maxBlocks = random.nextInt(MathHelper.clamp_int(conf.num(pk_crystalsDepositMaxCount) - 1, 1, 10)) + 2;

			posX = chunkX + random.nextInt(16);
			posY = MathHelper.clamp_int(
					random.nextInt(MathHelper.clamp_int(conf.num(pk_crystalsMaxY) - conf.num(pk_crystalsMinY), 1, 255))
							+ conf.num(pk_crystalsMinY), 1, 255);

			posZ = chunkZ + random.nextInt(16);

			PC_Logger.finest("Generating PowerCrystals deposit of size " + maxBlocks + " at coords "+new PC_CoordI(posX, posY, posZ));

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

	@Override
	public boolean onActivatorUsedOnBlock(ItemStack stack, EntityPlayer player, World world, PC_CoordI pos) {

		if (pos.getId(world) == Block.mobSpawner.blockID) {

			ModLoader.openGUI(player, new PCco_GuiSpawnerEditor((TileEntityMobSpawner) pos.getTileEntity(world)));

			return true;
		}

		return false;
	}

}
