package common.tileentity;

import java.util.List;

import common.block.Block;
import common.block.artificial.BlockStainedGlass;
import common.block.artificial.BlockStainedGlassPane;
import common.color.DyeColor;
import common.entity.types.EntityLiving;
import common.init.Blocks;
import common.network.Packet;
import common.packet.SPacketUpdateTileEntity;
import common.potion.Potion;
import common.potion.PotionEffect;
import common.tags.TagObject;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.world.State;
import common.world.World;
import common.world.AWorldServer;

public class TileEntityBeacon extends TileEntity implements ITickable
{
    /** List of effects that Beacon can apply */
    public static final Potion[][] effectsList = new Potion[][] {{Potion.SPEED, Potion.HASTE}, {Potion.RESISTANCE, Potion.JUMP}, {Potion.STRENGTH}, {Potion.REGENERATION}};
//    private final List<TileEntityBeacon.BeamSegment> beamSegments = Lists.<TileEntityBeacon.BeamSegment>newArrayList();
//    private long lastRenderUpdate;
//    private float charge;
    private boolean isComplete;

    /** Level of this beacon's pyramid. */
    private int levels = -1;

    /** Primary potion effect given by this beacon. */
    private Potion primaryEffect;

    /** Secondary potion effect given by this beacon. */
    private Potion secondaryEffect;

    /** Item given to this beacon as payment. */
//    private ItemStack payment;
    private String customName;
    private DyeColor beamColor = DyeColor.WHITE;

    /**
     * Like the old updateEntity(), except more generic.
     */
    public void update()
    {
        if (!this.worldObj.client && ((AWorldServer)this.worldObj).getTime() % 80L == 0L)
        {
            this.updateBeacon();
        }
//        else if (this.worldObj.client && this.worldObj.getDayTime() % 20L == 0L)
//        {
//            this.updateBeacon();
//        }
    }

    public void updateBeacon()
    {
    	if(!this.worldObj.client)
//    		this.updateSegmentColors();
//    	else
    		this.updateSegment();
    }

    private void addEffectsToPlayers()
    {
        if (this.isComplete && this.levels > 0 && this.primaryEffect != null)
        {
            double d0 = (double)(this.levels * 10 + 10);
            int i = 0;

            if (this.levels >= 4 && this.primaryEffect == this.secondaryEffect)
            {
                i = 1;
            }

            int j = this.pos.getX();
            int k = this.pos.getY();
            int l = this.pos.getZ();
            BoundingBox axisalignedbb = (new BoundingBox((double)j, (double)k, (double)l, (double)(j + 1), (double)(k + 1), (double)(l + 1))).expand(d0, d0, d0).addCoord(0.0D, (double)World.MAX_SIZE_Y, 0.0D);
            List<EntityLiving> list = this.worldObj.<EntityLiving>getEntitiesWithinAABB(EntityLiving.class, axisalignedbb);

            for (EntityLiving entityplayer : list)
            {
                entityplayer.addEffect(new PotionEffect(this.primaryEffect, 180, i, true, true));
            }

            if (this.levels >= 4 && this.primaryEffect != this.secondaryEffect && this.secondaryEffect != null)
            {
                for (EntityLiving entityplayer1 : list)
                {
                    entityplayer1.addEffect(new PotionEffect(this.secondaryEffect, 180, 0, true, true));
                }
            }
        }
    }
    
    private void calculateLevels() {
        int j = this.pos.getX();
        int k = this.pos.getY();
        int l = this.pos.getZ();
    	if (this.isComplete)
        {
            for (int l1 = 1; l1 <= 4; this.levels = l1++)
            {
                int i2 = k - l1;

                if (i2 < 0)
                {
                    break;
                }

                boolean flag1 = true;

                for (int j1 = j - l1; j1 <= j + l1 && flag1; ++j1)
                {
                    for (int k1 = l - l1; k1 <= l + l1; ++k1)
                    {
                        Block block = this.worldObj.getState(new BlockPos(j1, i2, k1)).getBlock();

                        if (block != Blocks.emerald_block && block != Blocks.gold_block && block != Blocks.diamond_block && block != Blocks.iron_block)
                        {
                            flag1 = false;
                            break;
                        }
                    }
                }

                if (!flag1)
                {
                    break;
                }
            }

            if (this.levels == 0)
            {
                this.isComplete = false;
            }
        }
    }

