package common.block.artificial;

import common.block.Block;
import common.block.Rotatable;
import common.block.Material;
import common.color.DyeColor;
import common.color.TextColor;
import common.entity.npc.EntityNPC;
import common.init.ItemRegistry;
import common.item.Item;
import common.item.block.ItemBed;
import common.model.BlockLayer;
import common.model.Model;
import common.model.ModelProvider;
import common.model.ModelRotation;
import common.properties.Property;
import common.properties.PropertyEnum;
import common.rng.Random;
import common.util.BlockPos;
import common.util.Facing;
import common.util.Identifyable;
import common.util.WorldPos;
import common.world.IWorldAccess;
import common.world.State;
import common.world.World;

public class BlockBed extends Block implements Rotatable {
	public static enum EnumPartType implements Identifyable {
		HEAD("head"), FOOT("foot");

		private final String name;

		private EnumPartType(String name) {
			this.name = name;
		}

		public String toString() {
			return this.name;
		}

		public String getName() {
			return this.name;
		}
	}

	public static final PropertyEnum<BlockBed.EnumPartType> PART = 
			PropertyEnum.<BlockBed.EnumPartType>create("part", BlockBed.EnumPartType.class);
	public static final DyeColor[] COLORS = new DyeColor[] 
			{DyeColor.RED, DyeColor.WHITE, DyeColor.BLACK, DyeColor.PURPLE};

	private final DyeColor color;

	public BlockBed(DyeColor color) {
		super(Material.BURNABLE);
		this.color = color;
		this.setDefaultState(this.getBaseState().withProperty(PART, BlockBed.EnumPartType.FOOT));
		this.setBedBounds();
	}

	public boolean onBlockActivated(World world, BlockPos pos, State state, EntityNPC player, Facing side, 
			float hitX, float hitY, float hitZ) {
		if(world.client)
			return true;
		if(state.getValue(PART) != BlockBed.EnumPartType.HEAD) {
			pos = pos.offset((Facing)state.getValue(FACING));
			state = world.getState(pos);
			if(state.getBlock() != this) {
				return true;
			}
		}
		if(player.isEntityAlive() && Math.abs(player.posX - (double)pos.getX()) <= 3.0D
				&& Math.abs(player.posY - (double)pos.getY()) <= 2.0D && Math.abs(player.posZ - (double)pos.getZ()) <= 3.0D) {
			player.setSpawnPoint(new WorldPos(pos, player.worldObj.dimension.getDimensionId()));
			player.connection.addHotbar(TextColor.DGREEN + "Dein Einstiegspunkt wurde auf %s bei [%s, %s, %s] gesetzt", 
					player.worldObj.dimension.getFormattedName(false), player.getSpawnPoint().getX(),
					player.getSpawnPoint().getY(), player.getSpawnPoint().getZ());
		}
//		else if(!Config.bedSpawn) {
//			world.destroyBlock(pos, true);
//			BlockPos blockpos = pos.offset(((Facing)state.getValue(FACING)).getOpposite());
//			if(world.getState(blockpos).getBlock() == this)
//				world.destroyBlock(blockpos, true);
//			world.newExplosion(null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, 0.0F, 
//					false, false, true);
//			((EntityNPCMP)player).addFeed(TextColor.DARK_RED + "Der Einstiegspunkt kann nicht gesetzt werden");
//		}
		return true;
	}

	public boolean isFullCube() {
		return false;
	}

	public boolean isOpaqueCube() {
		return false;
	}

	public void setBlockBoundsBasedOnState(IWorldAccess worldIn, BlockPos pos) {
		this.setBedBounds();
	}

