// SPDX-License-Identifier: GPL-3.0-or-later

//! The switch component

use super::gtk_props::apply;
use crate::{handlers::Handler, new_gc, Interactable};
use glib::Cast;
use grx_macros::{gtk_component, props};
use gtk::glib;
use std::{cell::Cell, rc::Rc};

#[props]
#[derive(Default)]
pub struct Props {
    pub on_change: Option<Handler<Switch>>,
}

impl std::fmt::Debug for Props {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Props")
            .field("id", &self.id)
            .field("classes", &self.classes)
            .field("styles", &self.styles)
            .field("children", &self.children)
            .field("on_change", &self.on_change.is_some())
            .finish()
    }
}

pub fn switch(mut props: Props) -> Rc<Switch> {
    let switch = gtk::Switch::builder().build();
    let sw = switch.clone();
    let onc = props.on_change.take();
    let switch = new_gc!(Switch {
        switch,
        props,
        state: false.into()
    });

    apply(switch.clone());

    if onc.is_some() {
        let btn = switch.clone();
        sw.connect_activate(move |_| {
            if let Some(c) = &onc {
                c(btn.clone());
            }
        });
    }

    switch
}

#[gtk_component(gtk::Switch)]
#[derive(Debug)]
pub struct Switch {
    state: Cell<bool>,
}

impl Switch {
    pub fn set_state(self: &Rc<Self>, state: bool) {
        self.state.replace(state);
        self.widget.set_state(state);
    }
    pub fn state(self: &Rc<Self>) -> bool {
        self.state.get()
    }
}

impl Interactable for Switch {
    #[allow(unused_variables)]
    fn on_click(self: &Rc<Self>, handler: impl Fn(&Rc<Self>) + 'static) {
        // ignore
    }

    #[allow(unused_variables)]
    fn on_change(self: &Rc<Self>, handler: impl Fn(&Rc<Self>) + 'static) {
        let s = self.clone();
        self.widget.connect_state_set(move |_, state| {
            s.state.replace(state);
            handler(&s);
            gtk::Inhibit(false)
        });
    }

    #[allow(unused_variables)]
    fn on_swipe(self: &Rc<Self>, handler: impl Fn(&Rc<Self>, f64, f64) + 'static) {
        // optional
    }

    #[allow(unused_variables)]
    fn on_blur(self: &Rc<Self>, handler: impl Fn(&Rc<Self>) + 'static) {
        // optional
    }
}
