package eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense;

import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.towers.Tower;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Material;
import net.minestom.server.network.packet.server.SendablePacket;
import net.minestom.server.network.packet.server.play.ParticlePacket;
import net.minestom.server.particle.Particle;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;

public class Cursor extends Entity {
    private boolean cursorActive = false;
    private final int reach;

    public Cursor(int reach) {
        super(EntityType.ARMOR_STAND);
        this.setBoundingBox(0,0,0);
        this.reach = reach;
    }

    public void updateCursorPosition(Player player) {
        Point targetPosition = player.getTargetBlockPosition(this.reach);
        this.moveCursorTo(targetPosition);
    }

    private void moveCursorTo(@Nullable Point newTargetBlockPosition) {
        this.setCursorEnabled(true);
        if(newTargetBlockPosition == null) {
            this.setCursorEnabled(false);
            return;
        }
        if(!this.getInstance().getBlock(newTargetBlockPosition).equals(Block.BLACK_WOOL)) this.setCursorEnabled(false);
        Material holdingMaterial = this.getInstance().getPlayerHandMaterial();
        if(!this.getInstance().getGame().getAvailableTowers().containsKey(holdingMaterial)) this.setCursorEnabled(false);
        this.teleport(new Pos(newTargetBlockPosition.add(0.5,1,0.5)));
        this.showRange(this.getInstance().getGame().getAvailableTowers().get(holdingMaterial));
    }

    private void setCursorEnabled(boolean enabled) {
        this.cursorActive = enabled;
        this.setInvisible(!enabled);
    }

    private void showRange(@Nullable Class<? extends Tower> towerClass) {
        if(towerClass == null) return;
        if(!this.isCursorActive()) return;
        try {
            int range = towerClass.getConstructor().newInstance().getRange();
            Collection<SendablePacket> particles = new ArrayList<>();
            double circumference = 2 * Math.PI * range;
            int count = (int) (circumference * 1.5);
            for (int i = 0; i < count; i++) {
                double radians = ((2 * Math.PI) / count) * i;
                Vec relativePosition = new Vec(Math.sin(radians)*range, 0, Math.cos(radians)*range);
                ParticlePacket particle = new ParticlePacket(Particle.COMPOSTER, this.position.add(relativePosition), Pos.ZERO, 0, 1);
                particles.add(particle);
            }
            this.getInstance().getPlayer().sendPackets(particles);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public TowerdefenseRoom getInstance() {
        return (TowerdefenseRoom) super.getInstance();
    }

    public boolean isCursorActive() {
        return this.cursorActive;
    }

    public Block getTargetBlock() {
        return this.getInstance().getBlock(this.getTargetBlockPosition());
    }

    public Pos getTargetBlockPosition() {
        return this.getPosition().sub(0, 0.5, 0);
    }
}
