package net.minecraft.src;

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

public class mod_PCmachines extends PC_Module {

	/** Configuration file */
	public static PC_PropertyManager conf;

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

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

	@Override
	public String getModuleName() {
		return "MACHINES";
	}





	// *** PROPERTIES ***
	/** block ids ignored by roaster */
	public static List<Integer> roasterIgnoreBlockIDs;
	/** flag for improved dispensers */
	private static boolean dispenseBuckets = true, dispenseWheat = true, dispenseFood = false, dispenseBowls = true;

	private static final String pk_harvester = "id.block.harvester";
	private static final String pk_builder = "id.block.builder";
	private static final String pk_roaster = "id.block.roaster";
	private static final String pk_laser = "id.block.laser";
	private static final String pk_xpbank = "id.block.XP_bank";
	private static final String pk_optical = "id.block.optical";
	private static final String pk_imirror = "id.item.mirror";
	private static final String pk_iprism = "id.item.prism";
	private static final String pk_doNotSmelt = "list.roaster.ignored_blocks";
	private static final String pk_dispenseBuckets = "opt.dispenser.throw_buckets";
	private static final String pk_dispenseWheat = "opt.dispenser.throw_wheat";
	private static final String pk_dispenseFood = "opt.dispenser.throw_all_food";
	private static final String pk_dispenseBowls = "opt.dispenser.throw_bowls";
	private static final String pk_altPrismRecipe = "opt.prism.alternate_recipe";

	static {
		conf = new PC_PropertyManager("/config/PowerCraft/module_machines.cfg", "PowerCraft MACHINES module\nconfiguration file");

		conf.putBlock(pk_harvester, 221);
		conf.putBlock(pk_builder, 222);
		conf.putBlock(pk_roaster, 228);
		conf.putBlock(pk_laser, 230);
		conf.putBlock(pk_xpbank, 231);
		conf.putBlock(pk_optical, 234);
		conf.putItem(pk_imirror, 19005);
		conf.putItem(pk_iprism, 19006);
		conf.putString(pk_doNotSmelt, "1", "Comma separated list of IDs ignored by roaster");

		conf.putBoolean(pk_dispenseBuckets, true, "Thrown buckets can milk cows.");
		conf.putBoolean(pk_dispenseBowls, true, "Thrown bowls can get soup from mushroom cow.");
		conf.putBoolean(pk_dispenseWheat, true, "Thrown wheat can put animals into 'love' mode.");
		conf.putBoolean(pk_dispenseFood, false, "Thrown meat can heal wolves etc.");
		conf.putBoolean(pk_altPrismRecipe, false,
				"Use \"+\" shaped glass recipe instead of the 4-block one.\nNeeded for compatibility with MoCreatures.");

		conf.apply();

		roasterIgnoreBlockIDs = PC_Utils.parseIntList(conf.getString(pk_doNotSmelt));

		dispenseBuckets = conf.getBoolean(pk_dispenseBuckets);
		dispenseWheat = conf.getBoolean(pk_dispenseWheat);
		dispenseFood = conf.getBoolean(pk_dispenseFood);
		dispenseBowls = conf.getBoolean(pk_dispenseBowls);
	}


	// laser renderer is only for the inventory item
	public static int rendererLaser = 0;
	public static int rendererXPBank = 0;





	// *** MODULE INIT ***

	@Override
	public void preInit() {}

	@Override
	public void registerEntities() {
		ModLoader.registerEntityID(net.minecraft.src.PCma_EntityThrownBucket.class, "PCma_ThrownBucket", ModLoader.getUniqueEntityId());
		ModLoader.registerEntityID(net.minecraft.src.PCma_EntityThrownFood.class, "PCma_ThrownFood", ModLoader.getUniqueEntityId());
	}

	@Override
	public void registerTileEntities() {
		ModLoader.registerTileEntity(net.minecraft.src.PCma_TileEntityBuilder.class, "FCBlockPlacer");
		ModLoader.registerTileEntity(net.minecraft.src.PCma_TileEntityRoaster.class, "FCRoaster");
		ModLoader.registerTileEntity(net.minecraft.src.PCma_TileEntityLaser.class, "PCLaser", new PCma_TileEntityLaserRenderer());
		ModLoader.registerTileEntity(net.minecraft.src.PCma_TileEntityXPBank.class, "PCXPBank");
		ModLoader.registerTileEntity(net.minecraft.src.PCma_TileEntityOptical.class, "PCLaserMirror", new PCma_TileEntityOpticalRenderer());
	}

