use dioxus::prelude::*;
use freya_core::platform::CursorIcon;
use freya_elements::{
    self as dioxus_elements,
    events::MouseEvent,
};
use freya_hooks::{
    use_animation,
    use_applied_theme,
    use_platform,
    AccordionTheme,
    AccordionThemeWith,
    AnimNum,
    Ease,
    Function,
};
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum AccordionStatus {
    #[default]
    Idle,
    Hovering,
}
#[derive(Props, Clone, PartialEq)]
pub struct AccordionProps {
    pub theme: Option<AccordionThemeWith>,
    pub children: Element,
    pub summary: Element,
}
#[allow(non_snake_case)]
pub fn Accordion(props: AccordionProps) -> Element {
    let theme = use_applied_theme!(&props.theme, accordion);
    let mut open = use_signal(|| false);
    let animation = use_animation(move |_conf| {
        AnimNum::new(0., 100.)
            .time(300)
            .function(Function::Expo)
            .ease(Ease::Out)
    });
    let mut status = use_signal(AccordionStatus::default);
    let platform = use_platform();
    let animation_value = animation.get().read().read();
    let AccordionTheme {
        background,
        color,
        border_fill,
    } = theme;
    let onclick = move |_: MouseEvent| {
        open.toggle();
        if *open.read() {
            animation.start();
        } else {
            animation.reverse();
        }
    };
    use_drop(move || {
        if *status.read() == AccordionStatus::Hovering {
            platform.set_cursor(CursorIcon::default());
        }
    });
    let onmouseenter = move |_| {
        platform.set_cursor(CursorIcon::Pointer);
        status.set(AccordionStatus::Hovering);
    };
    let onmouseleave = move |_| {
        platform.set_cursor(CursorIcon::default());
        status.set(AccordionStatus::default());
    };
    rsx!(
        rect {
            onmouseenter,
            onmouseleave,
            overflow: "clip",
            color: "{color}",
            padding: "10",
            margin: "2 4",
            corner_radius: "6",
            width: "100%",
            height: "auto",
            background: "{background}",
            onclick,
            border: "1 inner {border_fill}",
            {&props.summary}
            rect {
                overflow: "clip",
                width: "100%",
                visible_height: "{animation_value}%",
                {&props.children}
            }
        }
    )
}
#[derive(Props, Clone, PartialEq)]
pub struct AccordionSummaryProps {
    children: Element,
}
#[allow(non_snake_case)]
pub fn AccordionSummary(props: AccordionSummaryProps) -> Element {
    rsx!({ props.children })
}
#[derive(Props, Clone, PartialEq)]
pub struct AccordionBodyProps {
    children: Element,
}
#[allow(non_snake_case)]
pub fn AccordionBody(props: AccordionBodyProps) -> Element {
    rsx!(rect {
        width: "100%",
        padding: "15 0 0 0",
        {props.children}
    })
}
#[cfg(test)]
mod test {
    use std::time::Duration;
    use freya::prelude::*;
    use freya_testing::prelude::*;
    use tokio::time::sleep;
    #[tokio::test]
    pub async fn accordion() {
        fn accordion_app() -> Element {
            rsx!(
                Accordion {
                    summary: rsx!(AccordionSummary {
                        label {
                            "Accordion Summary"
                        }
                    }),
                    AccordionBody {
                        label {
                            "Accordion Body"
                        }
                    }
                }
            )
        }
        let mut utils = launch_test(accordion_app);
        let root = utils.root();
        let content = root.get(0).get(1).get(0);
        let label = content.get(0);
        utils.wait_for_update().await;
        assert!(!label.is_visible());
        utils.click_cursor((5., 5.)).await;
        sleep(Duration::from_millis(70)).await;
        utils.wait_for_update().await;
        assert!(label.is_visible());
    }
}