use serde::{Serialize, Deserialize};


#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
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,
}

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],
        }
    }
}

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

#[derive(Debug, Copy, Clone, PartialEq)]
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[7] = 3;
                },
                UnitModifier::Plus => {
                    result[7] = 1;
                },
                UnitModifier::Minus => {
                    result[7] = 0xFF;
                    result[8] = 0xFF;
                },
                UnitModifier::MinusMinus => {
                    result[7] = 0xFE;
                    result[8] = 0xFF;
                },
            }
        }

        result
    }
}