package common.village;

import java.util.Iterator;
import java.util.List;

import common.block.Block;
import common.block.BlockDoor;
import common.collect.Lists;
import common.material.Material;
import common.nbt.NBTTagCompound;
import common.nbt.NBTTagList;
import common.util.BlockPos;
import common.world.AWorldServer;

public class Village
{
    private final List<VillageDoorInfo> doors = Lists.<VillageDoorInfo>newArrayList();
    
    private BlockPos doorRange = BlockPos.ORIGIN;
    private BlockPos center = BlockPos.ORIGIN;
    private int radius;

//    public Village()
//    {
//    }
//
//    public Village(IWorldServer worldIn)
//    {
//        this.worldObj = worldIn;
//    }
//
//    public void setWorld(IWorldServer worldIn)
//    {
//        this.worldObj = worldIn;
//    }
    
    public void tick(AWorldServer world, int counter)
    {
//        this.tickCounter = counter;
        boolean mod = false;
        boolean reset = world.rand.zrange(50) == 0;
        Iterator<VillageDoorInfo> iterator = this.doors.iterator();

        while (iterator.hasNext())
        {
            VillageDoorInfo villagedoorinfo = (VillageDoorInfo)iterator.next();

            if (reset)
            {
                villagedoorinfo.resetDoorOpeningRestrictionCounter();
            }

            if (!this.isWoodDoor(world, villagedoorinfo.getDoorBlockPos()) || Math.abs(counter - villagedoorinfo.getInsidePosY()) > 1200)
            {
                this.doorRange = this.doorRange.subtract(villagedoorinfo.getDoorBlockPos());
                mod = true;
                villagedoorinfo.setIsDetachedFromVillageFlag(true);
                iterator.remove();
            }
        }

        if (mod)
        {
            this.updatePosition();
        }
    }

    public BlockPos getCenter()
    {
        return this.center;
    }

    public int getRadius()
    {
        return this.radius;
    }

//    public int getNumDoors()
//    {
//        return this.doors.size();
//    }

//    public int getSinceLastDoor()
//    {
//        return this.tickCounter - this.lastDoor;
//    }

//    public int getNumVillagers()
//    {
//        return this.numVillagers;
//    }

//    public boolean isInside(BlockPos pos)
//    {
//        return this.center.distanceSq(pos) < (double)(this.radius * this.radius);
//    }

    public List<VillageDoorInfo> getDoorList()
    {
        return this.doors;
    }

    public VillageDoorInfo getNearestDoor(BlockPos pos)
    {
        VillageDoorInfo villagedoorinfo = null;
        int i = Integer.MAX_VALUE;

        for (VillageDoorInfo villagedoorinfo1 : this.doors)
        {
            int j = villagedoorinfo1.getDistanceToDoorBlockSq(pos);

            if (j < i)
            {
                villagedoorinfo = villagedoorinfo1;
                i = j;
            }
        }

        return villagedoorinfo;
    }

    public VillageDoorInfo getDoorInfo(BlockPos pos)
    {
        VillageDoorInfo villagedoorinfo = null;
        int i = Integer.MAX_VALUE;

        for (VillageDoorInfo villagedoorinfo1 : this.doors)
        {
            int j = villagedoorinfo1.getDistanceToDoorBlockSq(pos);

            if (j > 256)
            {
                j = j * 1000;
            }
            else
            {
                j = villagedoorinfo1.getDoorOpeningRestrictionCounter();
            }

            if (j < i)
            {
                villagedoorinfo = villagedoorinfo1;
                i = j;
            }
        }

        return villagedoorinfo;
    }

    public VillageDoorInfo getExistedDoor(BlockPos doorBlock)
    {
        if (this.center.distanceSq(doorBlock) > (double)(this.radius * this.radius))
        {
            return null;
        }
        else
        {
            for (VillageDoorInfo villagedoorinfo : this.doors)
            {
                if (villagedoorinfo.getDoorBlockPos().getX() == doorBlock.getX() && villagedoorinfo.getDoorBlockPos().getZ() == doorBlock.getZ() && Math.abs(villagedoorinfo.getDoorBlockPos().getY() - doorBlock.getY()) <= 1)
                {
                    return villagedoorinfo;
                }
            }

            return null;
        }
    }

