// bibiman - a TUI for managing BibLaTeX databases
// Copyright (C) 2024  lukeflo
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
/////

use nucleo_matcher::{
    Config, Matcher,
    pattern::{CaseMatching, Normalization, Pattern},
};
use ratatui::widgets::{ListState, ScrollbarState};

#[derive(Debug)]
pub struct TagList {
    pub tag_list_items: Vec<String>,
    pub tag_list_at_search_start: Vec<String>,
    pub tag_list_state: ListState,
    pub tag_scroll_state: ScrollbarState,
    pub selected_keywords: Vec<String>,
    pub(crate) search_string: String, // pub tag_list_search: BibiSearch,
}

impl TagList {
    pub fn new(keyword_list: Vec<String>) -> Self {
        let tag_list_items = keyword_list;
        let tag_list_state = ListState::default(); // for preselection: .with_selected(Some(0));
        let tag_scroll_state = ScrollbarState::new(tag_list_items.len());
        Self {
            tag_list_items,
            tag_list_at_search_start: Vec::new(),
            tag_list_state,
            tag_scroll_state,
            selected_keywords: Vec::new(),
            search_string: String::new(), // tag_list_search: BibiSearch::default(),
        }
    }

    pub fn search_tag_list(search_pattern: &str, orig_list: Vec<String>) -> Vec<String> {
        // Set up matcher (TODO: One time needed only)
        let mut matcher = Matcher::new(Config::DEFAULT);

        // Filter the list items by search pattern
        let filtered_matches: Vec<String> = {
            let matches =
                Pattern::parse(search_pattern, CaseMatching::Ignore, Normalization::Smart)
                    .match_list(orig_list, &mut matcher);
            matches.into_iter().map(|f| f.0.to_string()).collect()
        };
        filtered_matches
    }

    pub(crate) fn search_string(&self) -> &str {
        &self.search_string
    }

    pub(crate) fn set_search_string<S: ToString>(&mut self, value: S) {
        self.search_string = value.to_string();
    }
}
