import java.util.ArrayList;
import java.util.List;

/**
 * El modelo: un reproductor que es una máquina de estados. No sabe nada de
 * consolas ni de ventanas; avisa a sus observers de lo que pasa.
 */
public class Player {
    private final List<Song> queue;
    private final List<PlayerListener> listeners = new ArrayList<>();
    private State state = State.STOPPED;
    private int index = 0;
    private int elapsed = 0;            // segundos de la canción actual

    public Player(List<Song> queue) {
        if (queue.isEmpty()) {
            throw new IllegalArgumentException("lista vacía");
        }
        this.queue = List.copyOf(queue);
    }

    public void addListener(PlayerListener listener) {
        listeners.add(listener);
    }

    public State state() {
        return state;
    }

    public Song current() {
        return queue.get(index);
    }

    /** El mismo evento hace cosas distintas según el estado. */
    public void play() {
        String message = switch (state) {
            case STOPPED -> {
                index = 0;
                elapsed = 0;
                yield "suena";
            }
            case PAUSED -> "continúa";
            case PLAYING -> "ya está sonando";
        };
        change(State.PLAYING, message);
    }

    public void pause() {
        switch (state) {
            case PLAYING -> change(State.PAUSED, "en pausa");
            case PAUSED, STOPPED -> change(state, "no hay nada que pausar");
        }
    }

    public void stop() {
        elapsed = 0;
        change(State.STOPPED, "detenido");
    }

    public void next() {
        switch (state) {
            case STOPPED -> change(State.STOPPED, "detenido: use play");
            case PLAYING, PAUSED -> advance();
        }
    }

    /** Evento del reloj: pasaron unos segundos. Solo cuenta si está sonando. */
    public void tick(int seconds) {
        if (state != State.PLAYING) {
            return;
        }
        elapsed += seconds;
        if (elapsed >= current().seconds()) {
            advance();
        }
    }

    private void advance() {
        elapsed = 0;
        if (index + 1 < queue.size()) {
            index++;
            change(state, "siguiente");
        } else {
            change(State.STOPPED, "fin de la lista");
            index = 0;
        }
    }

    private void change(State newState, String message) {
        state = newState;
        PlayerEvent event = new PlayerEvent(state, current(), message);
        for (PlayerListener l : List.copyOf(listeners)) {
            l.onEvent(event);
        }
    }
}