    private void updateSegment()
    {
//        int i = this.levels;
        int j = this.pos.getX();
        int k = this.pos.getY();
        int l = this.pos.getZ();
        this.levels = 0;
        this.isComplete = true;
        BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();

        for (int i1 = k + 1; i1 < 512; ++i1)
        {
            State iblockstate = this.worldObj.getState(blockpos$mutableblockpos.set(j, i1, l));

            if (!(iblockstate.getBlock() instanceof BlockStainedGlass) && !(iblockstate.getBlock() instanceof BlockStainedGlassPane) 
            		&& iblockstate.getBlock().getLightOpacity() >= 15 && iblockstate.getBlock() != Blocks.bedrock) {
                this.isComplete = false;
                break;
            }
        }

        this.calculateLevels();

//        if (this.levels == 4 && i < this.levels)
//        {
//            for (EntityNPC entityplayer : this.worldObj.getEntitiesWithinAABB(EntityNPC.class, (new AxisAlignedBB((double)j, (double)k, (double)l, (double)j, (double)(k - 4), (double)l)).expand(10.0D, 5.0D, 10.0D)))
//            {
//                entityplayer.triggerAchievement(AchievementList.fullBeacon);
//            }
//        }
        
        this.addEffectsToPlayers();
    }

//    private void updateSegmentColors()
//    {
//        int i = this.levels;
//        int j = this.pos.getX();
//        int k = this.pos.getY();
//        int l = this.pos.getZ();
//        this.levels = 0;
//        this.beamSegments.clear();
//        this.isComplete = true;
//        TileEntityBeacon.BeamSegment tileentitybeacon$beamsegment = new TileEntityBeacon.BeamSegment(EntitySheep.getDyeRgb(DyeColor.WHITE));
//        this.beamSegments.add(tileentitybeacon$beamsegment);
//        boolean flag = true;
//        BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
//
//        for (int i1 = k + 1; i1 < 512; ++i1)
//        {
//            State iblockstate = this.worldObj.getState(blockpos$mutableblockpos.set(j, i1, l));
//            float[] afloat;
//
//            if (iblockstate.getBlock() == Blocks.stained_glass)
//            {
//                afloat = EntitySheep.getDyeRgb((DyeColor)iblockstate.getValue(BlockStainedGlass.COLOR));
//            }
//            else
//            {
//                if (iblockstate.getBlock() != Blocks.stained_glass_pane)
//                {
//                    if (iblockstate.getBlock().getLightOpacity() >= 15 && iblockstate.getBlock() != Blocks.bedrock)
//                    {
//                        this.isComplete = false;
//                        this.beamSegments.clear();
//                        break;
//                    }
//
//                    tileentitybeacon$beamsegment.incrementHeight();
//                    continue;
//                }
//
//                afloat = EntitySheep.getDyeRgb((DyeColor)iblockstate.getValue(BlockStainedGlassPane.COLOR));
//            }
//
//            if (!flag)
//            {
//                afloat = new float[] {(tileentitybeacon$beamsegment.getColors()[0] + afloat[0]) / 2.0F, (tileentitybeacon$beamsegment.getColors()[1] + afloat[1]) / 2.0F, (tileentitybeacon$beamsegment.getColors()[2] + afloat[2]) / 2.0F};
//            }
//
//            if (Arrays.equals(afloat, tileentitybeacon$beamsegment.getColors()))
//            {
//                tileentitybeacon$beamsegment.incrementHeight();
//            }
//            else
//            {
//                tileentitybeacon$beamsegment = new TileEntityBeacon.BeamSegment(afloat);
//                this.beamSegments.add(tileentitybeacon$beamsegment);
//            }
//
//            flag = false;
//        }
//
//        this.calculateLevels();
//    }

//    public List<TileEntityBeacon.BeamSegment> getBeamSegments()
//    {
//        return this.beamSegments;
//    }

//    public float shouldBeamRender()
//    {
//        if (!this.isComplete)
//        {
//            return 0.0F;
//        }
//        else
//        {
//            int delta = (int)(this.worldObj.getTime() - this.lastRenderUpdate);
//            this.lastRenderUpdate = this.worldObj.getTime();
//
//            if (delta > 1)
//            {
//                this.charge -= (float)delta / 40.0F;
//
//                if (this.charge < 0.0F)
//                {
//                    this.charge = 0.0F;
//                }
//            }
//
//            this.charge += 0.025F;
//
//            if (this.charge > 1.0F)
//            {
//                this.charge = 1.0F;
//            }
//
//            return this.charge;
//        	return 1.0F;
//        }
//    }