    public void addDoor(VillageDoorInfo doorInfo)
    {
        this.doors.add(doorInfo);
        this.doorRange = this.doorRange.add(doorInfo.getDoorBlockPos());
        this.updatePosition();
//        this.lastDoor = doorInfo.getInsidePosY();
    }

    public boolean isAnnihilated()
    {
        return this.doors.isEmpty();
    }

    private boolean isWoodDoor(AWorldServer world, BlockPos pos)
    {
        Block block = world.getState(pos).getBlock();
        return block instanceof BlockDoor ? block.getMaterial() == Material.wood : false;
    }

    private void updatePosition()
    {
        int i = this.doors.size();

        if (i == 0)
        {
            this.center = new BlockPos(0, 0, 0);
            this.radius = 0;
        }
        else
        {
            this.center = new BlockPos(this.doorRange.getX() / i, this.doorRange.getY() / i, this.doorRange.getZ() / i);
            int j = 0;

            for (VillageDoorInfo villagedoorinfo : this.doors)
            {
                j = Math.max(villagedoorinfo.getDistanceToDoorBlockSq(this.center), j);
            }

            this.radius = Math.max(32, (int)Math.sqrt((double)j) + 1);
        }
    }

    public void readVillageDataFromNBT(NBTTagCompound compound)
    {
//        this.numVillagers = compound.getInteger("PopSize");
        this.radius = compound.getInteger("Radius");
//        this.lastDoor = compound.getInteger("Stable");
//        this.tickCounter = compound.getInteger("Tick");
//        this.noBreedTicks = compound.getInteger("MTick");
        this.center = new BlockPos(compound.getInteger("CX"), compound.getInteger("CY"), compound.getInteger("CZ"));
        this.doorRange = new BlockPos(compound.getInteger("ACX"), compound.getInteger("ACY"), compound.getInteger("ACZ"));
        NBTTagList nbttaglist = compound.getTagList("Doors", 10);

        for (int i = 0; i < nbttaglist.tagCount(); ++i)
        {
            NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
            VillageDoorInfo villagedoorinfo = new VillageDoorInfo(new BlockPos(nbttagcompound.getInteger("X"), nbttagcompound.getInteger("Y"), nbttagcompound.getInteger("Z")), nbttagcompound.getInteger("IDX"), nbttagcompound.getInteger("IDZ"), nbttagcompound.getInteger("TS"));
            this.doors.add(villagedoorinfo);
        }
    }

    public void writeVillageDataToNBT(NBTTagCompound compound)
    {
//        compound.setInteger("PopSize", this.numVillagers);
        compound.setInteger("Radius", this.radius);
//        compound.setInteger("Stable", this.lastDoor);
//        compound.setInteger("Tick", this.tickCounter);
//        compound.setInteger("MTick", this.noBreedTicks);
        compound.setInteger("CX", this.center.getX());
        compound.setInteger("CY", this.center.getY());
        compound.setInteger("CZ", this.center.getZ());
        compound.setInteger("ACX", this.doorRange.getX());
        compound.setInteger("ACY", this.doorRange.getY());
        compound.setInteger("ACZ", this.doorRange.getZ());
        NBTTagList nbttaglist = new NBTTagList();

        for (VillageDoorInfo villagedoorinfo : this.doors)
        {
            NBTTagCompound nbttagcompound = new NBTTagCompound();
            nbttagcompound.setInteger("X", villagedoorinfo.getDoorBlockPos().getX());
            nbttagcompound.setInteger("Y", villagedoorinfo.getDoorBlockPos().getY());
            nbttagcompound.setInteger("Z", villagedoorinfo.getDoorBlockPos().getZ());
            nbttagcompound.setInteger("IDX", villagedoorinfo.getInsideOffsetX());
            nbttagcompound.setInteger("IDZ", villagedoorinfo.getInsideOffsetZ());
            nbttagcompound.setInteger("TS", villagedoorinfo.getInsidePosY());
            nbttaglist.appendTag(nbttagcompound);
        }

        compound.setTag("Doors", nbttaglist);
    }
}
