package common.block.tech;

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

import common.block.Block;
import common.collect.Lists;
import common.collect.Maps;
import common.init.Blocks;
import common.init.Items;
import common.init.SoundEvent;
import common.item.CheatTab;
import common.item.Item;
import common.model.ParticleType;
import common.rng.Random;
import common.util.BlockPos;
import common.util.Facing;
import common.world.IWorldAccess;
import common.world.AWorldClient;
import common.world.State;
import common.world.World;
import common.world.AWorldServer;

public class BlockRedstoneTorch extends BlockTorch
{
    private static Map<World, List<BlockRedstoneTorch.Toggle>> toggles = Maps.<World, List<BlockRedstoneTorch.Toggle>>newHashMap();
    private final boolean isOn;

    private boolean isBurnedOut(AWorldServer worldIn, BlockPos pos, boolean turnOff)
    {
        if (!toggles.containsKey(worldIn))
        {
            toggles.put(worldIn, Lists.<BlockRedstoneTorch.Toggle>newArrayList());
        }

        List<BlockRedstoneTorch.Toggle> list = (List)toggles.get(worldIn);

        if (turnOff)
        {
            list.add(new BlockRedstoneTorch.Toggle(pos, worldIn.getTime()));
        }

        int i = 0;

        for (int j = 0; j < list.size(); ++j)
        {
            BlockRedstoneTorch.Toggle blockredstonetorch$toggle = (BlockRedstoneTorch.Toggle)list.get(j);

            if (blockredstonetorch$toggle.pos.equals(pos))
            {
                ++i;

                if (i >= 8)
                {
                    return true;
                }
            }
        }

        return false;
    }

    public BlockRedstoneTorch(boolean isOn)
    {
        this.isOn = isOn;
//        this.setTickRandomly(true);
        this.setTab((CheatTab)null);
    }

    /**
     * How many world ticks before ticking
     */
    public int tickRate(World worldIn, BlockPos pos)
    {
        return 2;
    }

    public void onBlockAdded(AWorldServer worldIn, BlockPos pos, State state)
    {
        if (this.isOn)
        {
            for (Facing enumfacing : Facing.values())
            {
                worldIn.notifyNeighborsOfStateChange(pos.offset(enumfacing), this);
            }
        }
    }

    public void onBlockRemoved(AWorldServer worldIn, BlockPos pos, State state)
    {
        if (this.isOn)
        {
            for (Facing enumfacing : Facing.values())
            {
                worldIn.notifyNeighborsOfStateChange(pos.offset(enumfacing), this);
            }
        }
    }

    public int getWeakPower(IWorldAccess worldIn, BlockPos pos, State state, Facing side)
    {
        return this.isOn && state.getValue(FACING) != side ? 15 : 0;
    }

    private boolean shouldBeOff(World worldIn, BlockPos pos, State state)
    {
        Facing enumfacing = ((Facing)state.getValue(FACING)).getOpposite();
        return worldIn.isSidePowered(pos.offset(enumfacing), enumfacing);
    }

    /**
     * Called randomly when setTickRandomly is set to true (used by e.g. crops to grow, etc.)
     */
    public void randomTick(AWorldServer worldIn, BlockPos pos, State state, Random random)
    {
    }

    public void updateTick(AWorldServer worldIn, BlockPos pos, State state, Random rand)
    {
        boolean flag = this.shouldBeOff(worldIn, pos, state);
        List<BlockRedstoneTorch.Toggle> list = (List)toggles.get(worldIn);

        while (list != null && !list.isEmpty() && worldIn.getTime() - ((BlockRedstoneTorch.Toggle)list.get(0)).time > 60L)
        {
            list.remove(0);
        }

        if (this.isOn)
        {
            if (flag)
            {
                worldIn.setState(pos, Blocks.unlit_redstone_torch.getState().withProperty(FACING, state.getValue(FACING)), 3);

                if (this.isBurnedOut(worldIn, pos, true))
                {
                    worldIn.playSound(SoundEvent.FIZZ, (double)((float)pos.getX() + 0.5F), (double)((float)pos.getY() + 0.5F), (double)((float)pos.getZ() + 0.5F), 0.5F);

                    for (int i = 0; i < 5; ++i)
                    {
                        double d0 = (double)pos.getX() + rand.doublev() * 0.6D + 0.2D;
                        double d1 = (double)pos.getY() + rand.doublev() * 0.6D + 0.2D;
                        double d2 = (double)pos.getZ() + rand.doublev() * 0.6D + 0.2D;
                        worldIn.spawnParticle(ParticleType.SMOKE_NORMAL, d0, d1, d2, 0.0D, 0.0D, 0.0D);
                    }

                    worldIn.scheduleUpdate(pos, worldIn.getState(pos).getBlock(), 160);
                }
            }
        }
        else if (!flag && !this.isBurnedOut(worldIn, pos, false))
        {
            worldIn.setState(pos, Blocks.redstone_torch.getState().withProperty(FACING, state.getValue(FACING)), 3);
        }
    }

    /**
     * Called when a neighboring block changes.
     */
    public void onNeighborBlockChange(World worldIn, BlockPos pos, State state, Block neighborBlock)
    {
        if (!this.onNeighborChangeInternal(worldIn, pos, state))
        {
            if (this.isOn == this.shouldBeOff(worldIn, pos, state))
            {
                worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn, pos));
            }
        }
    }

    public int getStrongPower(IWorldAccess worldIn, BlockPos pos, State state, Facing side)
    {
        return side == Facing.DOWN ? this.getWeakPower(worldIn, pos, state, side) : 0;
    }

    /**
     * Get the Item that this Block should drop when harvested.
     */
    public Item getItemDropped(State state, Random rand, int fortune)
    {
        return Items.redstone_torch;
    }

    /**
     * Can this block provide power. Only wire currently seems to have this change based on its state.
     */
    public boolean canProvidePower()
    {
        return true;
    }

    public void randomDisplayTick(AWorldClient worldIn, BlockPos pos, State state, Random rand)
    {
        if (this.isOn)
        {
            double d0 = (double)pos.getX() + 0.5D + (rand.doublev() - 0.5D) * 0.2D;
            double d1 = (double)pos.getY() + 0.7D + (rand.doublev() - 0.5D) * 0.2D;
            double d2 = (double)pos.getZ() + 0.5D + (rand.doublev() - 0.5D) * 0.2D;
            Facing enumfacing = (Facing)state.getValue(FACING);

            if (enumfacing.getAxis().isHorizontal())
            {
                Facing enumfacing1 = enumfacing.getOpposite();
                double d3 = 0.27D;
                d0 += 0.27D * (double)enumfacing1.getFrontOffsetX();
                d1 += 0.22D;
                d2 += 0.27D * (double)enumfacing1.getFrontOffsetZ();
            }

            worldIn.spawnParticle(ParticleType.REDSTONE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
        }
    }

    public Item getItem(World worldIn, BlockPos pos)
    {
        return Items.redstone_torch;
    }

    public boolean isAssociatedBlock(Block other)
    {
        return other == Blocks.unlit_redstone_torch || other == Blocks.redstone_torch;
    }
    
    public boolean isMagnetic() {
    	return true;
    }
	
	protected Item getItemToRegister() {
		return this.isOn ? super.getItemToRegister() : null;
	}

    static class Toggle
    {
        BlockPos pos;
        long time;

        public Toggle(BlockPos pos, long time)
        {
            this.pos = pos;
            this.time = time;
        }
    }
}