	public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock) {
		Facing enumfacing = (Facing)state.getValue(FACING);
		if(state.getValue(PART) == BlockBed.EnumPartType.HEAD) {
			if(worldIn.getState(pos.offset(enumfacing.getOpposite())).getBlock() != this)
				worldIn.setBlockToAir(pos);
		}
		else if(worldIn.getState(pos.offset(enumfacing)).getBlock() != this) {
			worldIn.setBlockToAir(pos);
			if(!worldIn.client)
				this.dropBlockAsItem(worldIn, pos, state, 0);
		}
	}

	public Item getItemDropped(State state, Random rand, int fortune) {
		return state.getValue(PART) == BlockBed.EnumPartType.HEAD ? null : ItemRegistry.getRegisteredItem(this.color.getName() + "_bed");
	}

	private void setBedBounds() {
		this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
	}

	public static BlockPos getSafeExitLocation(World worldIn, BlockPos pos, int tries) {
		Facing enumfacing = (Facing)worldIn.getState(pos).getValue(FACING);
		int i = pos.getX();
		int j = pos.getY();
		int k = pos.getZ();

		for(int l = 0; l <= 1; ++l) {
			int i1 = i - enumfacing.getFrontOffsetX() * l - 1;
			int j1 = k - enumfacing.getFrontOffsetZ() * l - 1;
			int k1 = i1 + 2;
			int l1 = j1 + 2;

			for(int i2 = i1; i2 <= k1; ++i2) {
				for(int j2 = j1; j2 <= l1; ++j2) {
					BlockPos blockpos = new BlockPos(i2, j, j2);

					if(hasRoomForPlayer(worldIn, blockpos)) {
						if(tries <= 0) {
							return blockpos;
						}

						--tries;
					}
				}
			}
		}

		return null;
	}

	protected static boolean hasRoomForPlayer(World worldIn, BlockPos pos) {
		return worldIn.isBlockSolid(pos.down()) && !worldIn.getState(pos).getBlock().getMaterial().isSolid()
				&& !worldIn.getState(pos.up()).getBlock().getMaterial().isSolid();
	}

	public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, State state, float chance, int fortune) {
		if(state.getValue(PART) == BlockBed.EnumPartType.FOOT)
			super.dropBlockAsItemWithChance(worldIn, pos, state, chance, 0);
	}

	public int getMobilityFlag() {
		return 1;
	}

	public BlockLayer getBlockLayer() {
		return BlockLayer.CUTOUT;
	}

	public Item getItem(World worldIn, BlockPos pos) {
		return ItemRegistry.getRegisteredItem(this.color.getName() + "_bed");
	}

//	public void onBlockHarvested(World worldIn, BlockPos pos, State state, EntityNPC player) {
//		if(player.creative && state.getValue(PART) == BlockBed.EnumPartType.HEAD) {
//			BlockPos blockpos = pos.offset(((Facing)state.getValue(FACING)).getOpposite());
//			if(worldIn.getState(blockpos).getBlock() == this)
//				worldIn.setBlockToAir(blockpos);
//		}
//	}

	public State getStateFromMeta(int meta) {
		return this.getState().withProperty(PART, (meta & 8) > 0 ? BlockBed.EnumPartType.HEAD : BlockBed.EnumPartType.FOOT)
				.withProperty(FACING, Facing.getHorizontal(meta));
	}

	public int getMetaFromState(State state) {
		return ((Facing)state.getValue(FACING)).getHorizontalIndex() | (state.getValue(PART) == BlockBed.EnumPartType.HEAD ? 8 : 0);
	}

	protected Property[] getProperties() {
		return new Property[] {FACING, PART};
	}

	public Model getModel(ModelProvider provider, String name, State state) {
		if(state.getValue(PART) == EnumPartType.HEAD)
			return provider.getModel(this.color + "_bed_head_top").add(0, 0, 0, 16, 9, 16)
					.u().rot(90).noCull().s(this.color + "_bed_head_end").noCull()
					.w(this.color + "_bed_head_side").uv(0, 7, 16, 16).noCull().e(this.color + "_bed_head_side").uv(16, 7, 0, 16).noCull()
					.add(0, 3, 0, 16, 3, 16)
					.d("oak_planks").noCull().rotate(ModelRotation.getNorthRot(state.getValue(FACING).getOpposite()));
		else
			return provider.getModel(this.color + "_bed_foot_top").add(0, 0, 0, 16, 9, 16)
					.u().rot(90).noCull().n(this.color + "_bed_foot_end").noCull()
					.w(this.color + "_bed_foot_side").uv(0, 7, 16, 16).noCull().e(this.color + "_bed_foot_side").uv(16, 7, 0, 16).noCull()
					.add(0, 3, 0, 16, 3, 16)
					.d("oak_planks").noCull().rotate(ModelRotation.getNorthRot(state.getValue(FACING).getOpposite()));
	}
	
	protected Item getItemToRegister() {
		return new ItemBed(this).setDisplay(this.color.getSubject(0) + " Bett");
	}
}
