mod imp;

use glib::Object;
use gtk::{
    gio,
    glib::{self, clone, subclass::types::ObjectSubclassIsExt},
    Button, Image, Switch,
};
use rusqlite::Connection;

use crate::{card::Card, db::get_db_path};

glib::wrapper! {
    pub struct CardEntry(ObjectSubclass<imp::CardEntry>)
        @extends gtk::Widget,
        @implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
                    gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
}

impl CardEntry {
    pub fn new(card: Option<&Card>) -> Self {
        match card {
            Some(card) => Object::builder()
                .property("imagepath", card.image_path().unwrap())
                .property("hieroglyph", card.hieroglyph().unwrap())
                .property("reading", card.reading().unwrap())
                .property("translation", card.translation().unwrap())
                .property("islearning", card.is_learning().unwrap())
                .build(),
            None => Object::builder()
                .property("imagepath", "")
                .property("hieroglyph", "")
                .property("reading", "")
                .property("translation", "")
                .property("islearning", false)
                .build(),
        }
    }

    pub fn get_image_widget(&self) -> &Image {
        self.imp().image.as_ref()
    }

    pub fn get_image_file_path(&self) -> String {
        self.imp().imagepath.borrow().clone()
    }

    pub fn get_delete_button_widget(&self) -> &Button {
        self.imp().delete_button.as_ref()
    }

    pub fn get_edit_button_widget(&self) -> &Button {
        self.imp().edit_button.as_ref()
    }

    pub fn get_is_learning_switch_widget(&self) -> &Switch {
        self.imp().is_learning_switch.as_ref()
    }

    pub fn update_file_for_image(&self) {
        let image_binding: &Image = self.imp().image.as_ref();
        let path: &str = &*self.imp().imagepath.borrow().clone().to_string();
        image_binding.set_file(Some(&path));
    }

    pub fn update_state(&self) {
        let conn = Connection::open(get_db_path()).unwrap();
        let is_learning_switch_binding: &Switch = self.imp().is_learning_switch.as_ref();
        let h = &self.hieroglyph();
        let sql = "SELECT is_learning FROM cards WHERE hieroglyph=:h;";
        let mut stmt = conn.prepare(sql).unwrap();
        let iter = stmt
            .query_map(&[(":h", h.as_str())], |row| Ok(row.get(0).unwrap()))
            .unwrap();

        for res in iter {
            is_learning_switch_binding.set_state(res.unwrap());
        }

        let self_binding = self;
        is_learning_switch_binding.connect_state_set(
            clone!(@strong self_binding => move |_, is_enabled| {
                let conn = Connection::open(get_db_path()).unwrap();
                let hieroglyph = &*self_binding.imp().hieroglyph.borrow().clone();
                println!("UPDATE cards SET is_learning = {is_enabled} WHERE hieroglyph = {hieroglyph}",);
                conn.execute(
                    "UPDATE cards SET is_learning = ?1 WHERE hieroglyph = ?2",
                    (&is_enabled, &hieroglyph),
                )
                .unwrap();
                glib::Propagation::Proceed
            }),
        );
    }
}