	@Override
	public void registerBlockRenderers() {
		rendererLaser = ModLoader.getUniqueBlockModelID(this, true);
		rendererXPBank = ModLoader.getUniqueBlockModelID(this, true);
	}

	@Override
	public void registerBlocks() {
		ModLoader.registerBlock(harvester);
		ModLoader.registerBlock(builder);
		ModLoader.registerBlock(roaster);
		ModLoader.registerBlock(laser);
		ModLoader.registerBlock(xpbank);
		ModLoader.registerBlock(optical);
	}

	@Override
	public void registerTextures() {

		prismPlacer.setIconIndex(ModLoader.addOverride("/gui/items.png", getImgDir() + "prismicon.png"));

		// set default textures, sometimes used for particles
		harvester.blockIndexInTexture = 109;
		builder.blockIndexInTexture = 109;
		laser.blockIndexInTexture = 16;
		roaster.blockIndexInTexture = 62;
		optical.blockIndexInTexture = 64;
		xpbank.blockIndexInTexture = 37;

	}

	@Override
	public void preloadTextures() {
		mc.renderEngine.getTexture(getTerrainFile());
		mc.renderEngine.getTexture(getImgDir() + "mirror.png");
		mc.renderEngine.getTexture(getImgDir() + "laser.png");
	}

	@Override
	public void addNames() {
		ModLoader.addName(harvester, "Block Harvester");
		ModLoader.addName(builder, "Block Dispenser");
		ModLoader.addName(roaster, "Roaster");
		ModLoader.addName(laser, "Laser");
		ModLoader.addName(xpbank, "Experience Storage");
		ModLoader.addName(optical, "laseropticalblock");
		ModLoader.addName(mirrorPlacer, "Mirror");
		ModLoader.addName(prismPlacer, "Prism");
	}

	@Override
	public void addRecipes() {
		//@formatter:off
		
		ModLoader.addRecipe(
				new ItemStack(builder, 1),
				new Object[] { "G", "D",
					Character.valueOf('G'), Item.ingotGold, Character.valueOf('D'), Block.dispenser });

		ModLoader.addRecipe(
				new ItemStack(harvester, 1),
				new Object[] { "P", "D",
					Character.valueOf('P'), Item.pickaxeSteel, Character.valueOf('D'), Block.dispenser });

		ModLoader.addRecipe(
				new ItemStack(roaster, 1),
				new Object[] { "III", "IFI", "III",
					Character.valueOf('I'), Item.ingotIron, Character.valueOf('F'), Item.flintAndSteel });

		ModLoader.addRecipe(
				new ItemStack(laser, 1),
				new Object[] { " WD", " S ", "SSS",
					Character.valueOf('S'), Block.stone, Character.valueOf('W'), new ItemStack(Block.planks, 1, -1), Character.valueOf('D'), Item.diamond });

		ModLoader.addRecipe(
				new ItemStack(laser, 1),
				new Object[] { " WD", " S ", "SSS",
					Character.valueOf('S'), Block.cobblestone, Character.valueOf('W'), new ItemStack(Block.planks, 1, -1), Character.valueOf('D'), Item.diamond });

		ModLoader.addRecipe(new ItemStack(xpbank, 1),
				new Object[] { "ODO", "OGO", "O O",
					Character.valueOf('O'), Block.obsidian, Character.valueOf('D'), Block.blockDiamond, Character.valueOf('G'), Item.ghastTear });

		ModLoader.addRecipe(
				new ItemStack(mirrorPlacer, 2),
				new Object[] { "GI", " I",	Character.valueOf('G'), Block.thinGlass, Character.valueOf('I'), Item.ingotIron });


		if(conf.getBoolean(pk_altPrismRecipe)){
			ModLoader.addRecipe(
					new ItemStack(prismPlacer, 1),
					new Object[] { " G ", "GGG", " G ", Character.valueOf('G'), Block.glass });
		}else{
			ModLoader.addRecipe(
					new ItemStack(prismPlacer, 1),
					new Object[] { "GG", "GG", Character.valueOf('G'), Block.glass });
		}
		
		//@formatter:on
	}

