use gtk::{
    glib::self,
    prelude::*,
    subclass::prelude::*,
};

#[derive(Copy, Clone, Debug, glib::Enum, Default)]
#[enum_type(name = "WildcardCaptureKind")]
pub enum CaptureKind {
    #[default]
    Overall,
    Group,
}

mod imp {
    use std::{
        cell::{Cell, RefCell},
        sync::LazyLock,
    };

    use super::*;

    #[derive(glib::Properties)]
    #[properties(wrapper_type = super::Capture)]
    pub struct Capture {
        #[property(get, set)]
        pub position: RefCell<u32>,
        #[property(get, set)]
        pub group_index: RefCell<u32>,
        #[property(get, set)]
        pub group_name: RefCell<Option<String>>,
        #[property(get, set)]
        pub string: RefCell<String>,
        #[property(get, set)]
        pub start: RefCell<u32>,
        #[property(get, set)]
        pub end: RefCell<u32>,

        #[property(get, set, builder(CaptureKind::Overall))]
        pub kind: Cell<CaptureKind>,
    }

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

        fn new() -> Self {
            Self {
                position: RefCell::default(),
                group_index: RefCell::default(),
                group_name: RefCell::default(),
                string: RefCell::default(),
                start: RefCell::default(),
                end: RefCell::default(),
                kind: Cell::default(),
            }
        }
    }

    impl ObjectImpl for Capture {
        fn properties() -> &'static [glib::ParamSpec] {
            static PROPERTIES: LazyLock<Vec<glib::ParamSpec>> = LazyLock::new(|| {
                Capture::derived_properties().to_vec()
            });
            PROPERTIES.as_ref()
        }

        fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
            match pspec.name() {
                _ => self.derived_set_property(id, value, pspec),
            }
        }

        fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
            match pspec.name() {
                _ => self.derived_property(id, pspec),
            }
        }
    }

    impl Capture {

    }
}

glib::wrapper! {
    pub struct Capture(ObjectSubclass<imp::Capture>);
}

impl Capture {
    pub fn new(
        kind: CaptureKind,
        position: u32,
        group_index: u32,
        group_name: Option<&str>,
        string: &str,
        start: u32,
        end: u32,
    ) -> Capture {
        glib::Object::builder::<Self>()
            .property("position", position)
            .property("group-index", group_index)
            .property("group-name", group_name)
            .property("string", string.to_string())
            .property("start", start)
            .property("end", end)
            .property("kind", kind)
            .build()
    }
}

