mod imp {
    use gtk::glib;
    use gtk::subclass::prelude::*;

    #[derive(Default)]
    pub(crate) struct SettingsDialog {}

    #[glib::object_subclass]
    impl ObjectSubclass for SettingsDialog {
        const NAME: &'static str = "SettingsDialog";
        type Type = super::SettingsDialog;
        type ParentType = gtk::Window;
    }

    impl ObjectImpl for SettingsDialog {}

    impl WidgetImpl for SettingsDialog {}

    impl WindowImpl for SettingsDialog {}
}

use crate::app::PatchpalApplication;
use gtk::glib;
use gtk::prelude::*;

glib::wrapper! {
    pub(crate) struct SettingsDialog(ObjectSubclass<imp::SettingsDialog>)
        @extends gtk::Window, gtk::Widget,
        @implements
            gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Native, gtk::Root,
            gtk::ShortcutManager;
}

impl SettingsDialog {
    pub(crate) fn new(application: &PatchpalApplication) -> Self {
        let dialog: Self = glib::Object::builder()
            .property("application", application)
            .property("modal", true)
            .property("title", "Settings")
            .property("transient-for", application.app_window())
            .build();
        dialog.setup_ui();
        dialog
    }

    fn application(&self) -> PatchpalApplication {
        let parent: &gtk::Window = self.upcast_ref();
        parent.application().unwrap().downcast().unwrap()
    }

    fn setup_ui(&self) {
        let app = self.application();
        let config = app.config();

        let grid = gtk::Grid::builder()
            .column_spacing(15)
            .row_spacing(4)
            .build();

        let editor_label = gtk::Label::builder()
            .label("External editor:")
            .halign(gtk::Align::Start)
            .build();

        let editor_entry = gtk::Entry::builder()
            .text(&config.get::<String>("editor").unwrap_or_default())
            .placeholder_text("e.g. gvim -f %f")
            .hexpand(true)
            .activates_default(true)
            .build();

        let help_label = gtk::Label::builder()
            .label("%f will be replaced with the file path")
            .halign(gtk::Align::Start)
            .css_classes(["dim-label"])
            .build();

        grid.attach(&editor_label, 0, 0, 1, 1);
        grid.attach(&editor_entry, 1, 0, 1, 1);
        grid.attach(&help_label, 1, 1, 1, 1);

        let button_box = gtk::Box::builder()
            .orientation(gtk::Orientation::Horizontal)
            .halign(gtk::Align::End)
            .spacing(10)
            .margin_top(20)
            .build();

        let button_cancel = gtk::Button::builder()
            .label("Cancel")
            .build();
        let button_ok = gtk::Button::builder()
            .label("OK")
            .build();

        button_box.append(&button_cancel);
        button_box.append(&button_ok);

        let main_box = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .margin_top(10)
            .margin_bottom(10)
            .margin_start(10)
            .margin_end(10)
            .spacing(10)
            .build();

        main_box.append(&grid);
        main_box.append(&button_box);

        self.set_child(Some(&main_box));
        self.set_default_widget(Some(&button_ok));

        button_cancel.connect_clicked(glib::clone!(
            #[weak(rename_to = window)] self,
            move |_| window.close()
        ));

        button_ok.connect_clicked(glib::clone!(
            #[weak(rename_to = window)] self,
            #[weak] editor_entry,
            move |_| {
                let app = window.application();
                let config = app.config();
                let editor_text = editor_entry.text();
                if !editor_text.is_empty() {
                    config.set("editor", editor_text.to_string());
                    let _ = config.save();
                }
                window.close();
            }
        ));
    }
}
