//! Visual demonstration of every supported `justify_content` mode.
//!
//! The window arranges one labeled cell per mode in a two-column grid. Each
//! cell is a flex container of the same fixed width with four
//! identically-sized children, so the only visible difference between cells is
//! how `justify_content` distributes the leftover space along the main axis.

use ruin_app::prelude::*;

const TRACK_WIDTH: f32 = 360.0;
const ITEM_SIZE: f32 = 44.0;

#[ruin_runtime::async_main]
async fn main() -> ruin_app::Result<()> {
    App::new()
        .window(
            Window::new()
                .title("RUIN justify_content")
                .app_id("dev.ruin.justify-content")
                .size(960.0, 620.0),
        )
        .mount(view! {
            JustifyContentGallery() {}
        })
        .run()
        .await
}

#[component]
fn JustifyContentGallery() -> impl IntoView {
    let canvas = Color::rgb(0x10, 0x16, 0x22);
    let panel = Color::rgb(0x1A, 0x23, 0x33);
    let accent = Color::rgb(0x71, 0xA7, 0xF7);
    let text_color = Color::rgb(0xF5, 0xF7, 0xFB);
    let muted = Color::rgb(0x9A, 0xA9, 0xC2);

    view! {
        column(gap = 18.0, padding = 24.0, background = canvas) {
            text(role = TextRole::Heading(1), size = 28.0, weight = FontWeight::Semibold, color = text_color) {
                "justify_content"
            }
            text(color = muted, wrap = TextWrap::Word) {
                "Each cell below is the same width and contains the same four boxes. The only \
                 thing that changes between cells is `justify_content`, which controls how the \
                 leftover space along the main axis is distributed."
            }

            row(gap = 16.0, align_items = AlignItems::Start) {
                column(gap = 14.0, flex = 1.0) {
                    JustifyRow(
                        label = "Start",
                        description = "Pack children at the start of the main axis (default).",
                        justify = JustifyContent::Start,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                    JustifyRow(
                        label = "End",
                        description = "Pack children at the end of the main axis.",
                        justify = JustifyContent::End,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                    JustifyRow(
                        label = "Center",
                        description = "Pack children as a group, centered on the main axis.",
                        justify = JustifyContent::Center,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                }
                column(gap = 14.0, flex = 1.0) {
                    JustifyRow(
                        label = "SpaceBetween",
                        description = "First child flush with the start, last with the end, equal gaps between.",
                        justify = JustifyContent::SpaceBetween,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                    JustifyRow(
                        label = "SpaceAround",
                        description = "Equal space around each child; end gaps are half the gap between children.",
                        justify = JustifyContent::SpaceAround,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                    JustifyRow(
                        label = "SpaceEvenly",
                        description = "Equal space between children and between children and both edges.",
                        justify = JustifyContent::SpaceEvenly,
                        panel = panel,
                        accent = accent,
                        text_color = text_color,
                        muted = muted,
                    ) {}
                }
            }
        }
    }
}

#[component]
fn JustifyRow(
    label: &'static str,
    description: &'static str,
    justify: JustifyContent,
    panel: Color,
    accent: Color,
    text_color: Color,
    muted: Color,
) -> impl IntoView {
    view! {
        column(
            gap = 6.0,
            padding = 12.0,
            background = panel,
            border_radius = 10.0,
            border = (1.0, accent),
        ) {
            row(gap = 10.0, align_items = AlignItems::Center) {
                text(size = 16.0, weight = FontWeight::Semibold, color = text_color) { label }
                text(color = muted) { description }
            }
            row(
                width = TRACK_WIDTH,
                height = ITEM_SIZE + 16.0,
                padding = 8.0,
                gap = 8.0,
                background = Color::rgba(0xFF, 0xFF, 0xFF, 0x10),
                border_radius = 6.0,
                align_items = AlignItems::Center,
                justify_content = justify,
            ) {
                JustifyItem(label = "1", accent = accent, text_color = text_color) {}
                JustifyItem(label = "2", accent = accent, text_color = text_color) {}
                JustifyItem(label = "3", accent = accent, text_color = text_color) {}
                JustifyItem(label = "4", accent = accent, text_color = text_color) {}
            }
        }
    }
}

#[component]
fn JustifyItem(label: &'static str, accent: Color, text_color: Color) -> impl IntoView {
    view! {
        block(
            width = ITEM_SIZE,
            height = ITEM_SIZE,
            background = accent,
            border_radius = 6.0,
            align_items = AlignItems::Center,
        ) {
            row(
                flex = 1.0,
                align_items = AlignItems::Center,
                justify_content = JustifyContent::Center,
            ) {
                text(size = 18.0, weight = FontWeight::Semibold, color = text_color) { label }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn gallery_renders_all_labels() {
        let root = JustifyContentGallery::builder().children(());
        let view = ruin_app::__render_mountable_for_test(&root);
        let snapshot = ruin_ui::layout_snapshot(1, UiSize::new(960.0, 620.0), view.element());

        for label in ["Start", "End", "Center", "SpaceBetween", "SpaceAround", "SpaceEvenly"] {
            assert!(
                snapshot.scene.items.iter().any(|item| matches!(
                    item,
                    ruin_ui::DisplayItem::Text(text) if text.text.contains(label)
                )),
                "expected `{label}` label to appear in the rendered scene",
            );
        }
    }
}
