/*
Copyright 2023 - 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>

This file is part of FitnessTrax.

FitnessTrax is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

FitnessTrax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see <https://www.gnu.org/licenses/>.
*/

mod about;
mod app;
mod app_window;
mod components;
#[cfg(test)]
mod gtk_init;
mod types;
mod view_models;
mod views;

use adw::prelude::*;
use app_window::AppWindow;
use gio::ActionEntry;
use std::{env, path::PathBuf};

const APP_ID_DEV: &str = "com.luminescent-dreams.fitnesstrax.dev";
const APP_ID_PROD: &str = "com.luminescent-dreams.fitnesstrax";

const RESOURCE_BASE_PATH: &str = "/com/luminescent-dreams/fitnesstrax/";

fn setup_app_about_action(app: &adw::Application) {
    let action = ActionEntry::builder("about")
        .activate(|_app: &adw::Application, _, _| {
            let window = about::AboutWindow::default();
            window.present();
        }).build();
    app.add_action_entries([action]);
}

/// Sets up an application-global action, `app.quit`, which will terminate the application.
fn setup_app_close_action(app: &adw::Application) {
    let action = ActionEntry::builder("quit")
        .activate(|app: &adw::Application, _, _| {
            // right now, stopping the application is dirt simple. But we could use this
            // block to add extra code that does additional shutdown steps if we ever want
            // some states that shouldn't be discarded.
            app.quit();
        })
        .build();
    app.add_action_entries([action]);
    app.set_accels_for_action("app.quit", &["<Ctrl>Q"]);
}

fn main() {
    // I still don't fully understand gio resources. resources_register_include! is convenient
    // because I don't have to deal with filesystem locations at runtime. However, I think other
    // GTK applications do that rather than compiling the resources directly into the app. So, I'm
    // unclear as to how I want to handle this.
    gio::resources_register_include!("com.luminescent-dreams.fitnesstrax.gresource")
        .expect("to register resources");

    let app_id = if std::env::var_os("ENV") == Some("dev".into()) {
        APP_ID_DEV
    } else {
        APP_ID_PROD
    };

    let settings = gio::Settings::new(app_id);
    let ft_app = app::App::new({
        let path = settings.string("series-path");
        if path.is_empty() {
            None
        } else {
            Some(PathBuf::from(path))
        }
    });

    let adw_app = adw::Application::builder()
        .application_id(app_id)
        .resource_base_path(RESOURCE_BASE_PATH)
        .build();

    adw_app.connect_activate(move |adw_app| {
        let icon_theme = gtk::IconTheme::for_display(&gdk::Display::default().unwrap());
        icon_theme.add_resource_path(&(RESOURCE_BASE_PATH.to_owned() + "/icons/scalable/actions"));

        setup_app_about_action(adw_app);
        setup_app_close_action(adw_app);

        AppWindow::new(app_id, RESOURCE_BASE_PATH, adw_app, ft_app.clone());
    });

    let args: Vec<String> = env::args().collect();
    ApplicationExtManual::run_with_args(&adw_app, &args);
}
