use std::cell::RefCell;
use std::ops::Deref;

use crate::game::*;

use glib::subclass::InitializingObject;
use gtk::glib::closure_local;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, Entry, Label};
use gtk::{prelude::*, Button};
use rand::Rng;

#[derive(CompositeTemplate, Default)]
#[template(resource = "/org/foxarmy/learn-hieroglyph/guessing/game/ui.xml")]
pub struct GuessingScene {
    #[template_child]
    pub question_label: TemplateChild<Label>,
    #[template_child]
    pub answer_entry: TemplateChild<Entry>,
    #[template_child]
    pub stats_label: TemplateChild<Label>,
    #[template_child]
    pub back_button: TemplateChild<Button>,

    pub ktr: RefCell<bool>,
    pub rtk: RefCell<bool>,
    pub hiragana: RefCell<bool>,
    pub katakana: RefCell<bool>,

    pub question: RefCell<Hieroglyph>,
    pub exact_kana: RefCell<Kanas>,
    pub correct_answer: RefCell<Hieroglyph>,
}

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

    fn class_init(klass: &mut Self::Class) {
        klass.bind_template();
    }

    fn instance_init(obj: &InitializingObject<Self>) {
        obj.init_template();
    }
}

impl ObjectImpl for GuessingScene {
    fn constructed(&self) {
        self.parent_constructed();

        self.obj().init();

        let stats: RefCell<(u32, u32)> = RefCell::new((0, 0));
        let b = self.obj();
        let self_binding = b.as_ref();
        let question_label_binding = &self.question_label.get();
        let answer_entry_binding = &self.answer_entry.get();
        let stats_label_binding = &self.stats_label.get();


        /*
        
        "Memory management when writing a gtk-rs app can be a bit tricky."
            (c) https://gtk-rs.org/gtk4-rs/stable/latest/book/g_object_memory_management.html
        
         */

        let iteration = closure_local!(@strong self_binding,
                                                @strong stats,
                                                @strong question_label_binding as question_label,
                                                @strong answer_entry_binding as answer_entry,
                                                @strong stats_label_binding as stats_label, => move |_entry: &Entry| {
            self_binding.read_settings();
            let answer: &String = &answer_entry.text().to_string();
            // //
            println!("{} <-> {}({})? = {}", answer, self_binding.imp().correct_answer.borrow(), self_binding.imp().question.borrow(), *answer == self_binding.imp().correct_answer.borrow().to_string());
            *stats.borrow_mut() = if *answer == self_binding.imp().correct_answer.borrow().to_string() { (stats.borrow().0 + 1, stats.borrow().1) } else {(stats.borrow().0, stats.borrow().1 + 1)};
            stats_label.set_label(format!("Correct|Incorrect: {}|{} ({:.2}%)", stats.borrow().0, stats.borrow().1, 100.0 * f64::from(stats.borrow().0) / f64::from(stats.borrow().0 + stats.borrow().1)).as_str());
            *self_binding.imp().question.borrow_mut() = ask(
                *self_binding.imp().ktr.borrow(),
                *self_binding.imp().rtk.borrow(),
                *self_binding.imp().hiragana.borrow(),
                *self_binding.imp().katakana.borrow());
            *self_binding.imp().exact_kana.borrow_mut() =
                if *self_binding.imp().hiragana.borrow() && *self_binding.imp().katakana.borrow() {
                    if rand::thread_rng().gen_bool(0.5) {Kanas::Hiragana} else {Kanas::Katakana}
                } else if *self_binding.imp().hiragana.borrow() {
                    Kanas::Hiragana
                } else {
                    Kanas::Katakana
                };
            *self_binding.imp().correct_answer.borrow_mut() = get_kana_pair_for_hieroglyph(
                match self_binding.imp().question.borrow().get_kana() {
                    Kanas::Romaji => match self_binding.imp().exact_kana.borrow().deref() {
                        Kanas::Hiragana => &Kanas::Hiragana,
                        Kanas::Katakana => &Kanas::Katakana,
                        _ => panic!("HOW DID YOU GET HERE?!")
                    },
                    _ => &Kanas::Romaji
                },
                &self_binding.imp().question.borrow()
            );
            let binding = generate_question_text(&self_binding.imp().question.borrow(), &self_binding.imp().exact_kana.borrow());
            let text: &str = &(binding.as_str());
            question_label.set_label(text);
            answer_entry.set_text("");
        });

        answer_entry_binding.connect_closure("activate", false, iteration);
    }
}

impl WidgetImpl for GuessingScene {}

impl WindowImpl for GuessingScene {}

impl ApplicationWindowImpl for GuessingScene {}
