package se.urmo.game.main;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import se.urmo.game.collision.GhostCollisionChecker;
import se.urmo.game.entities.ghost.Ghost;
import se.urmo.game.entities.ghost.mode.GhostMode;
import se.urmo.game.entities.ghost.strategy.BlinkyStrategy;
import se.urmo.game.entities.ghost.strategy.ClydeStrategy;
import se.urmo.game.entities.ghost.strategy.InkyStrategy;
import se.urmo.game.entities.ghost.strategy.PinkyStrategy;
import se.urmo.game.entities.ghost.strategy.ScatterToBottomLeft;
import se.urmo.game.entities.ghost.strategy.ScatterToBottomRight;
import se.urmo.game.entities.ghost.strategy.ScatterToTopLeft;
import se.urmo.game.entities.ghost.strategy.ScatterToTopRight;
import se.urmo.game.entities.pacman.PacMan;
import se.urmo.game.map.GameMap;

import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class GhostManager {
    public static final int MAX_SPRITE_FRAMES = 4;
    public static final int BLINKY_ANIMATION = 0;
    public static final int PINKY_ANIMATION = 2;
    public static final int INKY_ANIMATION = 1;
    public static final int CLYDE_ANIMATION = 3;
    @Getter
    private final List<Ghost> ghosts = new ArrayList<>();

    private long lastModeSwitchTime;
    private int phaseIndex = 0;

    // cycle in milliseconds: {scatter, chase, scatter, chase, ...}
    private final int[] cycleDurations = {
            7000, 20000,   // scatter 7s, chase 20s
            7000, 20000,   // scatter 7s, chase 20s
            5000, 20000,   // scatter 5s, chase 20s
            5000, Integer.MAX_VALUE // scatter 5s, then chase forever
    };
    private boolean frozen;

    public GhostManager(GhostCollisionChecker ghostCollisionChecker, AnimationManager animationManager, LevelManager levelManager) {
        // Create ghosts with their strategies
        Ghost blinky = new Ghost(ghostCollisionChecker, new BlinkyStrategy(), new ScatterToTopRight(), BLINKY_ANIMATION, levelManager);
        ghosts.add(blinky);
        ghosts.add(new Ghost(ghostCollisionChecker, new PinkyStrategy(), new ScatterToTopLeft(), PINKY_ANIMATION, levelManager));
        ghosts.add(new Ghost(ghostCollisionChecker, new InkyStrategy(blinky), new ScatterToBottomRight(), INKY_ANIMATION, levelManager));
        ghosts.add(new Ghost(ghostCollisionChecker, new ClydeStrategy(), new ScatterToBottomLeft(), CLYDE_ANIMATION, levelManager));

        ghosts.forEach(animationManager::register);

        setMode(GhostMode.HOUSE);
    }

    public void setMode(GhostMode mode) {
        for (Ghost g : ghosts) {
            g.setMode(mode);
        }
    }

    public void update(PacMan pacman, GameMap map) {
        long now = System.currentTimeMillis();
        if (phaseIndex < cycleDurations.length) {
            int duration = cycleDurations[phaseIndex];
            if (now - lastModeSwitchTime >= duration) {
                phaseIndex++;
                if (phaseIndex < cycleDurations.length) {
                    GhostMode newMode = (phaseIndex % 2 == 0) ? GhostMode.SCATTER : GhostMode.CHASE;
                    setMode(newMode);
                }
                lastModeSwitchTime = now;
            }
        }

        for (Ghost g : ghosts) {
            g.update(pacman, map);
        }
    }

    public void draw(Graphics2D g) {
        for (Ghost ghost : ghosts) {
            ghost.draw(g);
        }
    }

    public void setFrightMode() {
        setMode(GhostMode.FRIGHTENED);
    }

    public void reset() {
        phaseIndex = 0;
        setMode(GhostMode.SCATTER);
        ghosts.forEach(Ghost::reset);
    }

    public void setFrozen(boolean frozen) {
        this.ghosts.forEach(ghost -> ghost.setMode(GhostMode.FROZEN));
    }

    public int isFrightened() {
        return (int) ghosts.stream().filter(Ghost::isFrightened).count();
    }
}
