#include "../../../include/shared.hpp"
#include <PSX/GPU/gpu.hpp>
#include <PSX/Periphery/periphery.hpp>

namespace FontCycler {
    using namespace JabyEngine;

    static const char*const ASCII = "!\"#$%&'()*+,-./0\n123456789:;<=>?@\nABCDEFGHIJKLMNOP\nQRSTUVWXYZ[\\]^_`\nabcdefghijklmnop\nqrstuvwxyz{|}~\n";
    
    static JabyEngine::FontWriter*const FontWriters[] = {
        &FontWriter::bios_font_writer,
        &FontWriter::new_font_writer,
    };
    static constexpr auto MaxFontSelector = (sizeof(FontWriters)/sizeof(FontWriters[0])) - 1;
    static uint8_t        font_selector   = 0;

    static void increment_font_selector() {
        if(font_selector == MaxFontSelector) {
            font_selector = 0;
        }

        else {
            font_selector++;
        }
    }

    static void decrement_font_selector() {
        if(font_selector == 0) {
            font_selector = MaxFontSelector;
        }

        else {
            font_selector--;
        }
    }

    static void setup() {
        Shared::back_menu.reset();
        font_selector = 0;
    }

    static bool update_or_exit() {
        Periphery::query_controller();
        if(Shared::back_menu.update(Make::PositionI16(0, GPU::Display::Height - 32))) {
            return true;
        }

        const auto& controller = Periphery::get_primary_controller_as<Periphery::GenericController>();
        if(controller.button.went_up(Periphery::GenericController::Button::L1)) {
            decrement_font_selector();
        }
        if(controller.button.went_up(Periphery::GenericController::Button::R1)) {
            increment_font_selector();
        }

        auto cursor = FontWriter::update(Make::PositionI16(8, 8));
        FontWriters[font_selector]->write(cursor, ASCII);
        FontWriters[font_selector]->write(cursor, "\nPress L1 or R1 to cycle\nthrough fonts");
        return false;
    }

    static void render() {
        FontWriters[font_selector]->render();
        Shared::back_menu.render();
    }

    void main() {
        setup();

        while(true) {
            if(update_or_exit()) {
                break;
            }
            GPU::swap_buffers_vsync(1);
            render();
        }
    }
}