mod repetition;

use gtk4 as gtk;

use gtk::glib;
use gtk::prelude::*;

use crate::{
    db,
    gui::{update, update::Msg, App},
    model::{event, event::Event},
};

pub async fn show(app: &App, event: Event, is_new: bool) {
    let dialog = gtk::Dialog::builder()
        .transient_for(&*app.window)
        .modal(true)
        .title(if is_new { "Ajouter" } else { "Modifier" })
        .css_classes(vec!["g-Form".to_string()])
        .build();

    let content_area = dialog.content_area();

    let lines = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .build();
    content_area.append(&lines);

    let columns = gtk::Box::builder()
        .orientation(gtk::Orientation::Horizontal)
        .build();
    columns.add_css_class("g-Form__Columns");
    lines.append(&columns);

    // First column

    let column1 = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .build();
    column1.add_css_class("g-Form__Inputs");
    columns.append(&column1);

    let name = entry(&event.name);
    column1.append(&label("Événement"));
    column1.append(&name);

    let date = entry(&event.date.format(event::DATE_FORMAT).to_string());
    column1.append(&label("Jour"));
    column1.append(&date);

    let start = entry(
        &event
            .start
            .map(event::pprint_time)
            .unwrap_or_else(|| "".to_string()),
    );
    column1.append(&label("Début"));
    column1.append(&start);

    let end = entry(
        &event
            .end
            .map(event::pprint_time)
            .unwrap_or_else(|| "".to_string()),
    );
    column1.append(&label("Fin"));
    column1.append(&end);

    // Second column

    let repetition_model = repetition::view(&event);
    columns.append(&repetition_model.view);

    // Buttons

    let button = gtk::Button::builder()
        .label(if is_new { "Créer" } else { "Modifier" })
        .margin_bottom(10)
        .build();
    lines.append(&button);
    let conn = app.conn.clone();
    let tx = app.tx.clone();
    button.connect_clicked(glib::clone!(@weak dialog, @strong event => move |_| {
        match repetition::validate(&repetition_model) {
            Ok(repetition) => {
                match event::validate(event.id, date.buffer().text(), name.buffer().text(), start.buffer().text(), end.buffer().text(), repetition) {
                    Some(new) => {
                        match if is_new { db::insert(&conn, &new) } else { db::update(&conn, &new) } {
                            Ok(_) => {
                                let msg = if is_new { Msg::AddEvent { new } } else { Msg::UpdateEvent { old: event.clone(), new } };
                                update::send(tx.clone(), msg);
                                dialog.close()
                            },
                            Err(err) => eprintln!("Error when upserting event: {err}")
                        }
                    }
                    None => eprintln!("Event is not valid: {event:?}")
                }
            },
            Err(message) => eprintln!("{message}")
        }
    }));

    if !is_new {
        let button = gtk::Button::builder().label("Supprimer").build();
        lines.append(&button);
        let conn = app.conn.clone();
        let tx = app.tx.clone();
        button.connect_clicked(glib::clone!(@weak dialog => move |_| {
            if db::delete(&conn, &event.id).is_ok() {
                update::send(tx.clone(), Msg::DeleteEvent { event: event.clone() });
                dialog.close()
            }
        }));
    }

    dialog.run_future().await;
}

fn entry(text: &str) -> gtk::Entry {
    gtk::Entry::builder().text(text).margin_bottom(10).build()
}

fn label(text: &str) -> gtk::Label {
    gtk::Label::builder()
        .label(text)
        .halign(gtk::Align::Start)
        .margin_bottom(5)
        .build()
}