package common.ai;

import java.util.Map;

import common.block.Block;
import common.collect.Maps;
import common.entity.npc.EntityNPC;
import common.init.Blocks;
import common.init.Config;
import common.init.ItemRegistry;
import common.item.ItemStack;
import common.material.Material;
import common.rng.Random;
import common.util.BlockPos;
import common.util.ExtMath;
import common.world.State;
import common.world.World;

public class EntityAITakePlace extends EntityAIBase
{
	private static class StackKey {
		public String item;
		public int meta;
		
		public StackKey(String str) {
			String[] tok = str.split(":", 2);
			this.item = tok[0];
			this.meta = tok.length > 1 ? Integer.parseInt(tok[1]) : -1;
		}
		
		public StackKey(ItemStack stack) {
			this.item = ItemRegistry.REGISTRY.getNameForObject(stack.getItem()).toString();
			this.meta = stack.getItem().getMaxDamage() <= 0 ? stack.getMetadata() : -1;
		}
		
//		public boolean isSame(ItemStack stack) {
//			return this.item.equals(ItemRegistry.REGISTRY.getNameForObject(stack.getItem()).toString()) && 
//					(stack.getItem().getMaxDamage() > 0 || stack.getMetadata() == this.meta);
//		}
		
		public boolean equals(Object other) {
			return other instanceof StackKey && ((StackKey)other).item.equals(this.item) && ((StackKey)other).meta == this.meta;
		}
		
		public int hashCode() {
			return this.item.hashCode() ^ (this.meta << 8);
		}
		
		public String toString() {
			return this.item + (this.meta == -1 ? "" : (":" + this.meta));
		}
	}
	
    private static final Map<State, ItemStack> STEALABLE = Maps.newHashMap();
    private static final Map<StackKey, State> PLACEABLE = Maps.newHashMap();
    
    private static void addPlaceable(State state, ItemStack stack) {
    	STEALABLE.put(state, stack);
    	PLACEABLE.put(new StackKey(stack), state);
    }
    
    private static void addPlaceable(Block block) {
    	addPlaceable(block.getState(), new ItemStack(block));
    }

    static {
    	addPlaceable(Blocks.flower);
        addPlaceable(Blocks.brown_mushroom);
        addPlaceable(Blocks.red_mushroom);
        addPlaceable(Blocks.blue_mushroom);
    }

    private EntityNPC entity;
    private boolean place;

    public EntityAITakePlace(EntityNPC placer)
    {
        this.entity = placer;
    }

    public boolean shouldExecute()
    {
    	if(!Config.mobGrief || this.entity.getAttackTarget() != null)
    		return false;
    	if(this.entity.getHeldItem() == null) {
    		this.place = false;
    		return this.entity.getRNG().chance(20);
    	}
    	else if(this.entity.getRNG().chance(200) && PLACEABLE.containsKey(new StackKey(this.entity.getHeldItem()))) {
    		this.place = this.entity.getRNG().rarity(10);
    		return true;
    	}
    	return false;
    }

    public void updateTask()
    {
        Random random = this.entity.getRNG();
        World world = this.entity.worldObj;
        int i = ExtMath.floord(this.entity.posX - (this.place ? 1.0 : 2.0) + random.doublev() * (this.place ? 2.0 : 4.0));
        int j = ExtMath.floord(this.entity.posY + random.doublev() * (this.place ? 2.0 : 3.0));
        int k = ExtMath.floord(this.entity.posZ - (this.place ? 1.0 : 2.0) + random.doublev() * (this.place ? 2.0 : 4.0));
        BlockPos blockpos = new BlockPos(i, j, k);
        if(this.place) {
            ItemStack stack = this.entity.getHeldItem();
            if(stack == null || !PLACEABLE.containsKey(new StackKey(this.entity.getHeldItem())))
            	return;
            Block replace = world.getState(blockpos).getBlock();
            Block below = world.getState(blockpos.down()).getBlock();
            State state = PLACEABLE.get(new StackKey(this.entity.getHeldItem()));
            if (state.getBlock().canPlaceBlockAt(world, blockpos) && replace.getMaterial() == Material.air && 
            		below.getMaterial() != Material.air && below.isFullCube())
            {
            	this.entity.getLookHelper().setLookPosition((double)i + 0.5, (double)j + 0.5, (double)k + 0.5, 10.0F, 
            			(float)this.entity.getVerticalFaceSpeed());
                this.entity.swingItem();
                world.setState(blockpos, state, 3);
                --stack.stackSize;
                if(stack.stackSize <= 0)
                	this.entity.setItemNoUpdate(0, null);
            }
        }
        else {
            State state = world.getState(blockpos);
            Block block = state.getBlock();

            if (STEALABLE.containsKey(state) && 
            		(this.entity.getHeldItem() == null || (ItemStack.areItemsEqual(STEALABLE.get(state), 
            		this.entity.getHeldItem()) && this.entity.getHeldItem().stackSize < this.entity.getHeldItem().getMaxStackSize())))
            {
            	this.entity.getLookHelper().setLookPosition((double)i + 0.5, (double)j + 0.5, (double)k + 0.5, 10.0F, 
            			(float)this.entity.getVerticalFaceSpeed());
                this.entity.swingItem();
                world.setState(blockpos, Blocks.air.getState());
                if(this.entity.getHeldItem() != null)
                	++this.entity.getHeldItem().stackSize;
                else
                	this.entity.setItemNoUpdate(0, STEALABLE.get(state).copy());
            }
        }
    }

//private boolean shouldAttackPlayer(EntityNPC player)
//{
//  ItemStack itemstack = player.inventory.armorInventory[3];
//
//  if (itemstack != null && itemstack.getItem() == ItemRegistry.getItemFromBlock(Blocks.pumpkin))
//  {
//      return false;
//  }
//  else
//  {
//      Vec3 vec3 = player.getLook(1.0F).normalize();
//      Vec3 vec31 = new Vec3(this.posX - player.posX, this.getEntityBoundingBox().minY + (double)(this.height / 2.0F) - (player.posY + (double)player.getEyeHeight()), this.posZ - player.posZ);
//      double d0 = vec31.lengthVector();
//      vec31 = vec31.normalize();
//      double d1 = vec3.dotProduct(vec31);
//      return d1 > 1.0D - 0.025D / d0 ? player.canEntityBeSeen(this) : false;
//  }
//}
//
}
