use crate::{
    layout, mouse, row, text, Align, Clipboard, Element, Event, Hasher,
    HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text,
    VerticalAlignment, Widget,
};
use std::hash::Hash;
#[allow(missing_debug_implementations)]
pub struct Radio<Message, Renderer: self::Renderer + text::Renderer> {
    is_selected: bool,
    on_click: Message,
    label: String,
    width: Length,
    size: u16,
    spacing: u16,
    text_size: Option<u16>,
    style: Renderer::Style,
}
impl<Message, Renderer: self::Renderer + text::Renderer>
    Radio<Message, Renderer>
{
    
    
    
    
    
    
    
    
    
    
    pub fn new<F, V>(
        value: V,
        label: impl Into<String>,
        selected: Option<V>,
        f: F,
    ) -> Self
    where
        V: Eq + Copy,
        F: 'static + Fn(V) -> Message,
    {
        Radio {
            is_selected: Some(value) == selected,
            on_click: f(value),
            label: label.into(),
            width: Length::Shrink,
            size: <Renderer as self::Renderer>::DEFAULT_SIZE,
            spacing: Renderer::DEFAULT_SPACING, 
            text_size: None,
            style: Renderer::Style::default(),
        }
    }
    
    
    
    pub fn size(mut self, size: u16) -> Self {
        self.size = size;
        self
    }
    
    
    
    pub fn width(mut self, width: Length) -> Self {
        self.width = width;
        self
    }
    
    
    
    pub fn spacing(mut self, spacing: u16) -> Self {
        self.spacing = spacing;
        self
    }
    
    
    
    pub fn text_size(mut self, text_size: u16) -> Self {
        self.text_size = Some(text_size);
        self
    }
    
    
    
    pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
        self.style = style.into();
        self
    }
}
impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer>
where
    Renderer: self::Renderer + text::Renderer + row::Renderer,
    Message: Clone,
{
    fn width(&self) -> Length {
        self.width
    }
    fn height(&self) -> Length {
        Length::Shrink
    }
    fn layout(
        &self,
        renderer: &Renderer,
        limits: &layout::Limits,
    ) -> layout::Node {
        Row::<(), Renderer>::new()
            .width(self.width)
            .spacing(self.spacing)
            .align_items(Align::Center)
            .push(
                Row::new()
                    .width(Length::Units(self.size))
                    .height(Length::Units(self.size)),
            )
            .push(
                Text::new(&self.label)
                    .width(self.width)
                    .size(self.text_size.unwrap_or(renderer.default_size())),
            )
            .layout(renderer, limits)
    }
    fn on_event(
        &mut self,
        event: Event,
        layout: Layout<'_>,
        cursor_position: Point,
        messages: &mut Vec<Message>,
        _renderer: &Renderer,
        _clipboard: Option<&dyn Clipboard>,
    ) {
        match event {
            Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
                if layout.bounds().contains(cursor_position) {
                    messages.push(self.on_click.clone());
                }
            }
            _ => {}
        }
    }
    fn draw(
        &self,
        renderer: &mut Renderer,
        defaults: &Renderer::Defaults,
        layout: Layout<'_>,
        cursor_position: Point,
    ) -> Renderer::Output {
        let bounds = layout.bounds();
        let mut children = layout.children();
        let radio_layout = children.next().unwrap();
        let label_layout = children.next().unwrap();
        let radio_bounds = radio_layout.bounds();
        let label = text::Renderer::draw(
            renderer,
            defaults,
            label_layout.bounds(),
            &self.label,
            self.text_size.unwrap_or(renderer.default_size()),
            Default::default(),
            None,
            HorizontalAlignment::Left,
            VerticalAlignment::Center,
        );
        let is_mouse_over = bounds.contains(cursor_position);
        self::Renderer::draw(
            renderer,
            radio_bounds,
            self.is_selected,
            is_mouse_over,
            label,
            &self.style,
        )
    }
    fn hash_layout(&self, state: &mut Hasher) {
        struct Marker;
        std::any::TypeId::of::<Marker>().hash(state);
        self.label.hash(state);
    }
}
pub trait Renderer: crate::Renderer {
    
    type Style: Default;
    
    
    
    const DEFAULT_SIZE: u16;
    
    
    
    const DEFAULT_SPACING: u16;
    
    
    
    
    
    
    
    
    
    fn draw(
        &mut self,
        bounds: Rectangle,
        is_selected: bool,
        is_mouse_over: bool,
        label: Self::Output,
        style: &Self::Style,
    ) -> Self::Output;
}
impl<'a, Message, Renderer> From<Radio<Message, Renderer>>
    for Element<'a, Message, Renderer>
where
    Renderer: 'a + self::Renderer + row::Renderer + text::Renderer,
    Message: 'a + Clone,
{
    fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> {
        Element::new(radio)
    }
}