package me.parsell.glowstonedust.common;

import java.util.Map;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.enums.WireConnection;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;

public class GlowstoneWireBlock extends Block{
	// These are the states of the wires coming off our block
	public static final net.minecraft.state.property.EnumProperty<net.minecraft.block.enums.WireConnection> WIRE_CONNECTION_NORTH;
	public static final net.minecraft.state.property.EnumProperty<net.minecraft.block.enums.WireConnection> WIRE_CONNECTION_EAST;
	public static final net.minecraft.state.property.EnumProperty<net.minecraft.block.enums.WireConnection> WIRE_CONNECTION_SOUTH;
	public static final net.minecraft.state.property.EnumProperty<net.minecraft.block.enums.WireConnection> WIRE_CONNECTION_WEST;

  // Locally defined DIRECTION <-> WIRE_CONNECTION_DIRECTION
  public static final Map<Direction, EnumProperty<WireConnection>> DIRECTION_TO_WIRE_CONNECTION_PROPERTY;

	// Determines the hitbox for our block
	public static final VoxelShape DOT_SHAPE;

  // Full sided state
  private BlockState FULL_STATE;

	public GlowstoneWireBlock(Settings settings) {
		super(settings);
		// Set these properties to be none as start, so we start with a dot
		this.setDefaultState((BlockState)((BlockState)((BlockState)((BlockState)((BlockState)((BlockState)this.stateManager.getDefaultState()).with(WIRE_CONNECTION_NORTH, WireConnection.NONE)).with(WIRE_CONNECTION_EAST, WireConnection.NONE)).with(WIRE_CONNECTION_SOUTH, WireConnection.NONE)).with(WIRE_CONNECTION_WEST, WireConnection.NONE)));
    this.FULL_STATE = (BlockState)((BlockState)((BlockState)((BlockState)this.getDefaultState().with(WIRE_CONNECTION_NORTH, WireConnection.SIDE)).with(WIRE_CONNECTION_EAST, WireConnection.SIDE)).with(WIRE_CONNECTION_SOUTH, WireConnection.SIDE)).with(WIRE_CONNECTION_WEST, WireConnection.SIDE);
  }

	// Make sure out block has the properties for us to manage
	protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
		builder.add(WIRE_CONNECTION_NORTH, WIRE_CONNECTION_EAST, WIRE_CONNECTION_SOUTH, WIRE_CONNECTION_WEST);
	}

	private static boolean isFullyConnected(BlockState state) {
		return ((WireConnection)state.get(WIRE_CONNECTION_NORTH)).isConnected() && 
           ((WireConnection)state.get(WIRE_CONNECTION_SOUTH)).isConnected() && 
           ((WireConnection)state.get(WIRE_CONNECTION_EAST)).isConnected() && 
           ((WireConnection)state.get(WIRE_CONNECTION_WEST)).isConnected();
	}

	private static boolean isNotConnected(BlockState state) {
		return !((WireConnection)state.get(WIRE_CONNECTION_NORTH)).isConnected() && 
           !((WireConnection)state.get(WIRE_CONNECTION_SOUTH)).isConnected() && 
           !((WireConnection)state.get(WIRE_CONNECTION_EAST)).isConnected() && 
           !((WireConnection)state.get(WIRE_CONNECTION_WEST)).isConnected();
	}

  public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
    return DOT_SHAPE;
  }

  public BlockState getPlacecmentState(ItemPlacementContext ctx){
    return this.getDefaultState();
  }

  public BlockState rotate(BlockState state, BlockRotation rotation) {
    switch(rotation) {
    case CLOCKWISE_180:
       return (BlockState)((BlockState)((BlockState)((BlockState)state.with(WIRE_CONNECTION_NORTH, state.get(WIRE_CONNECTION_SOUTH))).with(WIRE_CONNECTION_EAST, state.get(WIRE_CONNECTION_WEST))).with(WIRE_CONNECTION_SOUTH, state.get(WIRE_CONNECTION_NORTH))).with(WIRE_CONNECTION_WEST, state.get(WIRE_CONNECTION_EAST));
    case COUNTERCLOCKWISE_90:
       return (BlockState)((BlockState)((BlockState)((BlockState)state.with(WIRE_CONNECTION_NORTH, state.get(WIRE_CONNECTION_EAST))).with(WIRE_CONNECTION_EAST, state.get(WIRE_CONNECTION_SOUTH))).with(WIRE_CONNECTION_SOUTH, state.get(WIRE_CONNECTION_WEST))).with(WIRE_CONNECTION_WEST, state.get(WIRE_CONNECTION_NORTH));
    case CLOCKWISE_90:
       return (BlockState)((BlockState)((BlockState)((BlockState)state.with(WIRE_CONNECTION_NORTH, state.get(WIRE_CONNECTION_WEST))).with(WIRE_CONNECTION_EAST, state.get(WIRE_CONNECTION_NORTH))).with(WIRE_CONNECTION_SOUTH, state.get(WIRE_CONNECTION_EAST))).with(WIRE_CONNECTION_WEST, state.get(WIRE_CONNECTION_SOUTH));
    default:
       return state;
    }
 }

 public BlockState mirror(BlockState state, BlockMirror mirror) {
    switch(mirror) {
    case LEFT_RIGHT:
       return (BlockState)((BlockState)state.with(WIRE_CONNECTION_NORTH, state.get(WIRE_CONNECTION_SOUTH))).with(WIRE_CONNECTION_SOUTH, state.get(WIRE_CONNECTION_NORTH));
    case FRONT_BACK:
       return (BlockState)((BlockState)state.with(WIRE_CONNECTION_EAST, state.get(WIRE_CONNECTION_WEST))).with(WIRE_CONNECTION_WEST, state.get(WIRE_CONNECTION_EAST));
    default:
       return super.mirror(state, mirror);
    }
 }

  public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit){
    if(isNotConnected(state))
      world.setBlockState(pos, FULL_STATE, 3);
    else
      world.setBlockState(pos, this.getDefaultState(), 3);
    System.out.println("onUse");
    return ActionResult.SUCCESS;
  }

  public void update(World world, BlockPos pos, BlockState state){
    System.out.println("Update");
  }

  // isnt system.out BUT will update neighors?
  public void updateNeighbors(World world, BlockPos pos){
    System.out.println("Update neighbors");
    if (world.getBlockState(pos).isOf(this)) {
      world.updateNeighborsAlways(pos, this);
      Direction[] var3 = Direction.values();
      int var4 = var3.length;

      for(int var5 = 0; var5 < var4; ++var5) {
         Direction direction = var3[var5];
         world.updateNeighborsAlways(pos.offset(direction), this);
      }

   }
  }

  public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean notify){
    System.out.println("Neighbor update");
  }

	static {
		WIRE_CONNECTION_NORTH = Properties.NORTH_WIRE_CONNECTION;
		WIRE_CONNECTION_EAST = Properties.EAST_WIRE_CONNECTION;
		WIRE_CONNECTION_SOUTH = Properties.SOUTH_WIRE_CONNECTION;
		WIRE_CONNECTION_WEST = Properties.WEST_WIRE_CONNECTION;
		
    DIRECTION_TO_WIRE_CONNECTION_PROPERTY = Maps.newEnumMap((Map)ImmutableMap.of(Direction.NORTH, WIRE_CONNECTION_NORTH, Direction.EAST, WIRE_CONNECTION_EAST, Direction.SOUTH, WIRE_CONNECTION_SOUTH, Direction.WEST, WIRE_CONNECTION_WEST));
    
    DOT_SHAPE = Block.createCuboidShape(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D);

	}
}