package crazypants.enderzoo.entity;

import java.util.List;

import javax.annotation.Nullable;

import crazypants.enderzoo.config.Config;
import crazypants.enderzoo.entity.ai.EntityAIAttackOnCollideAggressive;
import crazypants.enderzoo.entity.ai.EntityAINearestAttackableTargetBounded;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILeapAtTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class EntityDireWolf extends EntityMob implements IEnderZooMob {

  public static final String NAME = "direwolf";
  public static final int EGG_BG_COL = 0x606060;
  public static final int EGG_FG_COL = 0xA0A0A0;

  private static final SoundEvent SND_HURT = new SoundEvent(new ResourceLocation("enderzoo:direwolf.hurt"));
  private static final SoundEvent SND_HOWL = new SoundEvent(new ResourceLocation("enderzoo:direwolf.howl"));
  private static final SoundEvent SND_GROWL = new SoundEvent(new ResourceLocation("enderzoo:direwolf.growl"));
  private static final SoundEvent SND_DEATH = new SoundEvent(new ResourceLocation("enderzoo:direwolf.death"));

//  private static final int ANGRY_INDEX = 12;
  private static final DataParameter<Boolean> ANGRY_INDEX = EntityDataManager.<Boolean>createKey(EntityDireWolf.class, DataSerializers.BOOLEAN);

  private EntityLivingBase previsousAttackTarget;

  private static int packHowl = 0;
  private static long lastHowl = 0;

  public EntityDireWolf(World world) {
    super(world);
    setSize(0.8F, 1.2F);
    //getNavigator().setAvoidsWater(true);
//    ((PathNavigateGround) this.getNavigator()).setAvoidsWater(true);
    tasks.addTask(1, new EntityAISwimming(this));
    tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
    tasks.addTask(4, new EntityAIAttackOnCollideAggressive(this, 1.1D, true).setAttackFrequency(20));
    tasks.addTask(7, new EntityAIWander(this, 0.5D));
    tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
    tasks.addTask(9, new EntityAILookIdle(this));
    targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));

    if(Config.direWolfAggresiveRange > 0) {      
      EntityAINearestAttackableTargetBounded<EntityPlayer> nearTarg = new EntityAINearestAttackableTargetBounded<EntityPlayer>(this, EntityPlayer.class, true);
      nearTarg.setMaxDistanceToTarget(Config.direWolfAggresiveRange);
      targetTasks.addTask(2, nearTarg);
    }
  }

  @Override
  protected void entityInit() {
    super.entityInit();
    dataManager.register(ANGRY_INDEX, Boolean.FALSE);
    updateAngry();
  }

  public boolean isAngry() {
    return dataManager.get(ANGRY_INDEX);
  }

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

  @Override
  public int getMaxSpawnedInChunk() {
    return 6;
  }

  //  @Override
  //  public boolean isCreatureType(EnumCreatureType type, boolean forSpawnCount) {
  //    System.out.println("EntityDireWolf.isCreatureType: " + type);
  //    return type.getCreatureClass().isAssignableFrom(this.getClass());
  //  }

  private void updateAngry() {
    dataManager.set(ANGRY_INDEX, getAttackTarget() != null ? Boolean.TRUE : Boolean.FALSE);
  }

  @Override
  protected void applyEntityAttributes() {
    super.applyEntityAttributes();
    getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
    getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(40.0D);
    MobInfo.DIRE_WOLF.applyAttributes(this);
  }

  @Override
  protected void playStepSound(BlockPos bp, Block p_145780_4_) {
    playSound(SoundEvents.ENTITY_WOLF_STEP, 0.15F, 1.0F);
  }

  @Override
  protected SoundEvent getAmbientSound() {
    if (isAngry()) {
      return SND_GROWL;
    }
    if (EntityUtil.isPlayerWithinRange(this, 12)) {
      return SND_GROWL;
    }
    boolean howl = (packHowl > 0 || rand.nextFloat() <= Config.direWolfHowlChance) && world.getTotalWorldTime() > (lastHowl + 10);
    if (howl) {
      if (packHowl <= 0 && rand.nextFloat() <= 0.6) {
        packHowl = Config.direWolfPackHowlAmount;
      }
      lastHowl = world.getTotalWorldTime();
      packHowl = Math.max(packHowl - 1, 0);
      return SND_HOWL;
    } else {
      return SND_GROWL;
    }
  }

  @Override
  public void playSound(SoundEvent sound, float volume, float pitch) {
    if (SND_HOWL.equals(sound)) {
      volume *= (float) Config.direWolfHowlVolumeMult;
      pitch *= 0.8f;
    }
    world.playSound(posX,posY,posZ, sound, SoundCategory.NEUTRAL, volume, pitch, true);
  }

  @Override
  protected SoundEvent getHurtSound(DamageSource source) {
    return SND_HURT;
  }

  @Override
  protected SoundEvent getDeathSound() {
    return SND_DEATH;
  }

  @Override
  public float getEyeHeight() {
    return height * 0.8F;
  }

  @Override
  protected float getSoundVolume() {
    return 0.4F;
  }

  @Override
  protected Item getDropItem() {
    return Item.getItemById(-1);
  }

  @Override
  @Nullable
  protected ResourceLocation getLootTable() {
    return null; // use getDropItem() instead
  }

  public float getTailRotation() {
    if (isAngry()) {
      return (float) Math.PI / 2;
    }
    return (float) Math.PI / 4;
  }

  @Override
  public void setPosition(double x, double y, double z) {
    posX = x;
    posY = y;
    posZ = z;
    //Correct misalignment of bounding box    
    double hw = width / 2.0F;
    double hd = hw * 2.25;
    float f1 = height;

    setEntityBoundingBox(new AxisAlignedBB(
        x - hw, y, z - hd,
        x + hw, y + f1, z + hd));

  }

  @Override
  public void onLivingUpdate() {
    super.onLivingUpdate();
    EntityLivingBase curTarget = getAttackTarget();
    if (curTarget != previsousAttackTarget) {
      if (curTarget != null) {
        doGroupArgo(curTarget);
      }
      previsousAttackTarget = getAttackTarget();
      updateAngry();
    }
  }

  private void doGroupArgo(EntityLivingBase curTarget) {
    if (!Config.direWolfPackAttackEnabled) {
      return;
    }
    int range = 16;
    AxisAlignedBB bb = new AxisAlignedBB(posX - range, posY - range, posZ - range, posX + range, posY + range, posZ + range);
    List<EntityDireWolf> pack = world.getEntitiesWithinAABB(EntityDireWolf.class, bb);
    if (pack != null && !pack.isEmpty()) {
      for (EntityDireWolf wolf : pack) {
        if (wolf.getAttackTarget() == null) {
          EntityUtil.cancelCurrentTasks(wolf);
          wolf.setAttackTarget(curTarget);
        }
      }
    }
  }

}