package common.entity.animal;

import common.ai.EntityAIAttackOnCollide;
import common.ai.EntityAIFollowParent;
import common.ai.EntityAILookIdle;
import common.ai.EntityAIMate;
import common.ai.EntityAINearestAttackableTarget;
import common.ai.EntityAIPanic;
import common.ai.EntityAISwimming;
import common.ai.EntityAITempt;
import common.ai.EntityAIWander;
import common.ai.EntityAIWatchClosest;
import common.entity.DamageSource;
import common.entity.Entity;
import common.entity.npc.Alignment;
import common.entity.npc.EntityNPC;
import common.entity.types.EntityAnimal;
import common.entity.types.EntityLiving;
import common.init.Items;
import common.init.SoundEvent;
import common.item.Item;
import common.item.ItemStack;
import common.tags.TagObject;
import common.util.ExtMath;
import common.vars.Vars;
import common.world.World;

public class EntityChicken extends EntityAnimal {
	private final EntityAIAttackOnCollide attack = new EntityAIAttackOnCollide(this, EntityNPC.class, 1.4, false);
	private final EntityAINearestAttackableTarget targetter = new EntityAINearestAttackableTarget(this, EntityNPC.class, true);
	
	public float wingRotation;
	public float lastWingRotation;
	public float destPos;
	public float lastDestPos;
	private float wingRotDelta = 1.0F;
	private int eggTimer;
	private boolean noEggs;
	private boolean attackSet;

	public EntityChicken(World world) {
		super(world);
		this.setSize(0.4F, 0.7F);
		this.eggTimer = world.client || Vars.eggTimer <= 0 ? 1000 : this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
		this.tasks.addTask(0, new EntityAISwimming(this));
		this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
		this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
		this.tasks.addTask(3, new EntityAITempt(this, 1.0D, Items.wheat, false));
		this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
		this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
		this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
		this.tasks.addTask(7, new EntityAILookIdle(this));
	}

	public float getEyeHeight() {
		return this.height;
	}

	protected void entityInit() {
		super.entityInit();
		this.dataWatcher.addObject(18, Byte.valueOf((byte)0));
	}

	protected void applyEntityAttributes() {
		super.applyEntityAttributes();
		this.setMaxHealth(4);
		this.setSpeedBase(0.25f);
	}

	public void onLivingUpdate() {
		super.onLivingUpdate();
		this.lastWingRotation = this.wingRotation;
		this.lastDestPos = this.destPos;
		this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D);
		this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F);
		if(!this.onGround && this.wingRotDelta < 1.0F)
			this.wingRotDelta = 1.0F;
		this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D);
		if(!this.onGround && this.motionY < 0.0D)
			this.motionY *= 0.6D;
		this.wingRotation += this.wingRotDelta * 2.0F;
		if(!this.worldObj.client) {
			if(Vars.eggTimer > 0 && !this.isChild() && !this.noEggs && --this.eggTimer <= 0) {
				this.playSound(SoundEvent.PLOP, 1.0F);
				this.dropItem(Items.egg, 1);
				this.eggTimer = this.rand.excl(Vars.eggTimer, Vars.eggTimer * 2);
			}
			boolean evil = this.canBeEvil();
			if(evil != this.attackSet) {
				if(evil) {
					this.tasks.addTask(1, this.attack);
					this.targets.addTask(1, this.targetter);
				}
				else {
					this.tasks.removeTask(this.attack);
					this.targets.removeTask(this.targetter);
				}
				this.attackSet = evil;
			}
		}
	}

	public void fall(float distance, float damage) {
	}

	protected SoundEvent getLivingSound() {
		return SoundEvent.CHICKEN_IDLE;
	}

	protected SoundEvent getHurtSound() {
		return SoundEvent.CHICKEN_HIT;
	}

	protected SoundEvent getDeathSound() {
		return SoundEvent.CHICKEN_HIT;
	}

	protected Item getDropItem() {
		return Items.feather;
	}

	protected void dropFewItems(boolean hit, int looting) {
		int amt = this.rand.zrange(3) + this.rand.zrange(1 + looting);
		for(int z = 0; z < amt; z++) {
			this.dropItem(Items.feather, 1);
		}
		this.dropItem(this.isBurning() ? Items.cooked_chicken : Items.chicken, 1);
	}

	public EntityChicken createChild(EntityLiving entity) {
		EntityChicken chick = new EntityChicken(this.worldObj);
		chick.setEvil(this.isEvil());
		chick.setNotLaying(this.isNotLaying());
		return chick;
	}

	public boolean isBreedingItem(ItemStack stack) {
		return stack != null && stack.getItem() == Items.wheat;
	}

	public void readEntity(TagObject tag) {
		super.readEntity(tag);
		this.setEvil(tag.getBool("evil"));
		this.noEggs = tag.getBool("noEggs");
		this.eggTimer = tag.getInt("eggTime");
	}

	public void writeEntity(TagObject tag) {
		super.writeEntity(tag);
		tag.setBool("evil", this.isEvil());
		tag.setBool("noEggs", this.noEggs);
		tag.setInt("eggTime", this.eggTimer);
	}

	public void updateRiderPosition() {
		super.updateRiderPosition();
		float x = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F);
		float z = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F);
		float mult = 0.1F;
		float off = 0.0F;
		this.passenger.setPosition(this.posX + (double)(mult * x),
				this.posY + (double)(this.height * 0.5F) + this.passenger.getYOffset() + (double)off, this.posZ - (double)(mult * z));
		if(this.passenger instanceof EntityLiving)
			((EntityLiving)this.passenger).yawOffset = this.yawOffset;
	}

	public boolean attackEntityAsMob(Entity entityIn) {
    	if(!this.worldObj.client && !Vars.damageMobs)
    		return false;
		return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), this.isChild() ? 1 : 2);
	}
	
	public Object onInitialSpawn(Object livingdata) {
		livingdata = super.onInitialSpawn(livingdata);
		if(Vars.evilChickenChance > 0 && this.rand.chance(Vars.evilChickenChance))
			this.setEvil(true);
		if(this.rand.chance(15))
			this.setGrowingAge(-24000);
		return livingdata;
	}
	
	protected boolean canBeEvil() {
		return this.isEvil() || Vars.aggressiveChickens;
	}

	public boolean isEvil() {
		return this.dataWatcher.getWatchableObjectByte(18) != 0;
	}

	public void setEvil(boolean evil) {
		this.dataWatcher.updateObject(18, (byte)(evil ? 1 : 0));
	}

	public boolean isNotLaying() {
		return this.noEggs;
	}

	public void setNotLaying(boolean noEggs) {
		this.noEggs = noEggs;
	}

	public int getColor() {
		return 0xdb5152;
	}
	
	public Alignment getAlignment() {
		return this.isEvil() ? Alignment.CHAOTIC_EVIL : Alignment.CHAOTIC;
	}
}
