package me.earthme.luminol.mobaireducer;

import me.earthme.luminol.config.modules.optimizations.MobAiReducerConfig;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.level.Level;

import java.util.EnumSet;

public class OptimizedBreedGoal extends Goal {

    private final MobAiReducerConfig module;
    private final Animal animal;
    private Animal partner;
    private int cooldown = 0;

    public OptimizedBreedGoal(MobAiReducerConfig module, Animal animal, TargetingConditions breedTargeting) {
        this.module = module;
        this.animal = animal;
        this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
    }

    @Override
    public boolean canUse() {
        if (!animal.isInLove()) return false;
        partner = findPartner();
        return partner != null;
    }

    @Override
    public boolean canContinueToUse() {
        return partner != null && partner.isAlive() && partner.isInLove() && animal.isInLove();
    }

    @Override
    public void stop() {
        partner = null;
        cooldown = 0;
    }

    @Override
    public void tick() {
        if (partner == null) return;
        animal.getLookControl().setLookAt(partner, 10.0f, (float) animal.getMaxHeadXRot());
        double dist = animal.distanceToSqr(partner);
        double breedRangeSq = module.breedRange * module.breedRange;
        if (dist < breedRangeSq) {
            if (++cooldown >= 60) {
                animal.spawnChildFromBreeding((net.minecraft.server.level.ServerLevel) animal.level(), partner);
                cooldown = 0;
            }
        } else {
            animal.getNavigation().moveTo(partner, 1.0);
        }
    }

    private Animal findPartner() {
        Level level = animal.level();
        return level.getEntitiesOfClass(
                Animal.class,
                animal.getBoundingBox().inflate(module.breedRange),
                candidate -> candidate != animal && candidate.isAlive() && candidate.isInLove()
        ).stream().findFirst().orElse(null);
    }
}
