package thb.jeanluc.adventure.menu;

import thb.jeanluc.adventure.io.ConsoleIO;
import thb.jeanluc.adventure.io.GameIO;
import thb.jeanluc.adventure.save.Settings;
import thb.jeanluc.adventure.save.SettingsStore;

import java.util.List;

/** Settings screen: cycle colour, glyph, and music level; persists + applies. */
public final class SettingsMenu {

    private SettingsMenu() {
    }

    /** Loops the settings screen until "Back", persisting + applying each change. */
    public static Settings show(GameIO io, Settings current, SettingsStore store) {
        Settings s = current;
        while (true) {
            int i = io.choose("SETTINGS", List.of(
                    "Colour: " + s.colorMode(),
                    "Glyphs: " + s.glyphMode(),
                    "Music: " + s.musicLevel(),
                    "Back"));
            if (i == 0) {
                s = new Settings(nextColor(s.colorMode()), s.glyphMode(), s.musicLevel());
            } else if (i == 1) {
                s = new Settings(s.colorMode(), nextGlyph(s.glyphMode()), s.musicLevel());
            } else if (i == 2) {
                s = new Settings(s.colorMode(), s.glyphMode(), s.musicLevel().next());
            } else {
                return s;
            }
            store.save(s);
            apply(s, io);
        }
    }

    /** Applies settings to the IO: music level always; colour/glyph only on the console. */
    public static void apply(Settings s, GameIO io) {
        io.setMusicLevel(s.musicLevel());
        if (io instanceof ConsoleIO c) {
            c.setColorMode(s.colorMode());
            c.setGlyphMode(s.glyphMode());
        }
    }

    private static ConsoleIO.ColorMode nextColor(ConsoleIO.ColorMode m) {
        return switch (m) {
            case AUTO -> ConsoleIO.ColorMode.ON;
            case ON -> ConsoleIO.ColorMode.OFF;
            case OFF -> ConsoleIO.ColorMode.AUTO;
        };
    }

    private static ConsoleIO.GlyphMode nextGlyph(ConsoleIO.GlyphMode m) {
        return switch (m) {
            case UNICODE -> ConsoleIO.GlyphMode.ASCII;
            case ASCII -> ConsoleIO.GlyphMode.GLYPH;
            case GLYPH -> ConsoleIO.GlyphMode.UNICODE;
        };
    }
}
