1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::{
    constants::{PowerCreepClass, PowerType, ReturnCode},
    objects::{
        AccountPowerCreep, PowerCreep, RoomObjectProperties, StructureController,
        StructurePowerSpawn, StructureProperties,
    },
    traits::TryInto,
};

impl PowerCreep {
    pub fn create(name: &str, class: PowerCreepClass) -> ReturnCode {
        js_unwrap!(PowerCreep.create(@{name}, __power_creep_class_num_to_str(@{class as u32})))
    }

    pub fn class(&self) -> PowerCreepClass {
        js_unwrap!(__power_creep_class_str_to_num(@{self.as_ref()}.className))
    }

    pub fn power_cooldown(&self, power_type: PowerType) -> Option<u32> {
        js_unwrap!((@{self.as_ref()}.powers[@{power_type as u32}] || {}).cooldown)
    }

    pub fn power_keys(&self) -> Vec<PowerType> {
        js_unwrap!(Object.keys(@{self.as_ref()}.powers).map(Number))
    }

    pub fn power_level(&self, power_type: PowerType) -> Option<u8> {
        js_unwrap!((@{self.as_ref()}.powers[@{power_type as u32}] || {}).level)
    }

    pub fn use_power<T>(&self, power_type: PowerType, target: Option<&T>) -> ReturnCode
    where
        T: ?Sized + RoomObjectProperties,
    {
        match target {
            Some(v) => js_unwrap!(@{self.as_ref()}.usePower(@{power_type as u32}, @{v.as_ref()})),
            None => js_unwrap!(@{self.as_ref()}.usePower(@{power_type as u32})),
        }
    }

    pub fn upgrade(&self, power_type: PowerType) -> ReturnCode {
        js_unwrap!(@{self.as_ref()}.upgrade(@{power_type as u32}))
    }
}

impl AccountPowerCreep {
    pub fn class(&self) -> PowerCreepClass {
        js_unwrap!(__power_creep_class_str_to_num(@{self.as_ref()}.className))
    }

    pub fn delete(&self) -> ReturnCode {
        js_unwrap!(@{self.as_ref()}.delete())
    }

    pub fn cancel_delete(&self) -> ReturnCode {
        js_unwrap!(@{self.as_ref()}.delete(true))
    }

    pub fn power_keys(&self) -> Vec<PowerType> {
        js_unwrap!(Object.keys(@{self.as_ref()}.powers).map(Number))
    }

    pub fn power_level(&self, power_type: PowerType) -> Option<u8> {
        js_unwrap!((@{self.as_ref()}.powers[@{power_type as u32}] || {}).level)
    }

    pub fn rename(&self, new_name: &str) -> ReturnCode {
        js_unwrap!(@{self.as_ref()}.rename(@{new_name}))
    }

    pub fn upgrade(&self, power_type: PowerType) -> ReturnCode {
        js_unwrap!(@{self.as_ref()}.upgrade(@{power_type as u32}))
    }

    /// Convert this `AccountPowerCreep`, which can represent either a spawned
    /// or unspawned power creep, into a full `PowerCreep` object
    /// representation
    pub fn get_power_creep(&self) -> Option<PowerCreep> {
        // if the power creep has a position, it's spawned on the current shard and safe
        // to use as a full power creep object
        let upgrade_result = js! {
            const power_creep = @{self.as_ref()};
            if (power_creep.pos) {
                return power_creep;
            }
        }
        .try_into();

        match upgrade_result {
            Ok(v) => Some(v),
            Err(_) => None,
        }
    }
}

simple_accessors! {
    impl PowerCreep {
        pub fn level() -> u32 = level;
        pub fn shard() -> Option<String> = shard;
    }
}

simple_accessors! {
    impl AccountPowerCreep {
        pub fn level() -> u32 = level;
        pub fn shard() -> Option<String> = shard;
        pub fn delete_time() -> Option<u64> = deleteTime;
        pub fn spawn_cooldown_time() -> Option<u64> = spawnCooldownTime;
    }
}

creep_simple_generic_action! {
    impl PowerCreep {
        pub fn renew(StructureProperties) = renew();
    }
}

creep_simple_concrete_action! {
    impl PowerCreep {
        pub fn enable_room(StructureController) = enableRoom();
    }
}

creep_simple_concrete_action! {
    impl AccountPowerCreep {
        pub fn spawn(StructurePowerSpawn) = spawn();
    }
}