use serde::{Serialize, Deserialize};

#[derive(Debug, Copy, Clone)]
pub enum ItemParseError {
    InvalidUnitBytes,
    InvalidUnitType,
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
pub enum UnitType {
    KnightPower,
    GeneralPower,
    OgrePower,
    GodPower,
    PriestMind,
    GeneralMind,
    AngelMind,
    GodMind,
    MarksmanArm,
    GeneralArm,
    ElfArm,
    GodArm,
    ThiefLegs,
    GeneralLegs,
    ElfLegs,
    GodLegs,
    DiggerHp,
    GeneralHp,
    DragonHp,
    GodHp,
    MagicianTp,
    GeneralTp,
    AngelTp,
    GodTp,
    WarriorBody,
    GeneralBody,
    MetalBody,
    GodBody,
    AngelLuck,
    GodLuck,
    MasterAbility,
    HeroAbility,
    GodAbility,
    ResistFire,
    ResistFlame,
    ResistBurning,
    ResistCold,
    ResistFreeze,
    ResistBlizzard,
    ResistShock,
    ResistThunder,
    ResistStorm,
    ResistLight,
    ResistSaint,
    ResistHoly,
    ResistDark,
    ResistEvil,
    ResistDevil,
    AllResist,
    SuperResist,
    PerfectResist,
    HpRestorate,
    HpGenerate,
    HpRevival,
    TpRestorate,
    TpGenerate,
    TpRevival,
    PbAmplifier,
    PbGenerate,
    PbCreate,
    WizardTechnique,
    DevilTechnique,
    GodTechnique,
    GeneralBattle,
    DevilBattle,
    GodBattle,
    CurePoison,
    CureParalysis,
    CureSlow,
    CureConfuse,
    CureFreeze,
    CureShock,
    YasakaniMagatama,
    V101,
    V501,
    V502,
    V801,
    Limiter,
    Adept,
    SwordsmanLore,
    ProofOfSwordSaint,
    Smartlink,
    DivineProtection,
    HeavenlyBattle,
    HeavenlyPower,
    HeavenlyMind,
    HeavenlyArms,
    HeavenlyLegs,
    HeavenlyBody,
    HeavenlyLuck,
    HeavenlyAbility,
    CenturionAbility,
    FriendRing,
    HeavenlyHp,
    HeavenlyTp,
    HeavenlyResist,
    HeavenlyTechnique,
    HpRessurection,
    TpRessurection,
    PbIncrease,
}

impl UnitType {
    pub fn value(&self) -> [u8; 3] {
        match self {
            UnitType::KnightPower => [0x01, 0x03, 0x00],
            UnitType::GeneralPower => [0x01, 0x03, 0x01],
            UnitType::OgrePower => [0x01, 0x03, 0x02],
            UnitType::GodPower => [0x01, 0x03, 0x03],
            UnitType::PriestMind => [0x01, 0x03, 0x04],
            UnitType::GeneralMind => [0x01, 0x03, 0x05],
            UnitType::AngelMind => [0x01, 0x03, 0x06],
            UnitType::GodMind => [0x01, 0x03, 0x07],
            UnitType::MarksmanArm => [0x01, 0x03, 0x08],
            UnitType::GeneralArm => [0x01, 0x03, 0x09],
            UnitType::ElfArm => [0x01, 0x03, 0x0A],
            UnitType::GodArm => [0x01, 0x03, 0x0B],
            UnitType::ThiefLegs => [0x01, 0x03, 0x0C],
            UnitType::GeneralLegs => [0x01, 0x03, 0x0D],
            UnitType::ElfLegs => [0x01, 0x03, 0x0E],
            UnitType::GodLegs => [0x01, 0x03, 0x0F],
            UnitType::DiggerHp => [0x01, 0x03, 0x10],
            UnitType::GeneralHp => [0x01, 0x03, 0x11],
            UnitType::DragonHp => [0x01, 0x03, 0x12],
            UnitType::GodHp => [0x01, 0x03, 0x13],
            UnitType::MagicianTp => [0x01, 0x03, 0x14],
            UnitType::GeneralTp => [0x01, 0x03, 0x15],
            UnitType::AngelTp => [0x01, 0x03, 0x16],
            UnitType::GodTp => [0x01, 0x03, 0x17],
            UnitType::WarriorBody => [0x01, 0x03, 0x18],
            UnitType::GeneralBody => [0x01, 0x03, 0x19],
            UnitType::MetalBody => [0x01, 0x03, 0x1A],
            UnitType::GodBody => [0x01, 0x03, 0x1B],
            UnitType::AngelLuck => [0x01, 0x03, 0x1C],
            UnitType::GodLuck => [0x01, 0x03, 0x1D],
            UnitType::MasterAbility => [0x01, 0x03, 0x1E],
            UnitType::HeroAbility => [0x01, 0x03, 0x1F],
            UnitType::GodAbility => [0x01, 0x03, 0x20],
            UnitType::ResistFire => [0x01, 0x03, 0x21],
            UnitType::ResistFlame => [0x01, 0x03, 0x22],
            UnitType::ResistBurning => [0x01, 0x03, 0x23],
            UnitType::ResistCold => [0x01, 0x03, 0x24],
            UnitType::ResistFreeze => [0x01, 0x03, 0x25],
            UnitType::ResistBlizzard => [0x01, 0x03, 0x26],
            UnitType::ResistShock => [0x01, 0x03, 0x27],
            UnitType::ResistThunder => [0x01, 0x03, 0x28],
            UnitType::ResistStorm => [0x01, 0x03, 0x29],
            UnitType::ResistLight => [0x01, 0x03, 0x2A],
            UnitType::ResistSaint => [0x01, 0x03, 0x2B],
            UnitType::ResistHoly => [0x01, 0x03, 0x2C],
            UnitType::ResistDark => [0x01, 0x03, 0x2D],
            UnitType::ResistEvil => [0x01, 0x03, 0x2E],
            UnitType::ResistDevil => [0x01, 0x03, 0x2F],
            UnitType::AllResist => [0x01, 0x03, 0x30],
            UnitType::SuperResist => [0x01, 0x03, 0x31],
            UnitType::PerfectResist => [0x01, 0x03, 0x32],
            UnitType::HpRestorate => [0x01, 0x03, 0x33],
            UnitType::HpGenerate => [0x01, 0x03, 0x34],
            UnitType::HpRevival => [0x01, 0x03, 0x35],
            UnitType::TpRestorate => [0x01, 0x03, 0x36],
            UnitType::TpGenerate => [0x01, 0x03, 0x37],
            UnitType::TpRevival => [0x01, 0x03, 0x38],
            UnitType::PbAmplifier => [0x01, 0x03, 0x39],
            UnitType::PbGenerate => [0x01, 0x03, 0x3A],
            UnitType::PbCreate => [0x01, 0x03, 0x3B],
            UnitType::WizardTechnique => [0x01, 0x03, 0x3C],
            UnitType::DevilTechnique => [0x01, 0x03, 0x3D],
            UnitType::GodTechnique => [0x01, 0x03, 0x3E],
            UnitType::GeneralBattle => [0x01, 0x03, 0x3F],
            UnitType::DevilBattle => [0x01, 0x03, 0x40],
            UnitType::GodBattle => [0x01, 0x03, 0x41],
            UnitType::CurePoison => [0x01, 0x03, 0x42],
            UnitType::CureParalysis => [0x01, 0x03, 0x43],
            UnitType::CureSlow => [0x01, 0x03, 0x44],
            UnitType::CureConfuse => [0x01, 0x03, 0x45],
            UnitType::CureFreeze => [0x01, 0x03, 0x46],
            UnitType::CureShock => [0x01, 0x03, 0x47],
            UnitType::YasakaniMagatama => [0x01, 0x03, 0x48],
            UnitType::V101 => [0x01, 0x03, 0x49],
            UnitType::V501 => [0x01, 0x03, 0x4A],
            UnitType::V502 => [0x01, 0x03, 0x4B],
            UnitType::V801 => [0x01, 0x03, 0x4C],
            UnitType::Limiter => [0x01, 0x03, 0x4D],
            UnitType::Adept => [0x01, 0x03, 0x4E],
            UnitType::SwordsmanLore => [0x01, 0x03, 0x4F],
            UnitType::ProofOfSwordSaint => [0x01, 0x03, 0x50],
            UnitType::Smartlink => [0x01, 0x03, 0x51],
            UnitType::DivineProtection => [0x01, 0x03, 0x52],
            UnitType::HeavenlyBattle => [0x01, 0x03, 0x53],
            UnitType::HeavenlyPower => [0x01, 0x03, 0x54],
            UnitType::HeavenlyMind => [0x01, 0x03, 0x55],
            UnitType::HeavenlyArms => [0x01, 0x03, 0x56],
            UnitType::HeavenlyLegs => [0x01, 0x03, 0x57],
            UnitType::HeavenlyBody => [0x01, 0x03, 0x58],
            UnitType::HeavenlyLuck => [0x01, 0x03, 0x59],
            UnitType::HeavenlyAbility => [0x01, 0x03, 0x5A],
            UnitType::CenturionAbility => [0x01, 0x03, 0x5B],
            UnitType::FriendRing => [0x01, 0x03, 0x5C],
            UnitType::HeavenlyHp => [0x01, 0x03, 0x5D],
            UnitType::HeavenlyTp => [0x01, 0x03, 0x5E],
            UnitType::HeavenlyResist => [0x01, 0x03, 0x5F],
            UnitType::HeavenlyTechnique => [0x01, 0x03, 0x60],
            UnitType::HpRessurection => [0x01, 0x03, 0x61],
            UnitType::TpRessurection => [0x01, 0x03, 0x62],
            UnitType::PbIncrease => [0x01, 0x03, 0x63],
        }
    }