	@Override
	public void postInit() {
		PC_Utils.TMI_hideId(optical.blockID);
		PCma_CropList.ping();
	}






	//@formatter:off
	/** block harvester machine */
	public static Block harvester = new PCma_BlockHarvester(conf.getInteger(pk_harvester))
			.setHardness(0.7F)
			.setResistance(10.0F)
			.setBlockName("PCmaHarvester")
			.setStepSound(Block.soundStoneFootstep);

	/** block placing machine */
	public static Block builder = new PCma_BlockBuilder(conf.getInteger(pk_builder))
			.setHardness(0.7F)
			.setResistance(10.0F)
			.setBlockName("PCmaDispenser")
			.setStepSound(Block.soundStoneFootstep);

	/** instant furnace */
	public static Block roaster = new PCma_BlockRoaster(conf.getInteger(pk_roaster))
			.setHardness(0.7F)
			.setResistance(10.0F)
			.setBlockName("PCmaRoaster")
			.setStepSound(Block.soundStoneFootstep);

	/** laser device, tileentity subtypes */
	public static PCma_BlockLaser laser = (PCma_BlockLaser) (new PCma_BlockLaser(conf.getInteger(pk_laser)))
			.setHardness(0.7F)
			.setResistance(10.0F)
			.setBlockName("PCmaLaserBlock")
			.setStepSound(Block.soundStoneFootstep);

	/** mirror or prism, tileentity subtypes */
	public static Block optical = new PCma_BlockOptical(conf.getInteger(pk_optical))
			.setHardness(1.0F)
			.setResistance(4.0F)
			.setBlockName("PCmaLaserMirror")
			.setStepSound(Block.soundStoneFootstep);

	/** XP storage block */
	public static PCma_BlockXPBank xpbank = (PCma_BlockXPBank) (new PCma_BlockXPBank(conf.getInteger(pk_xpbank)))
			.setHardness(6.0F)
			.setResistance(100.0F)
			.setBlockName("PCmaXPBank")
			.setLightValue(0.5F)
			.setStepSound(Block.soundStoneFootstep);

	/** item for placing mirrors */
	public static Item mirrorPlacer = new PCma_ItemMirrorPlacer(conf.getInteger(pk_imirror))
			.setIconCoord(10, 2)
			.setItemName("PCmaLaserMirrorPlacer");

	/** item for placing prisms */
	public static Item prismPlacer = new PCma_ItemPrismPlacer(conf.getInteger(pk_iprism))
			.setIconCoord(11, 6)
			.setItemName("PCmaLaserPrismPlacer");
	
	//@formatter:on



	/**
	 * Dispense some items as thrown objects rather than EntityItem.
	 */
	@Override
	public boolean dispenseEntity(World world, double d, double d1, double d2, int i1, int j1, ItemStack itemstack) {

		if (dispenseBuckets && itemstack.itemID == Item.bucketEmpty.shiftedIndex) {
			PCma_EntityThrownBucket entity = new PCma_EntityThrownBucket(world, d, d1, d2, false);
			entity.setThrowableHeading(i1, 0.1D, j1, 1.1F, 6F);
			world.spawnEntityInWorld(entity);
			world.playAuxSFX(1002, (int) Math.round(d), (int) Math.round(d1), (int) Math.round(d2), 0);
			return true;
		}

		if (dispenseBowls && itemstack.itemID == Item.bowlEmpty.shiftedIndex) {
			PCma_EntityThrownBucket entity = new PCma_EntityThrownBucket(world, d, d1, d2, true);
			entity.setThrowableHeading(i1, 0.1D, j1, 1.1F, 6F);
			world.spawnEntityInWorld(entity);
			world.playAuxSFX(1002, (int) Math.round(d), (int) Math.round(d1), (int) Math.round(d2), 0);
			return true;
		}

		if (dispenseWheat && itemstack.itemID == Item.wheat.shiftedIndex) {
			PCma_EntityThrownFood entity = new PCma_EntityThrownFood(world, d, d1, d2, itemstack.getItem());
			entity.setThrowableHeading(i1, 0.1D, j1, 1.1F, 6F);
			world.spawnEntityInWorld(entity);
			world.playAuxSFX(1002, (int) Math.round(d), (int) Math.round(d1), (int) Math.round(d2), 0);
			return true;
		}

		if (dispenseFood && (itemstack.getItem() instanceof ItemFood || itemstack.getItem() == Item.bone)) {
			PCma_EntityThrownFood entity = new PCma_EntityThrownFood(world, d, d1, d2, itemstack.getItem());
			entity.setThrowableHeading(i1, 0.1D, j1, 1.1F, 6F);
			world.spawnEntityInWorld(entity);
			world.playAuxSFX(1002, (int) Math.round(d), (int) Math.round(d1), (int) Math.round(d2), 0);
			return true;
		}

		return false;
	}



	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void addRenderer(Map map) {
		map.put(PCma_EntityThrownBucket.class, new PCma_RenderThrownItem());
		map.put(PCma_EntityThrownFood.class, new PCma_RenderThrownItem());
	}





