package common.village;

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

import common.block.Block;
import common.block.Material;
import common.block.artificial.BlockDoor;
import common.collect.Lists;
import common.tags.TagObject;
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 readTags(TagObject tag)
    {
        this.radius = tag.getInt("Radius");
        this.center = new BlockPos(tag.getInt("CX"), tag.getInt("CY"), tag.getInt("CZ"));
        this.doorRange = new BlockPos(tag.getInt("ACX"), tag.getInt("ACY"), tag.getInt("ACZ"));
        List<TagObject> doors = tag.getList("Doors");

        for (int i = 0; i < doors.size(); ++i)
        {
            TagObject door = doors.get(i);
            VillageDoorInfo info = new VillageDoorInfo(new BlockPos(door.getInt("X"), door.getInt("Y"), door.getInt("Z")), door.getInt("IDX"), door.getInt("IDZ"), door.getInt("TS"));
            this.doors.add(info);
        }
    }

    public void writeTags(TagObject tag)
    {
        tag.setInt("Radius", this.radius);
        tag.setInt("CX", this.center.getX());
        tag.setInt("CY", this.center.getY());
        tag.setInt("CZ", this.center.getZ());
        tag.setInt("ACX", this.doorRange.getX());
        tag.setInt("ACY", this.doorRange.getY());
        tag.setInt("ACZ", this.doorRange.getZ());
        List<TagObject> doors = Lists.newArrayList();

        for (VillageDoorInfo info : this.doors)
        {
            TagObject door = new TagObject();
            door.setInt("X", info.getDoorBlockPos().getX());
            door.setInt("Y", info.getDoorBlockPos().getY());
            door.setInt("Z", info.getDoorBlockPos().getZ());
            door.setInt("IDX", info.getInsideOffsetX());
            door.setInt("IDZ", info.getInsideOffsetZ());
            door.setInt("TS", info.getInsidePosY());
            doors.add(door);
        }

        tag.setList("Doors", doors);
    }
}
