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

//! A row element that can have title, subtitle, prefix and suffix children.
//! Should be placed in a `list`.

use std::rc::Rc;

use glib::Cast;
use grx_macros::gtk_component;
use gtk::glib;
use gtk::traits::ListBoxRowExt;
use libadwaita::traits::{ExpanderRowExt, PreferencesRowExt};

use crate::{default_clear, default_remove, new_gc, props, Component, ComponentExt, ContainerExt};

use super::gtk_props::apply;

#[props]
#[derive(Default, Debug)]
pub struct Props {
    pub title: String,
    pub subtitle: String,
    pub selectable: Option<bool>,
    pub activatable: Option<bool>,
    pub expanded: Option<bool>,
}

pub fn expander_row(mut props: Props) -> Rc<ExpanderRow> {
    let row = libadwaita::ExpanderRow::builder()
        .title(&props.title)
        .subtitle(&props.subtitle)
        .build();
    if let Some(b) = props.activatable {
        row.set_activatable(b)
    }
    if let Some(b) = props.selectable {
        row.set_selectable(b)
    }
    if let Some(b) = props.expanded {
        row.set_expanded(b)
    }
    let comp = new_gc!(ExpanderRow { row, props });

    for c in comp.children().iter() {
        if c.annotations().contains_key("prefix") {
            comp.add_prefix(c.clone())
        } else if c.annotations().contains_key("suffix") {
            comp.add_suffix(c.clone())
        } else {
            comp.append(c.clone());
        }
    }

    apply(comp.clone());
    comp
}

#[gtk_component(libadwaita::ExpanderRow)]
#[derive(Debug)]
pub struct ExpanderRow {}

impl ExpanderRow {
    /// Set whether the row is expanded or collapsed.
    pub fn set_expanded(self: &Rc<Self>, expanded: bool) {
        self.widget.set_expanded(expanded);
    }

    pub fn set_title(self: &Rc<Self>, title: &str) {
        self.widget.set_title(title);
    }

    pub fn set_subtitle(self: &Rc<Self>, subtitle: &str) {
        self.widget.set_subtitle(subtitle);
    }

    pub fn add_prefix(self: &Rc<Self>, component: Component) {
        let widget: Rc<gtk::Widget> = component.inner().downcast().unwrap();
        self.widget.add_prefix(widget.as_ref());
    }

    pub fn add_suffix(self: &Rc<Self>, component: Component) {
        let widget: Rc<gtk::Widget> = component.inner().downcast().unwrap();
        self.widget.add_action(widget.as_ref());
    }
}

impl ContainerExt for ExpanderRow {
    fn append<W>(self: &Rc<Self>, child: Rc<W>)
    where
        W: crate::ComponentExt + ?Sized,
    {
        let inner = child.inner();
        let w: &gtk::Widget = inner.downcast_ref().unwrap();
        self.widget.add_row(w);
    }
    default_clear! {}

    default_remove! {}
}
