use std::path::{Path, PathBuf};

use gtk::{gio, prelude::*};

use crate::config;

#[derive(Debug, Clone)]
pub struct RecentManager {
    pub model: gtk::StringList,
    settings: gio::Settings,
}

impl RecentManager {
    fn init(&self) {
        let history = self.history();
        for item in history {
            self.model.append(item.to_str().unwrap());
        }
    }

    pub fn history(&self) -> Vec<PathBuf> {
        // As gtk-rs doesn't have bindings for array gvariants
        // we will store the history in gsettings as a comma sperated string instead
        // Hopefully we can ditch this in the future.
        let recent_files = self.settings.string("recent-files");

        recent_files
            .split(';')
            .map(|file| Path::new(file).to_path_buf())
            .filter(|path| path.exists())
            .collect::<Vec<PathBuf>>()
    }

    pub fn store(&self, history: Vec<PathBuf>) {
        let recent_files = history
            .iter()
            .map(|path| path.to_str().unwrap())
            .collect::<Vec<&str>>()
            .join(";");

        self.settings
            .set_string("recent-files", &recent_files)
            .unwrap();
    }

    fn index(&self, item: &Path) -> Option<u32> {
        for i in 0..self.model.n_items() {
            let path = self.model.string(i).unwrap();
            if path == item.to_str().unwrap() {
                return Some(i);
            }
        }
        None
    }

    pub fn add(&self, item: PathBuf) {
        if item.exists() {
            let mut history = self.history();

            if history.contains(&item) {
                history.retain(|p| p != &item); // Delete the old elements
            }

            if let Some(index) = self.index(&item) {
                self.model.remove(index);
            }
            history.push(item.clone());
            self.model.append(item.to_str().unwrap());

            self.store(history);
        }
    }
}

impl Default for RecentManager {
    fn default() -> Self {
        let model = gtk::StringList::new(&[]);
        let settings = gio::Settings::new(config::APP_ID);
        let recents_manager = Self { model, settings };

        recents_manager.init();
        recents_manager
    }
}
