use adw::prelude::*;
use async_std::channel::Receiver;
use async_std::task::spawn;
use gio::ActionEntry;
use otg_core::{Config, ConfigOption, Core, CoreNotification, LibraryPath, Observable};
use otg_gtk::{
    AppWindow, CoreApi, ResourceManager
};


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

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

async fn handler(notifications: Receiver<CoreNotification>, app_id: String) {
    loop {
        let msg = notifications.recv().await;
        match msg {
            Ok(CoreNotification::ConfigurationUpdated(cfg)) => {
                println!("commiting configuration");
                let settings = gio::Settings::new(&app_id);
                if let Some(LibraryPath(library_path)) = cfg.get() {
                    let _ = settings.set_string(
                        "library-path",
                        &library_path.into_os_string().into_string().unwrap(),
                    );
                }
            }
            Ok(_) => println!("discarding message"),
            Err(err) => {
                println!("shutting down handler with error: {:?}", err);
                return;
            }
        }
    }
}

/*
fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse) {
    let playing_field = Arc::new(RwLock::new(None));
    match message {
        CoreResponse::ConfigurationView(view) => perftrace("ConfigurationView", || {
            let config_page = ConfigurationPage::new(api, view);

            let window = adw::PreferencesWindow::new();
            window.add(&config_page);
            window.set_visible_page(&config_page);
            window.present();
        }),
        CoreResponse::HomeView(view) => perftrace("HomeView", || {
            let api = api.clone();

            let home = Home::new(api, view);
            app_window.set_content(&home);
        }),
        CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
            let api = api.clone();

            let mut playing_field = playing_field.write().unwrap();
            if playing_field.is_none() {
                perftrace("creating a new playing field", || {
                    let field = PlayingField::new(api, view);
                    app_window.set_content(&field);
                    *playing_field = Some(field);
                })
            } else if let Some(field) = playing_field.as_ref() {
                field.update_view(view)
            }
        }),
        CoreResponse::UpdatedConfigurationView(view) => perftrace("UpdatedConfiguration", || {
            println!("updated configuration: {:?}", view);
        }),
    }
}
*/

fn load_config(app_id: &str) -> Config {
    let settings = gio::Settings::new(app_id);
    let lib_path: String = settings.string("library-path").into();
    let mut config = Config::new();
    config.set(ConfigOption::LibraryPath(lib_path.into()));
    config
}

fn setup_app_configuration_action(app: &adw::Application, app_window: AppWindow) {
    println!("setup_app_configuration_action");
    let action = ActionEntry::builder("show_settings")
        .activate(move |_app: &adw::Application, _, _| {
            let app_window = app_window.clone();
            app_window.open_settings()
        })
        .build();
    app.add_action_entries([action]);
    println!("setup_app_configuration_action complete");
}

fn main() {
    gio::resources_register_include!("com.luminescent-dreams.otg-gtk.gresource")
        .expect("Failed to register resources");

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

    let config = load_config(app_id);

    let core = Core::new(config.clone());

    spawn({
        let notifier = core.subscribe();
        let app_id = app_id.to_owned();
        handler(notifier, app_id)
    });

    let app = adw::Application::builder()
        .application_id("com.luminescent-dreams.otg-gtk")
        .resource_base_path("/com/luminescent-dreams/otg-gtk")
        .build();

    app.connect_activate({
        move |app| {
            let resources = ResourceManager::default();
            let core_api = CoreApi { core: core.clone() };
            let app_window = AppWindow::new(app, core_api, resources);

            setup_app_configuration_action(app, app_window.clone());

            app_window.window.present();
        }
    });

    println!("running the gtk loop");
    app.run();
}
