use cryp::{Stat, Colours};
use util::{IntPct};

#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)]
pub enum Spec {
    Speed,
    RedSpeedI,
    BlueSpeedI,
    GreenSpeedI,
    GRSpeedI,
    GBSpeedI,
    RBSpeedI,
    // Pure redLife has to come first as it applies the base amount
    // that is multiplied
    Life,
    GreenLifeI,
    RedLifeI,
    BlueLifeI,
    GRLI,
    GBLI,
    RBLI,

    Damage,
    RedDamageI,
    GreenDamageI,
    BlueDamageI,
    GRDI,
    GBDI,
    RBDI,
}

impl Spec {
    pub fn affects(&self) -> Vec<Stat> {
        match *self {
            Spec::Damage        => vec![Stat::BlueDamage, Stat::RedDamage, Stat::GreenDamage],
            Spec::RedDamageI    => vec![Stat::RedDamage],
            Spec::GreenDamageI  => vec![Stat::GreenDamage],
            Spec::BlueDamageI   => vec![Stat::BlueDamage],
            Spec::GRDI          => vec![Stat::GreenDamage, Stat::RedDamage],
            Spec::GBDI          => vec![Stat::GreenDamage, Stat::BlueDamage],
            Spec::RBDI          => vec![Stat::RedDamage, Stat::BlueDamage],

            Spec::Speed         => vec![Stat::Speed],
            Spec::RedSpeedI     => vec![Stat::Speed],
            Spec::BlueSpeedI    => vec![Stat::Speed],
            Spec::GreenSpeedI   => vec![Stat::Speed],
            Spec::GRSpeedI      => vec![Stat::Speed],
            Spec::GBSpeedI      => vec![Stat::Speed],
            Spec::RBSpeedI      => vec![Stat::Speed],

            Spec::Life          => vec![Stat::GreenLife],
            Spec::RedLifeI      => vec![Stat::RedLife],
            Spec::BlueLifeI     => vec![Stat::BlueLife],
            Spec::GreenLifeI    => vec![Stat::GreenLife],
            Spec::GRLI          => vec![Stat::GreenLife, Stat::RedLife],
            Spec::GBLI          => vec![Stat::GreenLife, Stat::BlueLife],
            Spec::RBLI          => vec![Stat::BlueLife, Stat::RedLife],

        }
    }

