package org.amitcraft.entity;

import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.ai.EntityAIArrowAttack;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveThroughVillage;
import net.minecraft.entity.ai.EntityAIMoveTowardsTarget;
import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIPanic;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;

import org.amitcraft.core.AmitReference;

public class EntityBehlmann extends EntityMob implements IRangedAttackMob {
	private int teleportDelay = 0;

	public EntityBehlmann(World par1World) {
		super(par1World);
		this.texture = AmitReference.Sprites.MOB_TEXTURE_PATH + "behlmann.png";
		this.moveSpeed = this.stepHeight = 1.0F;

		this.getNavigator().setAvoidsWater(true);
		this.getNavigator().setCanSwim(true);

		this.tasks.addTask(1, new EntityAIArrowAttack(this, 0.25F, 20, 10.0F));
		this.tasks.addTask(2, new EntityAIAttackOnCollide(this, 0.25F, true));
		this.tasks.addTask(3, new EntityAIMoveTowardsTarget(this, 0.22F, 32.0F));
		this.tasks.addTask(4, new EntityAIMoveThroughVillage(this, 0.16F, true));
		this.tasks.addTask(5, new EntityAIMoveTwardsRestriction(this, 0.16F));
		this.tasks.addTask(6, new EntityAIWander(this, 0.16F));
		this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
		this.tasks.addTask(8, new EntityAILookIdle(this));
		this.tasks.addTask(9, new EntityAIPanic(this, 0.38F));
		this.tasks.addTask(10, new EntityAITempt(this, 0.25F, Block.brewingStand.blockID, false));
		this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
		this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityAnimal.class, 16.0F, 0, false));
	}

	/**
	 * Returns the sound this mob makes on death.
	 */
	@Override
	protected String getDeathSound() {
		return AmitReference.Sounds.BEHLMANN_DEATH_SOUND;
	}

	@Override
	public int getMaxHealth() {
		return 50;
	}

	@Override
	public int getAttackStrength(Entity par1Entity) {
		return 1999;
	}

	@Override
	protected boolean isAIEnabled() {
		return true;
	}

	@Override
	public String getTexture() {
		return AmitReference.Sprites.MOB_TEXTURE_PATH + "behlmann.png";
	}

	@Override
	public int getDropItemId() {
		return Item.brewingStand.itemID;
	}

	@Override
	public void onLivingUpdate() {
		this.moveSpeed = this.entityToAttack != null ? 6.5F : 0.3F;
		int i;

		for (i = 0; i < 2; ++i)
			this.worldObj.spawnParticle("portal", this.posX + (this.rand.nextDouble() - 0.5D) * this.width, this.posY + this.rand.nextDouble() * this.height - 0.25D, this.posZ + (this.rand.nextDouble() - 0.5D) * this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);

		if (this.worldObj.isDaytime() && !this.worldObj.isRemote) {
			float f = this.getBrightness(1.0F);

			if (f > 0.5F && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) {
				this.entityToAttack = null;
				this.teleportRandomly();
			}
		}

		if (this.isBurning()) {
			this.entityToAttack = null;
			this.teleportRandomly();
		}

		this.isJumping = false;

		if (this.entityToAttack != null) this.faceEntity(this.entityToAttack, 100.0F, 100.0F);

		if (!this.worldObj.isRemote && this.isEntityAlive()) if (this.entityToAttack != null) {
			if (this.entityToAttack instanceof EntityPlayer && this.shouldAttackPlayer((EntityPlayer) this.entityToAttack)) {
				this.moveStrafing = this.moveForward = 0.0F;
				this.moveSpeed = 0.0F;

				if (this.entityToAttack.getDistanceSqToEntity(this) < 16.0D) this.teleportRandomly();

				this.teleportDelay = 0;
			} else if (this.entityToAttack.getDistanceSqToEntity(this) > 256.0D && this.teleportDelay++ >= 30 && this.teleportToEntity(this.entityToAttack)) this.teleportDelay = 0;
		} else
			this.teleportDelay = 0;

		super.onLivingUpdate();
	}

	// Code stolen from an enderman
	/**
	 * Teleport the enderman to a random nearby position
	 */
	protected boolean teleportRandomly() {
		double d0 = this.posX + (this.rand.nextDouble() - 0.5D) * 64.0D;
		double d1 = this.posY + (this.rand.nextInt(64) - 32);
		double d2 = this.posZ + (this.rand.nextDouble() - 0.5D) * 64.0D;
		return this.teleportTo(d0, d1, d2);
	}

	/**
	 * Teleport the enderman to another entity
	 */
	protected boolean teleportToEntity(Entity par1Entity) {
		Vec3 vec3 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX - par1Entity.posX, this.boundingBox.minY + this.height / 2.0F - par1Entity.posY + par1Entity.getEyeHeight(), this.posZ - par1Entity.posZ);
		vec3 = vec3.normalize();
		double d0 = 16.0D;
		double d1 = this.posX + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3.xCoord * d0;
		double d2 = this.posY + (this.rand.nextInt(16) - 8) - vec3.yCoord * d0;
		double d3 = this.posZ + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3.zCoord * d0;
		return this.teleportTo(d1, d2, d3);
	}

	/**
	 * Teleport the enderman
	 */
	protected boolean teleportTo(double par1, double par3, double par5) {
		double d3 = this.posX;
		double d4 = this.posY;
		double d5 = this.posZ;
		this.posX = par1;
		this.posY = par3;
		this.posZ = par5;
		boolean flag = false;
		int i = MathHelper.floor_double(this.posX);
		int j = MathHelper.floor_double(this.posY);
		int k = MathHelper.floor_double(this.posZ);
		int l;

		if (this.worldObj.blockExists(i, j, k)) {
			boolean flag1 = false;

			while (!flag1 && j > 0) {
				l = this.worldObj.getBlockId(i, j - 1, k);

				if (l != 0 && Block.blocksList[l].blockMaterial.blocksMovement())
					flag1 = true;
				else {
					--this.posY;
					--j;
				}
			}

			if (flag1) {
				this.setPosition(this.posX, this.posY, this.posZ);

				if (this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox)) flag = true;
			}
		}

		if (!flag) {
			this.setPosition(d3, d4, d5);
			return false;
		} else {
			short short1 = 128;

			for (l = 0; l < short1; ++l) {
				double d6 = l / (short1 - 1.0D);
				float f = (this.rand.nextFloat() - 0.5F) * 0.2F;
				float f1 = (this.rand.nextFloat() - 0.5F) * 0.2F;
				float f2 = (this.rand.nextFloat() - 0.5F) * 0.2F;
				double d7 = d3 + (this.posX - d3) * d6 + (this.rand.nextDouble() - 0.5D) * this.width * 2.0D;
				double d8 = d4 + (this.posY - d4) * d6 + this.rand.nextDouble() * this.height;
				double d9 = d5 + (this.posZ - d5) * d6 + (this.rand.nextDouble() - 0.5D) * this.width * 2.0D;
				this.worldObj.spawnParticle("portal", d7, d8, d9, f, f1, f2);
			}

			this.worldObj.playSoundEffect(d3, d4, d5, "mob.endermen.portal", 1.0F, 1.0F);
			this.playSound("mob.endermen.portal", 1.0F, 1.0F);
			return true;
		}
	}

	private boolean shouldAttackPlayer(EntityPlayer par1EntityPlayer) {
		ItemStack var2 = par1EntityPlayer.inventory.armorInventory[3];

		if (var2 != null && var2.itemID == Block.pumpkin.blockID)
			return false;
		else {
			Vec3 var3 = par1EntityPlayer.getLook(1.0F).normalize();
			Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX - par1EntityPlayer.posX, this.boundingBox.minY + this.height / 2.0F - (par1EntityPlayer.posY + par1EntityPlayer.getEyeHeight()), this.posZ - par1EntityPlayer.posZ);
			double var5 = var4.lengthVector();
			var4 = var4.normalize();
			double var7 = var3.dotProduct(var4);
			return var7 > 1.0D - 0.025D / var5 ? par1EntityPlayer.canEntityBeSeen(this) : false;
		}
	}

	/**
	 * Called when a lightning bolt hits the entity.
	 */
	@Override
	public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) {
		this.worldObj.spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, EntityXPOrb.getXPSplit(1000)));
		super.onStruckByLightning(par1EntityLightningBolt);
	}

	@Override
	public void attackEntityWithRangedAttack(EntityLiving entityliving, float f) {
		double var3 = entityliving.posX - this.posX;
		double var5 = entityliving.boundingBox.minY + entityliving.height / 2.0F - (this.posY + this.height / 2.0F);
		double var7 = entityliving.posZ - this.posZ;

		EntitySmallFireball var11 = new EntitySmallFireball(this.worldObj, this, var3 + this.rand.nextGaussian(), var5, var7 + this.rand.nextGaussian());
		var11.posY = this.posY + this.height / 2.0F + 0.5D;
		this.worldObj.spawnEntityInWorld(var11);

	}

}