use crate::todo::{ToDoCategory, ToDoData};
use anyhow::{anyhow, Error};
use clap::ValueEnum;
use core::fmt;
use serde::{Deserialize, Serialize};
use std::str::FromStr;

/// An enumeration representing different types of widgets used in the application.
/// Widgets are I components with specific functionalities, such as task lists, project lists, and previews.
#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, Serialize, Deserialize, ValueEnum)]
pub enum WidgetType {
    #[default]
    List,
    Done,
    Project,
    Context,
    Hashtag,
    Preview,
    PendingLivePreview,
    DoneLivePreview,
}

impl fmt::Display for WidgetType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", format!("{self:?}").to_lowercase())
    }
}

impl From<ToDoCategory> for WidgetType {
    fn from(value: ToDoCategory) -> Self {
        use ToDoCategory::*;
        match value {
            Projects => WidgetType::Project,
            Contexts => WidgetType::Context,
            Hashtags => WidgetType::Hashtag,
        }
    }
}

impl From<ToDoData> for WidgetType {
    fn from(value: ToDoData) -> Self {
        use ToDoData::*;
        match value {
            Pending => WidgetType::List,
            Done => WidgetType::Done,
        }
    }
}

impl FromStr for WidgetType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use WidgetType::*;
        Ok(match s.to_lowercase().as_str() {
            "list" => List,
            "done" => Done,
            "projects" => Project,
            "contexts" => Context,
            "hashtags" => Hashtag,
            "preview" => Preview,
            "live-preview-pending" => PendingLivePreview,
            "live-preview-done" => DoneLivePreview,
            _ => return Err(anyhow!("Unknown widget type: {s}")),
        })
    }
}