    pub fn apply(&self, modified: u64, base: u64, player_colours: &Colours) -> u64 {
        match *self {
            // Upgrades to Damage Spec
            Spec::Damage            => modified + base.pct(5),
            Spec::RedDamageI        => modified + {
                let mut pct = 10;
                if player_colours.red >= 5  { pct += 10 };
                if player_colours.red >= 10 { pct += 20 };
                if player_colours.red >= 20 { pct += 40 };
                base.pct(pct)
            },
            Spec::GreenDamageI        => modified + {
                let mut pct = 10;
                if player_colours.green >= 5  { pct += 10 };
                if player_colours.green >= 10 { pct += 20 };
                if player_colours.green >= 20 { pct += 40 };
                base.pct(pct)
            },
            Spec::BlueDamageI        => modified + {
                let mut pct = 10;
                if player_colours.blue >= 5  { pct += 10 };
                if player_colours.blue >= 10 { pct += 20 };
                if player_colours.blue >= 20 { pct += 40 };
                base.pct(pct)
            },
            Spec::GRDI              => modified + {
                let mut pct = 5;
                if player_colours.green >= 2 && player_colours.red >= 2 { pct += 10 };
                if player_colours.green >= 5 && player_colours.red >= 5 { pct += 15 };
                if player_colours.green >= 10 && player_colours.red >= 10 { pct += 30 };
                base.pct(pct)
            },
            Spec::GBDI              => modified + {
                let mut pct = 5;
                if player_colours.green >= 2 && player_colours.blue >= 2 { pct += 10 };
                if player_colours.green >= 5 && player_colours.blue >= 5 { pct += 15 };
                if player_colours.green >= 10 && player_colours.blue >= 10 { pct += 30 };
                base.pct(pct)
            },
            Spec::RBDI              => modified + {
                let mut pct = 5;
                if player_colours.blue >= 2 && player_colours.red >= 2 { pct += 10 };
                if player_colours.blue >= 5 && player_colours.red >= 5 { pct += 15 };
                if player_colours.blue >= 10 && player_colours.red >= 10 { pct += 30 };
                base.pct(pct)
            },
            // Upgrades to speed Spec
            Spec::Speed            => modified + base.pct(5),
            Spec::RedSpeedI        => modified + {
                let mut pct = 5;
                if player_colours.red >= 5  { pct += 5 };
                if player_colours.red >= 10 { pct += 10 };
                if player_colours.red >= 20 { pct += 20 };
                base.pct(pct)
            },
            Spec::GreenSpeedI        => modified + {
                let mut pct = 5;
                if player_colours.green >= 5  { pct += 5 };
                if player_colours.green >= 10 { pct += 10 };
                if player_colours.green >= 20 { pct += 20 };
                base.pct(pct)
            },
            Spec::BlueSpeedI        => modified + {
                let mut pct = 5;
                if player_colours.blue >= 5  { pct += 5 };
                if player_colours.blue >= 10 { pct += 10 };
                if player_colours.blue >= 20 { pct += 20 };
                base.pct(pct)
            },
            Spec::GRSpeedI              => modified + {
                let mut pct = 5;
                if player_colours.green >= 2 && player_colours.red >= 2 { pct += 5 };
                if player_colours.green >= 5 && player_colours.red >= 5 { pct += 10 };
                if player_colours.green >= 10 && player_colours.red >= 10 { pct += 20 };
                base.pct(pct)
            },
            Spec::GBSpeedI              => modified + {
                let mut pct = 5;
                if player_colours.green >= 2 && player_colours.blue >= 2 { pct += 5 };
                if player_colours.green >= 5 && player_colours.blue >= 5 { pct += 10 };
                if player_colours.green >= 10 && player_colours.blue >= 10 { pct += 20 };
                base.pct(pct)
            },
            Spec::RBSpeedI              => modified + {
                let mut pct = 5;
                if player_colours.blue >= 2 && player_colours.red >= 2 { pct += 5 };
                if player_colours.blue >= 5 && player_colours.red >= 5 { pct += 10 };
                if player_colours.blue >= 10 && player_colours.red >= 10 { pct += 20 };
                base.pct(pct)
            },

            // Upgrades to HP Spec
            Spec::Life                  => modified + base.pct(5),
            Spec::GreenLifeI            => modified + {
                let mut mult: u64 = 15;
                if player_colours.green >= 5  { mult += 25 };
                if player_colours.green >= 10  { mult += 50 };
                if player_colours.green >= 20  { mult += 75 };
                mult * player_colours.green as u64
            },
            Spec::RedLifeI        => modified + {
                let mut mult: u64 = 15;
                if player_colours.red >= 5  { mult += 25 };
                if player_colours.red >= 10  { mult += 50 };
                if player_colours.red >= 20  { mult += 75 };
                mult * player_colours.red as u64
            },
            Spec::BlueLifeI       => modified + {
                let mut mult: u64 = 15;
                if player_colours.blue >= 5  { mult += 25 };
                if player_colours.blue >= 10  { mult += 50 };
                if player_colours.blue >= 20  { mult += 75 };
                mult * player_colours.blue as u64
            },
            Spec::GRLI              => modified + {
                let mut mult: u64 = 10;
                if player_colours.green >= 2 && player_colours.red >= 2 { mult += 10 };
                if player_colours.green >= 5 && player_colours.red >= 5 { mult += 25 };
                if player_colours.green >= 10 && player_colours.red >= 10 { mult += 50 };
                mult * (player_colours.green + player_colours.red) as u64
            },
            Spec::GBLI              => modified + {
                let mut mult: u64 = 10;
                if player_colours.green >= 2 && player_colours.red >= 2 { mult += 10 };
                if player_colours.green >= 5 && player_colours.red >= 5 { mult += 25 };
                if player_colours.green >= 10 && player_colours.red >= 10 { mult += 50 };
                mult * (player_colours.green + player_colours.red) as u64
            },
            Spec::RBLI              => modified + {
                let mut mult: u64 = 10;
                if player_colours.blue >= 2 && player_colours.red >= 2 { mult += 10 };
                if player_colours.blue >= 5 && player_colours.red >= 5 { mult += 25 };
                if player_colours.blue >= 10 && player_colours.red >= 10 { mult += 50 };
                mult * (player_colours.blue + player_colours.red) as u64
            },
        }
    }
}