    pub fn parse_type(data: [u8; 3]) -> Result<UnitType, ItemParseError> {
        match data {
            [0x01, 0x03, 0x00] => Ok(UnitType::KnightPower),
            [0x01, 0x03, 0x01] => Ok(UnitType::GeneralPower),
            [0x01, 0x03, 0x02] => Ok(UnitType::OgrePower),
            [0x01, 0x03, 0x03] => Ok(UnitType::GodPower),
            [0x01, 0x03, 0x04] => Ok(UnitType::PriestMind),
            [0x01, 0x03, 0x05] => Ok(UnitType::GeneralMind),
            [0x01, 0x03, 0x06] => Ok(UnitType::AngelMind),
            [0x01, 0x03, 0x07] => Ok(UnitType::GodMind),
            [0x01, 0x03, 0x08] => Ok(UnitType::MarksmanArm),
            [0x01, 0x03, 0x09] => Ok(UnitType::GeneralArm),
            [0x01, 0x03, 0x0A] => Ok(UnitType::ElfArm),
            [0x01, 0x03, 0x0B] => Ok(UnitType::GodArm),
            [0x01, 0x03, 0x0C] => Ok(UnitType::ThiefLegs),
            [0x01, 0x03, 0x0D] => Ok(UnitType::GeneralLegs),
            [0x01, 0x03, 0x0E] => Ok(UnitType::ElfLegs),
            [0x01, 0x03, 0x0F] => Ok(UnitType::GodLegs),
            [0x01, 0x03, 0x10] => Ok(UnitType::DiggerHp),
            [0x01, 0x03, 0x11] => Ok(UnitType::GeneralHp),
            [0x01, 0x03, 0x12] => Ok(UnitType::DragonHp),
            [0x01, 0x03, 0x13] => Ok(UnitType::GodHp),
            [0x01, 0x03, 0x14] => Ok(UnitType::MagicianTp),
            [0x01, 0x03, 0x15] => Ok(UnitType::GeneralTp),
            [0x01, 0x03, 0x16] => Ok(UnitType::AngelTp),
            [0x01, 0x03, 0x17] => Ok(UnitType::GodTp),
            [0x01, 0x03, 0x18] => Ok(UnitType::WarriorBody),
            [0x01, 0x03, 0x19] => Ok(UnitType::GeneralBody),
            [0x01, 0x03, 0x1A] => Ok(UnitType::MetalBody),
            [0x01, 0x03, 0x1B] => Ok(UnitType::GodBody),
            [0x01, 0x03, 0x1C] => Ok(UnitType::AngelLuck),
            [0x01, 0x03, 0x1D] => Ok(UnitType::GodLuck),
            [0x01, 0x03, 0x1E] => Ok(UnitType::MasterAbility),
            [0x01, 0x03, 0x1F] => Ok(UnitType::HeroAbility),
            [0x01, 0x03, 0x20] => Ok(UnitType::GodAbility),
            [0x01, 0x03, 0x21] => Ok(UnitType::ResistFire),
            [0x01, 0x03, 0x22] => Ok(UnitType::ResistFlame),
            [0x01, 0x03, 0x23] => Ok(UnitType::ResistBurning),
            [0x01, 0x03, 0x24] => Ok(UnitType::ResistCold),
            [0x01, 0x03, 0x25] => Ok(UnitType::ResistFreeze),
            [0x01, 0x03, 0x26] => Ok(UnitType::ResistBlizzard),
            [0x01, 0x03, 0x27] => Ok(UnitType::ResistShock),
            [0x01, 0x03, 0x28] => Ok(UnitType::ResistThunder),
            [0x01, 0x03, 0x29] => Ok(UnitType::ResistStorm),
            [0x01, 0x03, 0x2A] => Ok(UnitType::ResistLight),
            [0x01, 0x03, 0x2B] => Ok(UnitType::ResistSaint),
            [0x01, 0x03, 0x2C] => Ok(UnitType::ResistHoly),
            [0x01, 0x03, 0x2D] => Ok(UnitType::ResistDark),
            [0x01, 0x03, 0x2E] => Ok(UnitType::ResistEvil),
            [0x01, 0x03, 0x2F] => Ok(UnitType::ResistDevil),
            [0x01, 0x03, 0x30] => Ok(UnitType::AllResist),
            [0x01, 0x03, 0x31] => Ok(UnitType::SuperResist),
            [0x01, 0x03, 0x32] => Ok(UnitType::PerfectResist),
            [0x01, 0x03, 0x33] => Ok(UnitType::HpRestorate),
            [0x01, 0x03, 0x34] => Ok(UnitType::HpGenerate),
            [0x01, 0x03, 0x35] => Ok(UnitType::HpRevival),
            [0x01, 0x03, 0x36] => Ok(UnitType::TpRestorate),
            [0x01, 0x03, 0x37] => Ok(UnitType::TpGenerate),
            [0x01, 0x03, 0x38] => Ok(UnitType::TpRevival),
            [0x01, 0x03, 0x39] => Ok(UnitType::PbAmplifier),
            [0x01, 0x03, 0x3A] => Ok(UnitType::PbGenerate),
            [0x01, 0x03, 0x3B] => Ok(UnitType::PbCreate),
            [0x01, 0x03, 0x3C] => Ok(UnitType::WizardTechnique),
            [0x01, 0x03, 0x3D] => Ok(UnitType::DevilTechnique),
            [0x01, 0x03, 0x3E] => Ok(UnitType::GodTechnique),
            [0x01, 0x03, 0x3F] => Ok(UnitType::GeneralBattle),
            [0x01, 0x03, 0x40] => Ok(UnitType::DevilBattle),
            [0x01, 0x03, 0x41] => Ok(UnitType::GodBattle),
            [0x01, 0x03, 0x42] => Ok(UnitType::CurePoison),
            [0x01, 0x03, 0x43] => Ok(UnitType::CureParalysis),
            [0x01, 0x03, 0x44] => Ok(UnitType::CureSlow),
            [0x01, 0x03, 0x45] => Ok(UnitType::CureConfuse),
            [0x01, 0x03, 0x46] => Ok(UnitType::CureFreeze),
            [0x01, 0x03, 0x47] => Ok(UnitType::CureShock),
            [0x01, 0x03, 0x48] => Ok(UnitType::YasakaniMagatama),
            [0x01, 0x03, 0x49] => Ok(UnitType::V101),
            [0x01, 0x03, 0x4A] => Ok(UnitType::V501),
            [0x01, 0x03, 0x4B] => Ok(UnitType::V502),
            [0x01, 0x03, 0x4C] => Ok(UnitType::V801),
            [0x01, 0x03, 0x4D] => Ok(UnitType::Limiter),
            [0x01, 0x03, 0x4E] => Ok(UnitType::Adept),
            [0x01, 0x03, 0x4F] => Ok(UnitType::SwordsmanLore),
            [0x01, 0x03, 0x50] => Ok(UnitType::ProofOfSwordSaint),
            [0x01, 0x03, 0x51] => Ok(UnitType::Smartlink),
            [0x01, 0x03, 0x52] => Ok(UnitType::DivineProtection),
            [0x01, 0x03, 0x53] => Ok(UnitType::HeavenlyBattle),
            [0x01, 0x03, 0x54] => Ok(UnitType::HeavenlyPower),
            [0x01, 0x03, 0x55] => Ok(UnitType::HeavenlyMind),
            [0x01, 0x03, 0x56] => Ok(UnitType::HeavenlyArms),
            [0x01, 0x03, 0x57] => Ok(UnitType::HeavenlyLegs),
            [0x01, 0x03, 0x58] => Ok(UnitType::HeavenlyBody),
            [0x01, 0x03, 0x59] => Ok(UnitType::HeavenlyLuck),
            [0x01, 0x03, 0x5A] => Ok(UnitType::HeavenlyAbility),
            [0x01, 0x03, 0x5B] => Ok(UnitType::CenturionAbility),
            [0x01, 0x03, 0x5C] => Ok(UnitType::FriendRing),
            [0x01, 0x03, 0x5D] => Ok(UnitType::HeavenlyHp),
            [0x01, 0x03, 0x5E] => Ok(UnitType::HeavenlyTp),
            [0x01, 0x03, 0x5F] => Ok(UnitType::HeavenlyResist),
            [0x01, 0x03, 0x60] => Ok(UnitType::HeavenlyTechnique),
            [0x01, 0x03, 0x61] => Ok(UnitType::HpRessurection),
            [0x01, 0x03, 0x62] => Ok(UnitType::TpRessurection),
            [0x01, 0x03, 0x63] => Ok(UnitType::PbIncrease),
            _ => Err(ItemParseError::InvalidUnitType),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum UnitModifier {
    PlusPlus,
    Plus,
    Minus,
    MinusMinus,
}

#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub struct Unit {
    pub unit: UnitType,
    pub modifier: Option<UnitModifier>,
}


impl Unit {
    pub fn as_bytes(&self) -> [u8; 16] {
        let mut result = [0; 16];
        result[0..3].copy_from_slice(&self.unit.value());

        if let Some(modifier) = self.modifier {
            match modifier {
                UnitModifier::PlusPlus => {
                    result[6] = 2;
                },
                UnitModifier::Plus => {
                    result[6] = 1;
                },
                UnitModifier::Minus => {
                    result[6] = 0xFF;
                    result[7] = 0xFF;
                },
                UnitModifier::MinusMinus => {
                    result[6] = 0xFE;
                    result[7] = 0xFF;
                },
            }
        }
        result
    }

    pub fn from_bytes(data: [u8; 16]) -> Result<Unit, ItemParseError> {
        let u = UnitType::parse_type([data[0], data[1], data[2]]); 
        if let Ok(u) = u {
            let m = match u16::from_le_bytes([data[6], data[7]]) {
                0x02 => Some(UnitModifier::PlusPlus),
                0x01 => Some(UnitModifier::Plus),
                0xFEFF => Some(UnitModifier::Minus),
                0xFFFF => Some(UnitModifier::MinusMinus),
                _ => None,
            };

            Ok(Unit{
                unit: u,
                modifier: m,
            })
        }
        else {
            Err(ItemParseError::InvalidUnitBytes) // TODO: error handling if wrong bytes are given
        }
    }

    pub fn is_rare_item(self) -> bool {
        matches!(self.unit, UnitType::GodPower | UnitType::GodMind | UnitType::GodArm | UnitType::GodLegs | UnitType::GodHp | UnitType::GodTp | UnitType::GodBody | UnitType::GodLuck | UnitType::HeroAbility | UnitType::GodAbility | UnitType::AllResist | UnitType::SuperResist | UnitType::PerfectResist | UnitType::HpRevival | UnitType::TpRevival | UnitType::PbAmplifier | UnitType::PbGenerate | UnitType::PbCreate | UnitType::DevilTechnique | UnitType::GodTechnique | UnitType::DevilBattle | UnitType::GodBattle | UnitType::CurePoison | UnitType::CureParalysis | UnitType::CureSlow | UnitType::CureConfuse | UnitType::CureFreeze | UnitType::CureShock | UnitType::YasakaniMagatama | UnitType::V101 | UnitType::V501 | UnitType::V502 | UnitType::V801 | UnitType::Limiter | UnitType::Adept | UnitType::SwordsmanLore | UnitType::ProofOfSwordSaint | UnitType::Smartlink | UnitType::DivineProtection | UnitType::HeavenlyBattle | UnitType::HeavenlyPower | UnitType::HeavenlyMind | UnitType::HeavenlyArms | UnitType::HeavenlyLegs | UnitType::HeavenlyBody | UnitType::HeavenlyLuck | UnitType::HeavenlyAbility | UnitType::CenturionAbility | UnitType::FriendRing | UnitType::HeavenlyHp | UnitType::HeavenlyTp | UnitType::HeavenlyResist | UnitType::HeavenlyTechnique | UnitType::HpRessurection | UnitType::TpRessurection | UnitType::PbIncrease)
    }
}