    /**
     * Allows for a specialized description packet to be created. This is often used to sync tile entity data from the
     * server to the client easily. For example this is used by signs to synchronise the text to be displayed.
     */
    public Packet getDescriptionPacket()
    {
        return new SPacketUpdateTileEntity(this);
    }

    public double getMaxRenderDistanceSquared()
    {
        return 65536.0D;
    }

    private Potion getEffect(String id)
    {
    	Potion potion = Potion.getByName(id);
//        if (potion != null)
//        {
        return potion != Potion.SPEED && potion != Potion.HASTE && potion != Potion.RESISTANCE && potion != Potion.JUMP && potion != Potion.STRENGTH && potion != Potion.REGENERATION ? null : potion;
//        }
//        else
//        {
//            return null;
//        }
    }

    public void readTags(TagObject compound)
    {
        super.readTags(compound);
        this.primaryEffect = compound.hasString("Primary") ? this.getEffect(compound.getString("Primary")) : null;
        this.secondaryEffect = compound.hasString("Secondary") ? this.getEffect(compound.getString("Secondary")) : null;
        this.levels = compound.getInt("Levels");
//        try {
        this.beamColor = DyeColor.getByName(compound.getString("Color"));
//        }
//        catch(IllegalArgumentException e) {
//        	this.beamColor = DyeColor.WHITE;
//        }
    }

    public void writeTags(TagObject compound)
    {
        super.writeTags(compound);
        if(this.primaryEffect != null)
        	compound.setString("Primary", this.primaryEffect.getName());
        if(this.secondaryEffect != null)
        	compound.setString("Secondary", this.secondaryEffect.getName());
        compound.setInt("Levels", this.levels);
        compound.setString("Color", this.beamColor.getName());
    }

    /**
     * Returns the number of slots in the inventory.
     */
//    public int getSizeInventory()
//    {
//        return 1;
//    }

    /**
     * Returns the stack in the given slot.
     */
//    public ItemStack getStackInSlot(int index)
//    {
//        return index == 0 ? this.payment : null;
//    }

    /**
     * Removes up to a specified number of items from an inventory slot and returns them in a new stack.
     */
//    public ItemStack decrStackSize(int index, int count)
//    {
//        if (index == 0 && this.payment != null)
//        {
//            if (count >= this.payment.stackSize)
//            {
//                ItemStack itemstack = this.payment;
//                this.payment = null;
//                return itemstack;
//            }
//            else
//            {
//                this.payment.stackSize -= count;
//                return new ItemStack(this.payment.getItem(), count, this.payment.getMetadata());
//            }
//        }
//        else
//        {
//            return null;
//        }
//    }
//
//    /**
//     * Removes a stack from the given slot and returns it.
//     */
//    public ItemStack removeStackFromSlot(int index)
//    {
//        if (index == 0 && this.payment != null)
//        {
//            ItemStack itemstack = this.payment;
//            this.payment = null;
//            return itemstack;
//        }
//        else
//        {
//            return null;
//        }
//    }
//
//    /**
//     * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
//     */
//    public void setInventorySlotContents(int index, ItemStack stack)
//    {
//        if (index == 0)
//        {
//            this.payment = stack;
//        }
//    }

