use std::rc::Rc;

use ruin_ui::{CursorIcon, Edges, Element, RoutedPointerEvent};

use crate::context::allocate_element_id;
use crate::input::PressHandler;
use crate::primitives::ContainerProps;
use crate::surfaces;
use crate::text_style::{pop_text_style, push_text_style};
use crate::view::{Children, View};

pub struct ButtonBuilder {
    pub(crate) props: ContainerProps,
    pub(crate) on_press: Option<PressHandler>,
}

pub fn button() -> ButtonBuilder {
    ButtonBuilder {
        props: ContainerProps::new(
            Element::column()
                .padding(Edges::symmetric(14.0, 10.0))
                .background(surfaces::interactive())
                .corner_radius(10.0)
                .cursor(CursorIcon::Pointer)
                .focusable(true),
        ),
        on_press: None,
    }
}

impl ButtonBuilder {
    impl_props_methods!();

    pub fn shadow(mut self, shadow: impl crate::converters::IntoShadow) -> Self {
        self.props = self.props.shadow(shadow);
        self
    }

    pub fn on_press(mut self, handler: impl Fn(&RoutedPointerEvent) + 'static) -> Self {
        self.on_press = Some(Rc::new(handler));
        self
    }

    pub fn text_style(mut self, style: crate::text_style::PartialTextStyle) -> Self {
        self.props = self.props.text_style(style);
        self
    }

    pub fn children(mut self, children: impl Children) -> View {
        let id = allocate_element_id();
        self.props.element = self.props.element.id(id);
        if let Some(widget_ref) = &self.props.widget_ref {
            let _ = widget_ref.set(Some(id));
        }
        let had_style = self.props.partial_text_style.is_some();
        if let Some(style) = self.props.partial_text_style.take() {
            push_text_style(style);
        }
        let children_views = children.into_views();
        if had_style {
            pop_text_style();
        }
        let view = View::from_container(self.props.element, children_views);
        match self.on_press {
            Some(handler) => view.with_press_handler(id, handler),
            None => view,
        }
    }
}
