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.EntityLiving;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;

import lotr.common.entity.npc.LOTREntityNPC;
import lotr.common.entity.ai.LOTREntityAIRangedAttack;
import lotr.common.item.LOTRItemSpear;
import lotr.common.item.LOTRWeaponStats;

import java.util.UUID;

@Mixin(LOTREntityAIRangedAttack.class)
public class MixinLOTREntityAIRangedAttack {

    @Shadow(remap = false)
    private EntityLiving theOwner;
    @Shadow(remap = false)
    private IRangedAttackMob theOwnerRanged;
    @Shadow(remap = false)
    private EntityLivingBase attackTarget;
    @Shadow(remap = false)
    private int rangedAttackTime;
    @Shadow(remap = false)
    private double moveSpeed;
    @Shadow(remap = false)
    private double moveSpeedFlee = 1.5D;
    @Shadow(remap = false)
    private int repathDelay;
    @Shadow(remap = false)
    private int attackTimeMin;
    @Shadow(remap = false)
    private int attackTimeMax;
    @Shadow(remap = false)
    private float attackRange;
    @Shadow(remap = false)
    private float attackRangeSq;
    @Shadow(remap = false)
    public static Vec3 findPositionAwayFrom(EntityLivingBase entity, EntityLivingBase target, int min, int max) {return null;}

    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() {
        EntityLiving 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() {
        double distanceSq = this.theOwner.getDistanceSq(this.attackTarget.posX, this.attackTarget.boundingBox.minY, this.attackTarget.posZ);
        boolean canSee = this.theOwner.getEntitySenses().canSee((Entity)this.attackTarget);
        if (canSee) {
            this.repathDelay++;
        } else {
            this.repathDelay = 0;
        }
        if (distanceSq <= this.attackRangeSq) {
            if (this.theOwner.getDistanceSqToEntity((Entity)this.attackTarget) < 25.0D) {
                Vec3 vec = findPositionAwayFrom((EntityLivingBase)this.theOwner, this.attackTarget, 8, 16);
                if (vec != null)
                    this.theOwner.getNavigator().tryMoveToXYZ(vec.xCoord, vec.yCoord, vec.zCoord, this.moveSpeedFlee);
            } else if (this.repathDelay >= 20) {
                this.theOwner.getNavigator().clearPathEntity();
                this.repathDelay = 0;
            }
        } else {
            this.theOwner.getNavigator().tryMoveToEntityLiving((Entity)this.attackTarget, this.moveSpeed);
        }
        this.theOwner.getLookHelper().setLookPositionWithEntity((Entity)this.attackTarget, 30.0F, 30.0F);
        this.rangedAttackTime--;
        if (this.rangedAttackTime == 0) {
            if (distanceSq > this.attackRangeSq || !canSee)
                return;
            float distanceRatio = MathHelper.sqrt_double(distanceSq) / this.attackRange;
            float power = distanceRatio;
            power = MathHelper.clamp_float(power, 0.1F, 1.0F);
            this.theOwnerRanged.attackEntityWithRangedAttack(this.attackTarget, power);
            this.rangedAttackTime = MathHelper.floor_float(distanceRatio * (this.attackTimeMax - this.attackTimeMin) + this.attackTimeMin);
        } else if (this.rangedAttackTime < 0) {
            float distanceRatio = MathHelper.sqrt_double(distanceSq) / this.attackRange;
            this.rangedAttackTime = MathHelper.floor_float(distanceRatio * (this.attackTimeMax - this.attackTimeMin) + this.attackTimeMin);
        }
    }
}