    /**
     * Get the name of this object. For players this returns their username
     */
//    public String getName()
//    {
//        return this.hasCustomName() ? this.customName : "Leuchtfeuer";
//    }

    /**
     * Returns true if this thing is named
     */
//    public boolean hasCustomName()
//    {
//        return this.customName != null && this.customName.length() > 0;
//    }
//
//    public void setName(String name)
//    {
//        this.customName = name;
//    }

    /**
     * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended.
     */
//    public int getInventoryStackLimit()
//    {
//        return 1;
//    }

    /**
     * Do not make give this method the name canInteractWith because it clashes with Container
     */
//    public boolean isUseableByPlayer(EntityNPC player)
//    {
//        return this.worldObj.getTileEntity(this.pos) != this ? false : player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) <= 64.0D;
//    }
//
//    public void openInventory(EntityNPC player)
//    {
//    }
//
//    public void closeInventory(EntityNPC player)
//    {
//    }

    /**
     * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
     */
//    public boolean isItemValidForSlot(int index, ItemStack stack)
//    {
//        return stack.getItem() == Items.emerald || stack.getItem() == Items.diamond || stack.getItem() == Items.gold_ingot || stack.getItem() == Items.iron_ingot;
//    }
//
//    public String getGuiID()
//    {
//        return "beacon";
//    }
//
//    public Container createContainer(InventoryPlayer playerInventory, EntityNPC playerIn)
//    {
//        return new ContainerBeacon(playerInventory, this);
//    }
//
//    public int getField(int id)
//    {
//        switch (id)
//        {
//            case 0:
//                return this.levels;
//
//            case 1:
//                return this.primaryEffect;
//
//            case 2:
//                return this.secondaryEffect;
//
//            default:
//                return 0;
//        }
//    }
//
//    public void setField(int id, int value)
//    {
//        switch (id)
//        {
//            case 0:
//                this.levels = value;
//                break;
//
//            case 1:
//                this.primaryEffect = this.func_183001_h(value);
//                break;
//
//            case 2:
//                this.secondaryEffect = this.func_183001_h(value);
//        }
//    }
//
//    public int getFieldCount()
//    {
//        return 3;
//    }
//
//    public void clear()
//    {
//        this.payment = null;
//    }

    public boolean receiveClientEvent(int id, int type)
    {
        if (id == 1)
        {
            this.beamColor = DyeColor.byMetadata(type);
            return true;
        }
        else
        {
            return super.receiveClientEvent(id, type);
        }
    }
    
    public int getColor() {
    	return 0xff00ff;
    }
    
    public int getBeamColor() {
    	return this.beamColor.getColor();
    }
    
    public void setBeamColor(DyeColor color) {
    	this.beamColor = color;
    	if(!this.worldObj.client)
    		this.worldObj.addBlockEvent(this.pos, this.getBlockType(), 1, color.getMetadata());
    }

//    public static class BeamSegment
//    {
//        private final float[] colors;
//        private int height;
//
//        public BeamSegment(float[] p_i45669_1_)
//        {
//            this.colors = p_i45669_1_;
//            this.height = 1;
//        }
//
//        protected void incrementHeight()
//        {
//            ++this.height;
//        }
//
//        public float[] getColors()
//        {
//            return this.colors;
//        }
//
//        public int getHeight()
//        {
//            return this.height;
//        }
//    }
}
