use chrono::{Datelike, Local, Utc};
use geo_types::{Latitude, Longitude};
use glib::Sender;
use gtk::prelude::*;
use ifc::IFC;
use std::{
    env,
    sync::{Arc, RwLock},
};

mod app_window;
use app_window::ApplicationWindow;

mod components;

mod drawing;

mod soluna_client;
use soluna_client::SolunaClient;

mod solstices;
use solstices::EVENTS;

mod types;
use types::State;

/*
const EO_TEXT: &'static str = "
day = {$day ->
    *[Sunday] Dimanĉo
    [Monday] Lundo
    [Tuesday] Mardo
    [Wednesday] Merkredo
    [Thursday] Ĵaŭdo
    [Friday] Vendredo
    [Saturday] Sabato
    [LeapDay] Leap Day
    [YearDay] Year Day
}
month = {$month ->
    *[January] Januaro
    [February] Februaro
    [March] Marto
    [April] Aprilo
    [May] Mayo
    [June] Junio
    [Sol] Solo
    [July] Julio
    [August] Aŭgusto
    [September] Septembro
    [October] Oktobro
    [November] Novembro
    [December] Decembro
}
spring_equinox = Printempa Ekvinokso
summer_solstice = Somera Solstico
autumn_equinox = Aŭtuna Ekvinokso
winter_solstice = Vintra Solstico
";
*/

#[derive(Clone, Debug)]
pub enum Message {
    Refresh(State),
}

#[derive(Clone)]
pub struct Core {
    tx: Arc<RwLock<Option<Sender<Message>>>>,
}

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

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

    let latitude = Latitude::from(41.78);
    let longitude = Longitude::from(-71.41);

    let runtime = tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap();

    let core = Core {
        tx: Arc::new(RwLock::new(None)),
    };

    runtime.spawn({
        let core = core.clone();
        async move {
            let soluna_client = SolunaClient::new();

            loop {
                let transit = soluna_client
                    .request(latitude.clone(), longitude.clone(), Local::now())
                    .await;

                let now = Local::now();
                let state = State {
                    date: IFC::from(now.date_naive().with_year(now.year() + 10000).unwrap()),
                    next_event: EVENTS.next_event(now.with_timezone(&Utc)).unwrap(),
                    events: EVENTS.yearly_events(now.year()).unwrap(),
                    transit: Some(transit),
                };

                if let Some(ref gtk_tx) = *core.tx.read().unwrap() {
                    let _ = gtk_tx.send(Message::Refresh(state.clone()));
                    std::thread::sleep(std::time::Duration::from_secs(60));
                } else {
                    std::thread::sleep(std::time::Duration::from_secs(1));
                }
            }
        }
    });

    app.connect_activate(move |app| {
        let (gtk_tx, gtk_rx) =
            gtk::glib::MainContext::channel::<Message>(gtk::glib::Priority::DEFAULT);

        *core.tx.write().unwrap() = Some(gtk_tx);

        let window = ApplicationWindow::new(app);
        window.window.present();

        gtk_rx.attach(None, {
            let window = window.clone();
            move |msg| {
                let Message::Refresh(state) = msg;
                ApplicationWindow::update_state(&window, state);

                glib::ControlFlow::Continue
            }
        });
    });

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