package com.zivilon.cinder_loe.mixins;

import com.zivilon.cinder_loe.CinderLoE;
import com.zivilon.cinder_loe.client.model.*;
import com.zivilon.cinder_loe.entity.Renegade;
import com.zivilon.cinder_loe.util.IEntityLivingBase;
import com.zivilon.cinder_loe.util.Utilities;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Overwrite;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;

import lotr.common.entity.npc.LOTREntityNPC;
import lotr.common.entity.projectile.LOTREntitySpear;
import lotr.common.entity.ai.LOTREntityAIAttackOnCollide;
import lotr.common.item.LOTRItemSpear;
import lotr.common.item.LOTRWeaponStats;

import java.util.UUID;

@Mixin(LOTREntityAIAttackOnCollide.class)
public class MixinLOTREntityAIAttackOnCollide {

    @Shadow(remap = false)
    protected World worldObj;
    @Shadow(remap = false)
    protected EntityCreature theOwner;
    @Shadow(remap = false)
    protected EntityLivingBase attackTarget;
    @Shadow(remap = false)
    protected int attackTick;
    @Shadow(remap = false)
    protected void updateLookAndPathing() {}
    public UUID leader_id;
    public Entity leader;

    /**
     * @author Shinare
     * @reason If warband leader is too far, move to leader instead of attacking target
     */
    @Overwrite(remap = false)
    public void func_75246_d() { // updateTask()
        if (warband_task()) return;
        update_vanilla_task();
    }

    private boolean warband_task() {
        EntityCreature entity = this.theOwner;
        UUID leader_id = ((IEntityLivingBase)entity).get_warband_uuid();

        if (leader_id != null) {
            if (leader == null)
                leader = Utilities.find_entity_by_uuid(entity.worldObj, leader_id);
            if (leader != null && entity.getDistanceSqToEntity(leader) > 576.0D) {
                entity.setAttackTarget(null);
                entity.getNavigator().tryMoveToEntityLiving(leader, 1.3D);
                return true;  // Return here to not run default logic
            }
        }
        return false;
    }

    private void update_vanilla_task() {
        updateLookAndPathing();
        if (this.attackTick > 0)
            this.attackTick--;
        ItemStack weapon = this.theOwner.getHeldItem();
        if (weapon != null && weapon.getItem() instanceof LOTRItemSpear && this.attackTick <= 0 && this.theOwner instanceof LOTREntityNPC) {
            LOTREntityNPC theNPC = (LOTREntityNPC)this.theOwner;
            ItemStack spearBackup = theNPC.npcItemsInv.getSpearBackup();
            if (spearBackup != null) {
                LOTRItemSpear spearItem = (LOTRItemSpear)weapon.getItem();
                double d = this.theOwner.getDistanceToEntity((Entity)this.attackTarget);
                double range = this.theOwner.getNavigator().getPathSearchRange();
                if (d > 5.0D && d < range * 0.75D) {
                    LOTREntitySpear spear = new LOTREntitySpear(this.worldObj, (EntityLivingBase)this.theOwner, this.attackTarget, weapon.copy(), 0.75F + (float)d * 0.025F, 0.5F);
                    this.worldObj.playSoundAtEntity((Entity)this.theOwner, "random.bow", 1.0F, 1.0F / (this.worldObj.rand.nextFloat() * 0.4F + 1.2F) + 0.25F);
                    this.worldObj.spawnEntityInWorld((Entity)spear);
                    this.attackTick = 30 + this.theOwner.getRNG().nextInt(20);
                    if (ItemStack.areItemStacksEqual(theNPC.npcItemsInv.getIdleItem(), theNPC.npcItemsInv.getMeleeWeapon()))
                        theNPC.npcItemsInv.setIdleItem(spearBackup);
                    theNPC.npcItemsInv.setMeleeWeapon(spearBackup);
                    theNPC.npcItemsInv.setSpearBackup(null);
                    return;
                }
            }
        }
        float weaponReach = 1.0F;
        if (this.theOwner.ridingEntity != null)
            weaponReach = LOTREntityNPC.MOUNT_RANGE_BONUS;
        weaponReach *= LOTRWeaponStats.getMeleeReachFactor(this.theOwner.getHeldItem());
        float meleeRange = (float)this.theOwner.boundingBox.getAverageEdgeLength() + weaponReach;
        if (this.theOwner.getDistanceSqToEntity((Entity)this.attackTarget) <= (meleeRange * meleeRange))
            if (this.attackTick <= 0) {
                this.attackTick = LOTRWeaponStats.getAttackTimeMob(weapon);
                this.theOwner.attackEntityAsMob((Entity)this.attackTarget);
                this.theOwner.swingItem();
        }
    }
}