	@Override
	public boolean renderWorldBlock(RenderBlocks renderblocks, IBlockAccess iblockaccess, int i, int j, int k, Block block, int renderType) {

		if (renderType == rendererXPBank) {

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

			// XP bank inner thingy
			xpbank.rendering = true;
			PC_Renderer.renderBlockSwapTerrain(renderblocks, iblockaccess, i, j, k, block);
			xpbank.rendering = false;
			block.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			// obsidian body
			Block.obsidian.setBlockBounds(0.0F, 0.3F, 0.0F, 1.0F, 0.7F, 1.0F);
			renderblocks.renderStandardBlock(Block.obsidian, i, j, k);

			// legs
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.0F, 0.15F, 0.3F, 0.15F);
			renderblocks.renderStandardBlock(Block.obsidian, i, j, k);
			Block.obsidian.setBlockBounds(0.85F, 0.0F, 0.0F, 1.0F, 0.3F, 0.15F);
			renderblocks.renderStandardBlock(Block.obsidian, i, j, k);
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.85F, 0.15F, 0.3F, 1.0F);
			renderblocks.renderStandardBlock(Block.obsidian, i, j, k);
			Block.obsidian.setBlockBounds(0.85F, 0.0F, 0.85F, 1.0F, 0.3F, 1.0F);
			renderblocks.renderStandardBlock(Block.obsidian, i, j, k);

			// reset
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			RenderBlocks.cfgGrassFix = gf;

			return true;
		}

		return false;
	}

	@Override
	public void renderInvBlock(RenderBlocks renderblocks, Block block, int i, int rtype) {
		/**
		 * Laser is rendered like this in inventory, but block is rendered by
		 * SpecialTileEntityRnderer
		 */
		if (rtype == rendererLaser) {
			PC_Renderer.renderInvBlockSwapTerrain(renderblocks, block, i);
			block.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			// cobble body
			Block.cobblestone.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.2F, 1.0F);
			PC_Renderer.renderInvBox(renderblocks, Block.cobblestone, 0);
			Block.cobblestone.setBlockBounds(0.4F, 0.2F, 0.4F, 0.6F, 0.3F, 0.6F);
			PC_Renderer.renderInvBox(renderblocks, Block.cobblestone, 0);
			// reset
			Block.cobblestone.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			return;
		}

		if (rtype == rendererXPBank) {
			PC_Renderer.renderInvBlockSwapTerrain(renderblocks, block, i);
			block.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			// obsidian body
			Block.obsidian.setBlockBounds(0.0F, 0.3F, 0.0F, 1.0F, 0.8F, 1.0F);
			PC_Renderer.renderInvBox(renderblocks, Block.obsidian, 0);

			// legs
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.0F, 0.2F, 0.3F, 0.2F);
			PC_Renderer.renderInvBox(renderblocks, Block.obsidian, 0);
			Block.obsidian.setBlockBounds(0.8F, 0.0F, 0.0F, 1.0F, 0.3F, 0.2F);
			PC_Renderer.renderInvBox(renderblocks, Block.obsidian, 0);
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.8F, 0.2F, 0.3F, 1.0F);
			PC_Renderer.renderInvBox(renderblocks, Block.obsidian, 0);
			Block.obsidian.setBlockBounds(0.8F, 0.0F, 0.8F, 1.0F, 0.3F, 1.0F);
			PC_Renderer.renderInvBox(renderblocks, Block.obsidian, 0);

			// reset
			Block.obsidian.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);

			return;
		}
	}
}
