use seed::{prelude::*, *};
use seed_hooks::{state_access::CloneState, topo, use_state};

use crate::{
    api::urls,
    state::{Context, Model, Msg, Tag},
    view::{self, view_header, view_search_results},
};

#[topo::nested]
pub(super) fn view(model: &Model) -> Node<Msg> {
    log::info!("tablet::view");
    let show_icon_text = true;
    // Do two queries, one without `unread` so it loads fast, then a second with unread.
    let content = match &model.context {
        Context::None => div![h1!["Loading"]],
        Context::ThreadResult {
            thread,
            open_messages,
        } => view::thread(thread, open_messages, show_icon_text),
        Context::SearchResult {
            query,
            results,
            count,
            pager,
            selected_threads,
        } => view_search_results(
            &query,
            results.as_slice(),
            *count,
            pager,
            selected_threads,
            show_icon_text,
        ),
    };
    fn view_tag_li(display_name: &str, indent: usize, t: &Tag, search_unread: bool) -> Node<Msg> {
        let href = if search_unread {
            urls::search(&format!("is:unread tag:{}", t.name), 0)
        } else {
            urls::search(&format!("tag:{}", t.name), 0)
        };
        li![a![
            attrs! {
                At::Href => href
            },
            (0..indent).map(|_| span![C!["tag-indent"], ""]),
            i![
                C!["tag-tag", "fa-solid", "fa-tag"],
                style! {
                    //"--fa-primary-color" => t.fg_color,
                    St::Color => t.bg_color,
                },
            ],
            display_name,
            IF!(t.unread>0 => format!(" ({})", t.unread))
        ]]
    }
    fn matches(a: &[&str], b: &[&str]) -> usize {
        std::iter::zip(a.iter(), b.iter())
            .take_while(|(a, b)| a == b)
            .count()
    }
    fn view_tag_list<'a>(
        tags: impl Iterator<Item = &'a Tag>,
        search_unread: bool,
    ) -> Vec<Node<Msg>> {
        let mut lis = Vec::new();
        let mut last = Vec::new();
        for t in tags {
            let parts: Vec<_> = t.name.split('/').collect();
            let mut n = matches(&last, &parts);
            if n <= parts.len() - 2 && parts.len() > 1 {
                // Synthesize fake tags for proper indenting.
                for i in n..parts.len() - 1 {
                    let display_name = parts[n];
                    lis.push(view_tag_li(
                        &display_name,
                        n,
                        &Tag {
                            name: parts[..i + 1].join("/"),
                            bg_color: "#fff".to_string(),
                            fg_color: "#000".to_string(),
                            unread: 0,
                        },
                        search_unread,
                    ));
                }
                n = parts.len() - 1;
            }
            let display_name = parts[n];
            lis.push(view_tag_li(&display_name, n, t, search_unread));
            last = parts;
        }
        lis
    }
    let unread = model
        .tags
        .as_ref()
        .map(|tags| tags.iter().filter(|t| t.unread > 0).collect())
        .unwrap_or(Vec::new());
    let tags_open = use_state(|| false);
    let force_tags_open = unread.is_empty();
    div![
        C!["main-content"],
        aside![
            C!["tags-menu", "menu"],
            IF!(!unread.is_empty() => p![C!["menu-label"], "Unread"]),
            IF!(!unread.is_empty() => ul![C!["menu-list"], view_tag_list(unread.into_iter(),true)]),
            p![
                C!["menu-label"],
                IF!(!force_tags_open =>
                i![C![
                    "fa-solid",
                    if tags_open.get() {
                        "fa-angle-up"
                    } else {
                        "fa-angle-down"
                    }
                ]]),
                " Tags",
                ev(Ev::Click, move |_| {
                    tags_open.set(!tags_open.get());
                })
            ],
            ul![
                C!["menu-list"],
                IF!(force_tags_open||tags_open.get() => model.tags.as_ref().map(|tags| view_tag_list(tags.iter(),false))),
            ]
        ],
        div![
            view_header(&model.query, &model.refreshing_state),
            content,
            view_header(&model.query, &model.refreshing_state),
        ]
    ]
}
