use serde::{Deserialize, Serialize};

#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum OutFormat {
  Json,
  Jsonl,
  #[default]
  Text,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)]
#[error("invalid out format: possible values are `json`, `jsonl`, `text`")]
pub struct InvalidOutFormat;

impl OutFormat {
  pub fn as_str(&self) -> &'static str {
    match &self {
      Self::Json => "json",
      Self::Jsonl => "jsonl",
      Self::Text => "text",
    }
  }

  pub fn parse(s: &str) -> Result<Self, InvalidOutFormat> {
    match s {
      "json" => Ok(Self::Json),
      "jsonl" => Ok(Self::Jsonl),
      "text" => Ok(Self::Text),
      _ => Err(InvalidOutFormat),
    }
  }
}

impl core::str::FromStr for OutFormat {
  type Err = InvalidOutFormat;

  fn from_str(s: &str) -> Result<Self, Self::Err> {
    Self::parse(s)
  }
}

impl clap::ValueEnum for OutFormat {
  fn value_variants<'a>() -> &'a [Self] {
    &[Self::Json, Self::Jsonl, Self::Text]
  }

  fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
    Some(clap::builder::PossibleValue::new(self.as_str()))
  }
}
