use std::fmt::Write;

use gettextrs::gettext;
use gtk::{glib, prelude::*, subclass::prelude::*};

use crate::level_bar::LevelBar;

mod imp {
    use std::cell::Cell;

    use super::*;

    #[derive(Debug, Default, glib::Properties)]
    #[properties(wrapper_type = super::ContrastLevelBar)]
    pub struct ContrastLevelBar {
        pub level_label: gtk::Label,
        pub level_bar: LevelBar,
        #[property(get, set = Self::set_contrast_level, minimum = 0.0, maximum = 21.0, default = 0.0)]
        pub contrast_level: Cell<f32>,
    }

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

        fn class_init(klass: &mut Self::Class) {
            klass.set_layout_manager_type::<gtk::BoxLayout>();
        }
    }

    #[glib::derived_properties]
    impl ObjectImpl for ContrastLevelBar {
        fn constructed(&self) {
            self.parent_constructed();
            let obj = self.obj();
            let layout_manager = obj
                .layout_manager()
                .and_downcast::<gtk::BoxLayout>()
                .unwrap();
            layout_manager.set_orientation(gtk::Orientation::Vertical);
            obj.set_halign(gtk::Align::Fill);
            obj.set_valign(gtk::Align::Center);
            obj.set_vexpand(true);
            obj.add_css_class("level-box");

            self.level_bar.add_marker_at("A", 3.5);
            self.level_bar.add_marker_at("AA", 4.5);
            self.level_bar.add_marker_at("AAA", 7.0);
            obj.bind_property("contrast-level", &self.level_bar, "value")
                .sync_create()
                .build();
            obj.append(&self.level_bar);

            self.level_label.add_css_class("level-label");
            self.level_label.set_halign(gtk::Align::Center);
            self.level_label.set_valign(gtk::Align::Start);
            obj.append(&self.level_label);
        }
    }

    impl WidgetImpl for ContrastLevelBar {}

    impl BoxImpl for ContrastLevelBar {}

    impl ContrastLevelBar {
        fn set_contrast_level(&self, contrast_level: f32) {
            let mut level_label = gettext("Contrast Ratio∶ ");
            if contrast_level.fract() != 0.0 {
                write!(level_label, "{:.1}∶1", contrast_level).unwrap();
            } else {
                write!(level_label, "{:}∶1", contrast_level as i32).unwrap();
            }
            self.level_label.set_text(&level_label);
            self.contrast_level.set(contrast_level);
        }
    }
}

glib::wrapper! {
    pub struct ContrastLevelBar(ObjectSubclass<imp::ContrastLevelBar>)
        @extends gtk::Widget, gtk::Box;
}
