#![windows_subsystem = "windows"]

mod db;
mod game;
mod ui;
mod widgets;
mod dictionary;
mod card;
mod card_gobject;

use crate::ui::menu::MenuScene;

use db::get_program_home_path;
use gtk::glib::closure_local;
use gtk::glib::subclass::types::ObjectSubclassIsExt;
use gtk::{gio, glib, Application, Button};
use gtk::{prelude::*, Window};
use ui::cards::edit::MemoryCardsEditScene;
use ui::cards::game::MemoryCardsGameScene;
use ui::cards::setup::MemoryCardsSetupScene;
use ui::guessing::game::GuessingScene;
use ui::guessing::setup::GuessingSetupScene;

enum AppWindow {
    MenuScene = 1,

    GuessingSetupScene = 2,
    GuessingScene = 3,

    MemoryCardsSetupScene = 4,
    MemoryCardsEditScene = 5,
    MemoryCardsGameScene = 6,
}

const APP_ID: &str = "org.foxarmy.learn-hieroglyph";

fn main() -> glib::ExitCode {
    gio::resources_register_include!("compiled.gresource").expect("Cannot include gresources");

    db::init(); // Create database if not exists, create program's home if not exists, etc...

    dictionary::import(&(get_program_home_path() + "/dictionary.txt")); // Read file, parse it, deduplicate and append to the database.

    

    let app: Application = Application::builder().application_id(APP_ID).build();

    app.connect_activate(build_ui);

    app.run()
}

fn hide_all_windows(app: &Application) {
    for window in app.windows() {
        window.set_visible(false);
    }
}

fn switch_to(app: &Application, win: AppWindow) {
    hide_all_windows(app);
    app.window_by_id(win as u32).unwrap().set_visible(true);
}

fn build_ui(app: &Application) {
    let menu: MenuScene = MenuScene::new(app); // 1
    let guessing_setup: GuessingSetupScene = GuessingSetupScene::new(app); // 2
    let guessing_scene: GuessingScene = GuessingScene::new(app); // 3
    let memory_cards_setup: MemoryCardsSetupScene = MemoryCardsSetupScene::new(app); // 4
    let memory_cards_edit: MemoryCardsEditScene = MemoryCardsEditScene::new(app); // 5
    let memory_cards_game: MemoryCardsGameScene = MemoryCardsGameScene::new(app); // 6

    menu.get_guessing_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::GuessingSetupScene);
            }
        ),
    );

    menu.get_memory_cards_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::MemoryCardsSetupScene);
            }
        ),
    );

    guessing_setup.get_start_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app, @strong guessing_scene => move |_b: &Button| {
                switch_to(&app, AppWindow::GuessingScene);
                guessing_scene.read_settings();
                guessing_scene.init();
            }
        ),
    );

    guessing_setup.get_back_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::MenuScene);
            }
        ),
    );

    guessing_scene.get_back_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::GuessingSetupScene);
            }
        ),
    );

    memory_cards_setup.get_edit_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app, @strong memory_cards_edit => move |_b: &Button| {
                switch_to(&app, AppWindow::MemoryCardsEditScene);
                memory_cards_edit.imp().query_cards(None);
                // memory_cards_edit.imp().update_state();
            }
        ),
    );

    memory_cards_setup.get_back_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::MenuScene);
            }
        ),
    );

    memory_cards_setup.get_start_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app, @strong memory_cards_game => move |_b: &Button| {
                switch_to(&app, AppWindow::MemoryCardsGameScene);
                memory_cards_game.imp().update_card();
                // memory_cards_game.imp().u
            }
        ),
    );

    memory_cards_edit.get_back_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::MemoryCardsSetupScene);
            }
        ),
    );

    memory_cards_game.get_back_button().connect_closure(
        "clicked",
        false,
        closure_local!(
            @strong app => move |_b: &Button| {
                switch_to(&app, AppWindow::MemoryCardsSetupScene);
            }
        ),
    );

    connect_close_requrest(app, menu.upcast_ref::<Window>());
    connect_close_requrest(app, guessing_setup.upcast_ref::<Window>());
    connect_close_requrest(app, guessing_scene.upcast_ref::<Window>());
    connect_close_requrest(app, memory_cards_setup.upcast_ref::<Window>());
    connect_close_requrest(app, memory_cards_edit.upcast_ref::<Window>());
    connect_close_requrest(app, memory_cards_game.upcast_ref::<Window>());

    menu.present();
}

fn connect_close_requrest<W: IsA<Window>>(app: &Application, w: &W) {
    w.connect_closure(
        "close-request",
        false,
        closure_local!(@strong app => move |_w: &Window| {
            app.quit();
            true
        }),
    );
}