pub(crate) mod detail;
pub(crate) mod library;
pub(crate) mod season_detail;
pub(crate) mod tmdb_matcher;

use crate::database::Database;
use iced::Task;

#[derive(Debug, Clone)]
pub(crate) enum Message {
    LibraryItemHover(Option<usize>),
    LibraryScrolled(iced::widget::scrollable::Viewport),
    TmdbToggleSearch,
    TmdbSearchQueryChanged(String),
    TmdbSearchSubmit,
    TmdbSearchCompleted(Result<Vec<tmdb_matcher::ShowTmdbSearchResultItem>, String>),
    TmdbSelectMatch(usize),
    TmdbMatchCompleted(Result<tmdb_matcher::ShowMatchData, String>),
}

pub(crate) struct State {
    pub(crate) items: Vec<library::ShowLibraryItem>,
    pub(crate) seasons: Vec<detail::SeasonItem>,
    pub(crate) season_episodes: Vec<season_detail::EpisodeItem>,
    pub(crate) scroll_offset: f32,
    pub(crate) viewport_height: f32,
    pub(crate) hovered_item: Option<usize>,
    pub(crate) tmdb_state: Option<tmdb_matcher::ShowTmdbMatcherState>,
}

impl State {
    pub(crate) fn new(items: Vec<library::ShowLibraryItem>) -> Self {
        Self {
            items,
            seasons: Vec::new(),
            season_episodes: Vec::new(),
            scroll_offset: 0.0,
            viewport_height: 0.0,
            hovered_item: None,
            tmdb_state: None,
        }
    }
}

pub(crate) fn update(
    state: &mut State,
    msg: Message,
    db: &mut Database,
    tmdb_token: &Option<String>,
) -> Task<crate::ui::Message> {
    match msg {
        Message::LibraryItemHover(idx) => {
            state.hovered_item = idx;
            Task::none()
        }
        Message::LibraryScrolled(viewport) => {
            state.scroll_offset = viewport.absolute_offset().y;
            state.viewport_height = viewport.bounds().height;
            Task::none()
        }
        Message::TmdbMatchCompleted(result) => {
            if let Some(tmdb_state) = &mut state.tmdb_state {
                tmdb_state.matching = false;
                match result {
                    Ok(data) => {
                        let show_index = tmdb_state.show_index;
                        let show_id = state.items[show_index].id;
                        tmdb_matcher::apply_match(&data, show_id, db, &mut state.items[show_index]);
                        tmdb_state.search_expanded = false;
                        tmdb_state.search_results.clear();
                    }
                    Err(e) => {
                        tmdb_state.error = Some(e);
                    }
                }
            }
            Task::none()
        }
        Message::TmdbToggleSearch
        | Message::TmdbSearchQueryChanged(_)
        | Message::TmdbSearchSubmit
        | Message::TmdbSearchCompleted(_)
        | Message::TmdbSelectMatch(_) => {
            if let Some(tmdb_state) = &mut state.tmdb_state {
                tmdb_matcher::update(tmdb_state, msg, tmdb_token)
            } else {
                Task::none()
            }
        }
    }
}
