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
use std::{collections::HashMap, error::Error, ffi::CStr};

use crate::{ai_interface::AIInterface, get_callback};

#[derive(Debug, Copy, Clone)]
pub struct SkirmishAI {
    ai_id: i32,
}

#[derive(Debug, Clone)]
pub struct SkirmishAIAll {
    number_of_ais: i32,
    max_number_of_ais: i32,
    team: i32,
    info: HashMap<String, (String, String)>,
    options: HashMap<String, String>,
}

impl AIInterface {
    pub fn skirmish_ai(&self) -> SkirmishAI {
        SkirmishAI { ai_id: self.ai_id }
    }
}

impl SkirmishAI {
    pub fn number_of_ais(&self) -> Result<i32, Box<dyn Error>> {
        let get_size = get_callback!(self.ai_id, getNumSkirmishAIs)?;

        Ok(unsafe { get_size(self.ai_id) })
    }

    pub fn max_number_of_ais(&self) -> Result<i32, Box<dyn Error>> {
        let get_max = get_callback!(self.ai_id, getMaxSkirmishAIs)?;

        Ok(unsafe { get_max(self.ai_id) })
    }

    pub fn team(&self) -> Result<i32, Box<dyn Error>> {
        let get_team_id = get_callback!(self.ai_id, SkirmishAI_getTeamId)?;

        Ok(unsafe { get_team_id(self.ai_id) })
    }

    pub fn info(&self) -> Result<HashMap<String, (String, String)>, Box<dyn Error>> {
        let get_info_size = get_callback!(self.ai_id, SkirmishAI_Info_getSize)?;
        let get_info_key = get_callback!(self.ai_id, SkirmishAI_Info_getKey)?;
        let get_info_value = get_callback!(self.ai_id, SkirmishAI_Info_getValue)?;
        let get_info_description = get_callback!(self.ai_id, SkirmishAI_Info_getDescription)?;

        let mut info = HashMap::new();
        let info_size = unsafe { get_info_size(self.ai_id) };
        for i in 0..info_size {
            let key =
                String::from(unsafe { CStr::from_ptr(get_info_key(self.ai_id, i)) }.to_str()?);
            let value =
                String::from(unsafe { CStr::from_ptr(get_info_value(self.ai_id, i)) }.to_str()?);
            let description = String::from(
                unsafe { CStr::from_ptr(get_info_description(self.ai_id, i)) }.to_str()?,
            );

            info.insert(key, (value, description));
        }

        Ok(info)
    }

    pub fn options(&self) -> Result<HashMap<String, String>, Box<dyn Error>> {
        let get_options_size = get_callback!(self.ai_id, SkirmishAI_OptionValues_getSize)?;
        let get_options_key = get_callback!(self.ai_id, SkirmishAI_OptionValues_getKey)?;
        let get_options_value = get_callback!(self.ai_id, SkirmishAI_OptionValues_getValue)?;

        let mut options = HashMap::new();
        let options_size = unsafe { get_options_size(self.ai_id) };
        for i in 0..options_size {
            let key =
                String::from(unsafe { CStr::from_ptr(get_options_key(self.ai_id, i)) }.to_str()?);
            let value =
                String::from(unsafe { CStr::from_ptr(get_options_value(self.ai_id, i)) }.to_str()?);

            options.insert(key, value);
        }

        Ok(options)
    }

    pub fn all(&self) -> Result<SkirmishAIAll, Box<dyn Error>> {
        Ok(SkirmishAIAll {
            number_of_ais: self.number_of_ais()?,
            max_number_of_ais: self.max_number_of_ais()?,
            team: self.team()?,
            info: self.info()?,
            options: self.options()?,
        })
    }
}