//! Bottom thumbnail strip — lazy-loaded, horizontal scrollable.
//!
//! Thumbnails are decoded in the background at 80px max dimension. The cache
//! is keyed by image index. On navigation, the app requests thumbnails for
//! the current ±10 window that aren't yet cached.

use std::collections::HashMap;
use std::path::PathBuf;

use iced::widget::{button, container, row, scrollable, text};
use iced::{Element, Length};

use super::theme;

pub const THUMB_SIZE: f32 = 72.0;
pub const THUMB_PADDING: f32 = 4.0;
pub const BAR_HEIGHT: f32 = THUMB_SIZE + 2.0 * THUMB_PADDING + 4.0; // 80
const THUMB_ENTRY_WIDTH: f32 = THUMB_SIZE + 2.0 + 2.0; // image + border + spacing

/// The scrollable Id for the thumbnail strip. Used by the app layer
/// to programmatically scroll the strip so the current image stays visible
/// (video-editor-timeline behavior).
pub fn thumb_scroll_id() -> scrollable::Id {
    scrollable::Id::new("thumbnails")
}

/// State for the thumbnail bar.
#[derive(Debug, Clone, Default)]
pub struct ThumbnailBar {
    /// Paths to all images in the folder.
    pub paths: Vec<PathBuf>,
    /// Current index (highlighted).
    pub current: usize,
    /// Cached thumbnail handles, keyed by index.
    pub cache: HashMap<usize, iced::widget::image::Handle>,
}

#[derive(Debug, Clone)]
pub enum ThumbnailMessage {
    Clicked(usize),
}

impl ThumbnailBar {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn set_paths(&mut self, paths: Vec<PathBuf>, current: usize) {
        self.paths = paths;
        self.current = current;
        self.cache.clear();
    }

    pub fn set_current(&mut self, current: usize) {
        self.current = current;
    }

    pub fn insert_thumbnail(&mut self, index: usize, handle: iced::widget::image::Handle) {
        self.cache.insert(index, handle);
    }

    /// Which thumbnail indices should be requested for decoding?
    /// Returns the current ±10 window that aren't in the cache.
    pub fn needed_thumbnails(&self, window: usize) -> Vec<usize> {
        if self.paths.is_empty() {
            return Vec::new();
        }
        let start = self.current.saturating_sub(window);
        let end = (self.current + window + 1).min(self.paths.len());
        (start..end)
            .filter(|i| !self.cache.contains_key(i))
            .collect()
    }

    /// Render the thumbnail bar.
    pub fn view(&self) -> Element<'_, ThumbnailMessage> {
        if self.paths.is_empty() {
            return container(
                text("No images loaded")
                    .color(theme::TEXT_DIM)
                    .size(11),
            )
            .width(Length::Fill)
            .height(Length::Fixed(BAR_HEIGHT))
            .align_x(iced::Alignment::Center)
            .align_y(iced::Alignment::Center)
            .style(|_| container::Style {
                background: Some(theme::BG_CHROME.into()),
                border: iced::Border {
                    color: theme::BG_CHROME_BORDER,
                    width: 1.0,
                    radius: 0.0.into(),
                },
                ..Default::default()
            })
            .into();
        }

        let thumbs: Vec<Element<'_, ThumbnailMessage>> = self
            .paths
            .iter()
            .enumerate()
            .map(|(i, path)| {
                let is_current = i == self.current;

                let inner: Element<'_, ThumbnailMessage> = if let Some(handle) = self.cache.get(&i) {
                    // Cached thumbnail — show the image.
                    iced::widget::image(handle.clone())
                        .width(Length::Fixed(THUMB_SIZE))
                        .height(Length::Fixed(THUMB_SIZE))
                        .content_fit(iced::ContentFit::Cover)
                        .into()
                } else {
                    // Not yet decoded — show a placeholder with the file extension.
                    let ext = path
                        .extension()
                        .and_then(|e| e.to_str())
                        .unwrap_or("?")
                        .to_uppercase();
                    container(
                        text(ext).color(theme::TEXT_DIM).size(10),
                    )
                    .width(Length::Fixed(THUMB_SIZE))
                    .height(Length::Fixed(THUMB_SIZE))
                    .align_x(iced::Alignment::Center)
                    .align_y(iced::Alignment::Center)
                    .style(|_| container::Style {
                        background: Some(theme::BG_CHROME_BORDER.into()),
                        ..Default::default()
                    })
                    .into()
                };

                // Wrap in a container that adds a border for the current thumb.
                let bordered = container(inner)
                    .width(Length::Fixed(THUMB_SIZE + 2.0))
                    .height(Length::Fixed(THUMB_SIZE + 2.0))
                    .padding(1.0)
                    .style(move |_| container::Style {
                        border: iced::Border {
                            color: if is_current {
                                theme::ACCENT
                            } else {
                                iced::Color::TRANSPARENT
                            },
                            width: if is_current { 2.0 } else { 0.0 },
                            radius: 3.0.into(),
                        },
                        background: Some(theme::BG_IMAGE_AREA.into()),
                        ..Default::default()
                    });

                button(bordered)
                    .on_press(ThumbnailMessage::Clicked(i))
                    .padding(0.0)
                    .style(|_theme, _status| button::Style {
                        background: Some(iced::Color::TRANSPARENT.into()),
                        border: iced::Border {
                            radius: 3.0.into(),
                            ..Default::default()
                        },
                        ..Default::default()
                    })
                    .into()
            })
            .collect();

        let strip = row(thumbs)
            .padding(iced::Padding {
                top: THUMB_PADDING,
                right: THUMB_PADDING,
                bottom: THUMB_PADDING,
                left: THUMB_PADDING,
            })
            .spacing(2.0)
            .align_y(iced::Alignment::Center);

        let scrollable = scrollable(strip)
            .id(thumb_scroll_id())
            .direction(scrollable::Direction::Horizontal(
                scrollable::Scrollbar::new().width(4).scroller_width(4),
            ))
            .width(Length::Fill)
            .height(Length::Fixed(BAR_HEIGHT));

        container(scrollable)
            .width(Length::Fill)
            .height(Length::Fixed(BAR_HEIGHT))
            .style(|_| container::Style {
                background: Some(theme::BG_CHROME.into()),
                border: iced::Border {
                    color: theme::BG_CHROME_BORDER,
                    width: 1.0,
                    radius: 0.0.into(),
                },
                ..Default::default()
            })
            .into()
    }
}
