package crazypants.enderzoo.entity;

import crazypants.enderzoo.config.Config;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;

public class EntityFallenMount extends EntityHorse implements IEnderZooMob {

  public static final int EGG_BG_COL = 0x365A25;
  public static final int EGG_FG_COL = 0xA0A0A0;
  public static final String NAME = "fallenmount";

  public static final double MOUNTED_ATTACK_MOVE_SPEED = Config.fallenMountChargeSpeed;;

  private boolean wasRidden = false;
  private final EntityAINearestAttackableTarget<EntityPlayer> findTargetAI;
  private EntityAIAttackMelee attackAI;

  private ItemStack armor = ItemStack.EMPTY;

  public EntityFallenMount(World world) {
    super(world);
    setGrowingAge(0);
    setHorseSaddled(true);

    tasks.taskEntries.clear();
    tasks.addTask(0, new EntityAISwimming(this));
    tasks.addTask(6, new EntityAIWander(this, 1.2D));
    tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
    tasks.addTask(8, new EntityAILookIdle(this));

    findTargetAI = new EntityAINearestAttackableTarget<EntityPlayer>(this, EntityPlayer.class, true);
    attackAI = new EntityAIAttackMelee(this, MOUNTED_ATTACK_MOVE_SPEED, false);
    updateAttackAI(); 
  }

  @Override
  protected void applyEntityAttributes() {
    super.applyEntityAttributes();
    getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE);
    MobInfo.FALLEN_MOUNT.applyAttributes(this);
  }

  @Override
  protected boolean isMovementBlocked() {
    return isRearing();
  }

  @Override
  public boolean processInteract(EntityPlayer player, EnumHand hand) {
    ItemStack itemstack = player.inventory.getCurrentItem();
    if(itemstack.getItem() == Items.SPAWN_EGG) {
      return super.processInteract(player, hand);
    }
    return false;
  }

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

  @Override
  public boolean canMateWith(EntityAnimal p_70878_1_) {
    return false;
  }
  
  @Override
  public boolean canBeLeashedTo(EntityPlayer player) {    
    return false;
  }

  @Override
  public boolean isBreedingItem(ItemStack p_70877_1_) {   
    return false;
  }  

  @Override
  public boolean isCreatureType(EnumCreatureType type, boolean forSpawnCount) {    
    if(type == EnumCreatureType.MONSTER) {      
      return true;
    }
    return false;    
  }

  @Override
  public IEntityLivingData onInitialSpawn(DifficultyInstance di, IEntityLivingData data) {  

    setHorseArmorStack(ItemStack.EMPTY);        
    setHorseSaddled(true);    
    setGrowingAge(0);
    getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(Config.fallenMountHealth);
    getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.2);
    getAttributeMap().getAttributeInstanceByName("horse.jumpStrength").setBaseValue(0.5);
    setHealth(getMaxHealth());
    
    float chanceOfArmor = world.getDifficulty() == EnumDifficulty.HARD ? Config.fallenMountChanceArmoredHard
        : Config.fallenMountChanceArmored;
    if(rand.nextFloat() <= chanceOfArmor) {

      //Value between 0 and 1 (normal) - 1.5 based on how long a chunk has been occupied and the moon phase
      
      //float occupiedDiffcultyMultiplier = worldObj.func_147462_b(posX, posY, posZ);
      
      float occupiedDiffcultyMultiplier = di.getClampedAdditionalDifficulty();
      //TODO: Do I need this normalised still?
      occupiedDiffcultyMultiplier /= 1.5f; // normalize
      float chanceImprovedArmor = world.getDifficulty() == EnumDifficulty.HARD ? Config.fallenMountChanceArmorUpgradeHard
          : Config.fallenMountChanceArmorUpgrade;
      chanceImprovedArmor *= (1 + occupiedDiffcultyMultiplier); //If we have the max occupied factor, double the chance of improved armor

      int armorLevel = 0;
      for (int i = 0; i < 2; i++) {
        if(rand.nextFloat() <= chanceImprovedArmor) {
          armorLevel++;
        }
      }
      Item armorItem = Items.IRON_HORSE_ARMOR;
      switch (armorLevel) {
      case 1:
        armorItem = Items.GOLDEN_HORSE_ARMOR;
        break;
      case 2:
        armorItem = Items.DIAMOND_HORSE_ARMOR;
        break;
      }
      armor = new ItemStack(armorItem);
      setHorseArmorStack(armor);
    } else {
      armor = ItemStack.EMPTY;
      setHorseArmorStack(armor);
    }
    return data;
  }

  @Override
  public void onUpdate() {
    super.onUpdate();
    if(!world.isRemote && world.getDifficulty() == EnumDifficulty.PEACEFUL) {
      setDead();
    }
  }

  @Override
  public void onLivingUpdate() {

    super.onLivingUpdate();

    if(world.isDaytime() && !world.isRemote) {
      if(burnInSun() && world.getTotalWorldTime() % 20 == 0) {
        float f = getBrightness();
        if(f > 0.5F && rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F
            && world.canBlockSeeSky(new BlockPos(MathHelper.floor(posX), MathHelper.floor(posY), MathHelper.floor(posZ)))) {
          setFire(8);
        }
      }
    }
    setEatingHaystack(false);    

    if(wasRidden != isRidden()) {
      updateAttackAI();
      wasRidden = isRidden();
    }
  }

  
  private boolean burnInSun() {        
    if(!isRidden()) {
      return getTotalArmorValue() == 0;
    }    
    if(Config.fallenMountShadedByRider) {
      return false;
    }
    return getTotalArmorValue() > 0;
  }

  protected boolean isRidden() {    
    return !getPassengers().isEmpty();
  }

  private void updateAttackAI() {
    targetTasks.removeTask(findTargetAI);
    tasks.removeTask(attackAI);
    if(!isRidden()) {
      targetTasks.addTask(2, findTargetAI);
      tasks.addTask(4, attackAI);
    }
  }

  @Override
  public boolean attackEntityAsMob(Entity target) {
    if(isRidden() || isDead) {
      return false;
    }
    super.attackEntityAsMob(target);
    if(!isRearing()) {
      makeMad();
    }
    float damage = (float) getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue();
    return target.attackEntityFrom(DamageSource.causeMobDamage(this), damage);
  }

  @Override
  public void writeEntityToNBT(NBTTagCompound root) {
    super.writeEntityToNBT(root);
    NBTTagCompound armTag = new NBTTagCompound();
    armor.writeToNBT(armTag);
    root.setTag("armor", armTag);
  }

  @Override
  public void readEntityFromNBT(NBTTagCompound root) {
    super.readEntityFromNBT(root);
    setHorseSaddled(true);
    if(root.hasKey("armor")) {
      NBTTagCompound armTag = root.getCompoundTag("armor");
      armor = new ItemStack(armTag);
      setHorseArmorStack(armor);
    } else {
      armor = ItemStack.EMPTY;
      setHorseArmorStack(armor);
    }
  }


}