// NOTE: Do not edit this file manually, it is generated by error_code_message_map.util.ts
use strum_macros::{Display, EnumString};

use crate::util::position::Position;

#[derive(Debug, Display, PartialEq, EnumString)]
pub enum ErrorCode {
    #[strum(serialize = "SMIK-1")]
    /**
     * en: SectionMetaInfoKey is invalid
     * ja: セクションメタ情報のキーが不正です
     */
    Smik1,

    #[strum(serialize = "SMIK-2")]
    /**
     * en: SectionMetaInfoKey should not contains line break
     * ja: セクションメタ情報のキーに改行を含めることはできません
     */
    Smik2,

    #[strum(serialize = "SMIV-1")]
    /**
     * en: SectionMetaInfoValue should not be empty
     * ja: セクションメタ情報の値は空にできません
     */
    Smiv1,

    #[strum(serialize = "SMIV-2")]
    /**
     * en: SectionMetaInfoValue needs line break after
     * ja: セクションメタ情報の値の後に改行が必要です
     */
    Smiv2,

    #[strum(serialize = "SMIV-3")]
    /**
     * en: SectionMetaInfoValue of repeat needs to be number
     * ja: セクションメタ情報の値のrepeatの値は数値である必要があります
     */
    Smiv3,

    #[strum(serialize = "CIMK-1")]
    /**
     * en: ChordInfoMetaKey should not contains line break
     * ja: コードメタ情報のキーに改行を含めることはできません
     */
    Cimk1,

    #[strum(serialize = "CIMK-2")]
    /**
     * en: MetaInfoKey should not be empty
     * ja: コードメタ情報のキーは空にできません
     */
    Cimk2,

    #[strum(serialize = "CIMK-3")]
    /**
     * en: MetaInfoKey is invalid
     * ja: コードメタ情報のキーが不正です
     */
    Cimk3,

    #[strum(serialize = "CIMV-1")]
    /**
     * en: MetaInfoValue should not contains line break
     * ja: コードメタ情報の値に改行を含めることはできません
     */
    Cimv1,

    #[strum(serialize = "CIMV-2")]
    /**
     * en: MetaInfoValue should not be empty
     * ja: コードメタ情報の値は空にできません
     */
    Cimv2,

    #[strum(serialize = "CIMV-3")]
    /**
     * en: MetaInfoValue needs close parenthesis after
     * ja: コードメタ情報の値の後に閉じ括弧が必要です
     */
    Cimv3,

    #[strum(serialize = "CIMV-4")]
    /**
     * en: MetaInfoValue is invalid
     * ja: コードメタ情報の値が不正です
     */
    Cimv4,

    #[strum(serialize = "CHB-1")]
    /**
     * en: % should not be placed first of ChordBlock
     * ja: コードブロックの先頭に%を置くことはできません
     */
    Chb1,

    #[strum(serialize = "CHB-2")]
    /**
     * en: ChordBlock should not contains line break
     * ja: コードブロックに改行を含めることはできません
     */
    Chb2,

    #[strum(serialize = "CHO-1")]
    /**
     * en: Invalid chord
     * ja: コードが不正です
     */
    Cho1,

    #[strum(serialize = "CHO-2")]
    /**
     * en: Chord should not contains line break
     * ja: コードに改行を含めることはできません
     */
    Cho2,

    #[strum(serialize = "CHO-3")]
    /**
     * en: Chord should not be empty
     * ja: コードは空にできません
     */
    Cho3,

    #[strum(serialize = "DEN-1")]
    /**
     * en: Invalid denominator
     * ja: 分母が不正です
     */
    Den1,

    #[strum(serialize = "DEN-2")]
    /**
     * en: Denominator is limited to one per chord
     * ja: コードに対して分母は1つまでです
     */
    Den2,

    #[strum(serialize = "EXT-1")]
    /**
     * en: Invalid extension
     * ja: テンションが不正です
     */
    Ext1,

    #[strum(serialize = "EXT-2")]
    /**
     * en: Extension must not be empty
     * ja: テンションは空にできません
     */
    Ext2,

    #[strum(serialize = "EXT-3")]
    /**
     * en: Extension must be surrounded by parenthesis
     * ja: テンションは括弧で囲む必要があります
     */
    Ext3,

    #[strum(serialize = "EXT-4")]
    /**
     * en: No multiple extension parenthesis
     * ja: テンションの括弧は1つまでです
     */
    Ext4,

    #[strum(serialize = "TKN-1")]
    /**
     * en: Invalid token type
     * ja: 不正なトークンタイプです
     */
    Tkn1,

    #[strum(serialize = "BS-1")]
    /**
     * en: Invalid base
     * ja: 不正なベース音です
     */
    Bs1,

    #[strum(serialize = "BL-1")]
    /**
     * en: Continuous blank lines are not allowed
     * ja: 連続した空行は許可されていません
     */
    Bl1,

    #[strum(serialize = "OTHER-1")]
    /**
     * en: Unknown error
     * ja: 不明なエラーです
     */
    Other1,
}

#[derive(Debug, PartialEq)]
pub struct ErrorInfo {
    pub code: ErrorCode,
    pub additional_info: Option<String>,
}

#[derive(Debug, PartialEq)]
pub struct ErrorInfoWithPosition {
    pub error: ErrorInfo,
    pub position: Position,
}

// implement to_string() for ErrorInfo
impl std::fmt::Display for ErrorInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let additional_info = match &self.additional_info {
            Some(info) => format!(": {}", info),
            None => "".to_string(),
        };
        write!(f, "{}{}", self.code, additional_info)
    }
}
