use async_trait::async_trait;
use serde_json::Value;

use crate::filetree::FileTree;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SortOption {
    pub key: String,
    pub label: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct FilterOption {
    pub key: String,
    pub label: String,
}

#[async_trait]
pub trait DisplayMode: Send + Sync {
    fn name(&self) -> &'static str;
    fn render(&self, tree: &FileTree) -> Value;
    fn sort_options(&self) -> Vec<SortOption>;
    fn filter_options(&self) -> Vec<FilterOption>;
}

pub fn get_mode(name: &str) -> Option<Box<dyn DisplayMode>> {
    match name {
        "tree" => Some(Box::new(crate::filetree::modes::tree::TreeMode)),
        "list" => Some(Box::new(crate::filetree::modes::list::ListMode)),
        "grid_sm" => Some(Box::new(crate::filetree::modes::grid_sm::GridSmMode)),
        "grid_lg" => Some(Box::new(crate::filetree::modes::grid_lg::GridLgMode)),
        _ => None,
    }
}

pub fn list_modes() -> Vec<Box<dyn DisplayMode>> {
    vec![
        Box::new(crate::filetree::modes::list::ListMode),
        Box::new(crate::filetree::modes::tree::TreeMode),
        Box::new(crate::filetree::modes::grid_sm::GridSmMode),
        Box::new(crate::filetree::modes::grid_lg::GridLgMode),
    ]
}
