package alice.cubicvillager.block;

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

import javax.annotation.Nullable;

import alice.cubicvillager.CubicVillager;
import alice.cubicvillager.ItemManager;
import alice.cubicvillager.block.state.BlockStateContainerVillager;
import alice.cubicvillager.tileentity.TileEntityVillager;
import alice.cubicvillager.utility.ModLogger;
import alice.cubicvillager.utility.TypeTransformer;
import alice.cubicvillager.utility.VillagerData;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.registry.RegistryNamespaced;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerCareer;
import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.registries.GameData;

public final class BlockVillagerTrader extends BlockVillager implements ITileEntityProvider
{
	protected static final RegistryNamespaced<ResourceLocation, VillagerProfession> PROFESSIONS;
	public static final Enchantment SILKTOUCH;

	static
	{
		PROFESSIONS = GameData.getWrapper(VillagerProfession.class);
		SILKTOUCH = Enchantment.REGISTRY.getObjectById(33);
	}

	public BlockVillagerTrader()
	{
		super("villager_block_trade", true);
		this.setCreativeTab(CreativeTabs.DECORATIONS);
		GameRegistry.registerTileEntity(TileEntityVillager.class, "cubicvillager_trader");
	}

	@SideOnly(Side.CLIENT)
	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn)
	{
		NBTTagCompound tagItemStack = stack.getTagCompound();
		if(tagItemStack == null)
			return;

		StringBuilder tooltipText = new StringBuilder();
		String name = tagItemStack.getString("Name");
		boolean hasString = TypeTransformer.notEmpty(name);
		if(hasString)
		{
			tooltipText.append("Name:§b");
			tooltipText.append(name);
			tooltipText.append("§r");
			String tt = tooltipText.toString();
			tooltip.add(tt);
		}

		String professionString = tagItemStack.getString("prf");
		hasString = TypeTransformer.notEmpty(professionString);
		if(!hasString)
			professionString = "minecraft:farmer";
		ResourceLocation professionName = new ResourceLocation(professionString);
		VillagerProfession profession = BlockVillagerTrader.PROFESSIONS.getObject(professionName);

		byte _b = tagItemStack.getByte("car");
		int careerId = TypeTransformer.fromUnsignedByte(_b);
		VillagerCareer career = profession.getCareer(careerId);

		tooltipText = new StringBuilder();
		tooltipText.append("entity.Villager.");
		String _career = career.getName();
		tooltipText.append(_career);
		String _id = tooltipText.toString();
		String localizedCareer = I18n.format(_id);

		tooltipText = new StringBuilder();
		tooltipText.append("Profession:§b");
		tooltipText.append(localizedCareer);
		tooltipText.append("§r");
		String _line = tooltipText.toString();
		tooltip.add(_line);

		tooltipText = new StringBuilder();
		tooltipText.append("Level:§b");
		byte __love = tagItemStack.getByte("lov");
		int _love = TypeTransformer.fromUnsignedByte(__love);
		tooltipText.append(_love);
		tooltipText.append("§r");
		_line = tooltipText.toString();
		tooltip.add(_line);
	}

	@Override
	public TileEntity createNewTileEntity(World world, int meta)
	{
		TileEntity te = new TileEntityVillager(world);
		return te;
	}

	@Override
	public Item getItemDropped(IBlockState state, Random random, int fortune)
	{
		return null;
	}

	@Override
	public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player)
	{
		Item item = Item.getItemFromBlock(this);
		if(item == null)
			return null;

		TileEntity tile = world.getTileEntity(pos);
		if(!(tile instanceof TileEntityVillager))
			return null;

		NBTTagCompound tag = new NBTTagCompound();
		VillagerData.tileToTag((TileEntityVillager)tile, tag);
		ItemStack stack = new ItemStack(item);
		stack.setTagCompound(tag);

		return stack;
	}

	@Override
	public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float px, float py, float pz)
	{
		if(world.isRemote)
			return true;

		int x = pos.getX();
		int y = pos.getY();
		int z = pos.getZ();

		TileEntity tileEntity = world.getTileEntity(pos);
		if(!(tileEntity instanceof TileEntityVillager))
		{
			ModLogger.chatNotify((WorldServer)world, "§4ERROR: Bad tile entity located at %d, %d, %d!§r", x, y, z);
			return false;
		}

		player.openGui(CubicVillager.me, 0, world, x, y, z);

		return true;
	}

	@Override
	public void onBlockHarvested(World world, BlockPos pos, IBlockState state, EntityPlayer player)
	{
		if(world.isRemote)
			return;

		TileEntity tileVillager = world.getTileEntity(pos);
		int x = pos.getX();
		int y = pos.getY();
		int z = pos.getZ();

		if(player.capabilities.isCreativeMode)
		{
			boolean sneak = player.isSneaking();
			if(sneak)
				dropTaggedBlock(world, x, y, z, true);
		}
		else
		{
			boolean stick = false;
			ItemStack currentItemS = player.getHeldItemMainhand();
			boolean empty = currentItemS.isEmpty();
			if(empty)
			{
				currentItemS = player.getHeldItemOffhand();
				empty = currentItemS.isEmpty();
			}
			Item currentItem = null;
			if(!empty)
			{
				currentItem = currentItemS.getItem();
				Item _wand = ItemManager.getItem("wand");
				if(currentItem == _wand)
					stick = true;
			}

			if(stick)
				dropTaggedBlock(world, x, y, z, true);
			else
			{
				boolean silk = (EnchantmentHelper.getEnchantmentLevel(SILKTOUCH, currentItemS) > 0);
				dropTaggedBlock(world, x, y, z, silk);
			}
		}

		if(tileVillager instanceof TileEntityVillager)
		{
			ItemStack[] itemStacks = ((TileEntityVillager)tileVillager).tradeInventory;
			for(ItemStack is : itemStacks)
			{
				boolean empty = is.isEmpty();
				if(empty)
					continue;
				EntityItem itemDrop = new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, is);
				world.spawnEntity(itemDrop);
			}

			itemStacks = ((TileEntityVillager)tileVillager).inventory;
			for(ItemStack is : itemStacks)
			{
				boolean empty = is.isEmpty();
				if(empty)
					continue;
				EntityItem itemDrop = new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, is);
				world.spawnEntity(itemDrop);
			}
		}
	}

	@Override
	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase entity, ItemStack itemStack)
	{
		super.onBlockPlacedBy(world, pos, state, entity, itemStack);

		int x = pos.getX();
		int y = pos.getY();
		int z = pos.getZ();
		
		TileEntity tileVillager = world.getTileEntity(pos);
		if(!(tileVillager instanceof TileEntityVillager))
		{
			if(!world.isRemote)
				ModLogger.chatNotify((WorldServer)world, "§4ERROR: Bad tile entity located at %d, %d, %d!§r", x, y, z);
			return;
		}
		
		NBTTagCompound tagItemStack = itemStack.getTagCompound();
		if(tagItemStack != null)
			VillagerData.tagToTile(tagItemStack, (TileEntityVillager)tileVillager);
		
		boolean sneak = entity.isSneaking();
		if(sneak)
			return;
		boolean placeOverEmeralds = checkUnderblocks(world, pos);
		if(!placeOverEmeralds)
			return;

		float fx = (float)x + 0.5F;
		float fy = (float)y - 1.5F;
		float fz = (float)z + 0.5F;

		EntityVillager villager = new EntityVillager(world);
		Random rng = villager.getRNG();

		if(!world.isRemote)
		{
			// Create a villager from block.
			VillagerData.tagToVillager(tagItemStack, villager);
			villager.setPosition(fx, fy, fz);
			world.spawnEntity(villager);
		}
		
		//for(byte particle = 0; particle < 5; particle++)
		//{
		//	world.spawnParticle("happyVillager", x - 0.5 + rng.nextDouble() * 2, y - 1.5 + rng.nextDouble() * 2, z - 0.5 + rng.nextDouble() * 2, 0, 0, 0);
		//}
		
		if(!world.isRemote)
		{
			if((entity instanceof EntityPlayer) && !((EntityPlayer)entity).capabilities.isCreativeMode)
			{
				int amount = rng.nextInt(4);
				amount += 18; // 18 - 22
				ItemStack drop = new ItemStack(Items.EMERALD, amount);
				EntityItem dropItem = new EntityItem(world, fx, fy, fz, drop);
				world.spawnEntity(dropItem);
			}
		}
		
		world.setBlockToAir(pos);
		BlockPos posDown = pos.down();
		world.setBlockToAir(posDown);
		posDown = posDown.down();
		world.setBlockToAir(posDown);
	}

	@Override
	protected BlockStateContainer createBlockState()
	{
		BlockStateContainer bsc = new BlockStateContainerVillager(this, STATES);
		return bsc;
	}

	private static boolean checkUnderblocks(World world, BlockPos vPos)
	{
		int y = vPos.getY();

		if(y < 2)
			return false;

		BlockPos pos = vPos.down();
		IBlockState block = world.getBlockState(pos);
		Block _block = block.getBlock();
		boolean isEmerald = _block.equals(Blocks.EMERALD_BLOCK);

		if(!isEmerald)
			return false;

		pos = pos.down();
		block = world.getBlockState(pos);
		_block = block.getBlock();
		isEmerald = _block.equals(Blocks.EMERALD_BLOCK);

		return isEmerald;
	}

	public static void dropTaggedBlock(World world, int x, int y, int z, boolean isSilkTouch)
	{
		if(world.isRemote)
			return;

		Block _trader = ItemManager.getBlock("trader");
		ItemStack itemStack = new ItemStack(_trader, 1, 0);

		if(isSilkTouch)
		{
			BlockPos pos = new BlockPos(x, y, z);
			TileEntity tileVillager = world.getTileEntity(pos);
			if(tileVillager instanceof TileEntityVillager)
			{
				NBTTagCompound tag = new NBTTagCompound();
				VillagerData.tileToTag((TileEntityVillager)tileVillager, tag);
				itemStack.setTagCompound(tag);
			}
		}

		EntityItem ei = new EntityItem(world, (double)x + 0.5, (double)y + 0.5, (double)z + 0.5, itemStack);
		world.spawnEntity(ei);
	}
}
