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
129
use std::collections::HashMap;
use itertools::Itertools;
use crate::components::base::InnerClient;
use crate::components::chronicle::starrail::StarRailClient;
use crate::components::models::Base;
use crate::components::models::hoyolab::record::{Account, AccountList};
use crate::typing::{Dict, Game, Languages};



pub struct Client {
    pub(crate) client: InnerClient,
    pub(crate) starrail: StarRailClient,
}

impl Default for Client {
    fn default() -> Self {
        Client {
            client: InnerClient::default(),
            starrail: StarRailClient::default(),
        }
    }
}

impl AsMut<Client> for Client {
    fn as_mut(&mut self) -> &mut Client {
        self
    }
}

impl Client {
    pub fn new() -> Client {
        Client {
            client: InnerClient::default(),
            starrail: StarRailClient::default(),
        }
    }


    /// HELP: Someone tell me how to use as method chain without as_mut func
    pub fn set_cookies(&mut self,  cookies: CookieType) -> anyhow::Result<&mut Self> {
        use crate::components::managers::manager::{__parse_cookies, auto_cookie};

        let cookies = match cookies {
            CookieType::Str(cookies) => __parse_cookies(String::from(cookies)),
            CookieType::Dict(cookies) => {
                let mut dict = Dict::new();
                for (key, value) in cookies.into_iter() {
                    dict.insert(key.to_string(), value.to_string());
                }
                dict
            }
        };

        self.client.cookie_manager = auto_cookie(cookies);

        #[cfg(feature = "genshin")] {

        }

        #[cfg(feature = "starrail")] {

        }

        #[cfg(feature = "honkai")] {

        }

        Ok(self)
    }

    pub fn set_from_env(&mut self, path: Option<&str>) -> anyhow::Result<&mut Self> {
        use std::env::var;

        match path {
            None => dotenv::dotenv()?,
            Some(path) => dotenv::from_filename(path)?
        };

        let ltuid = var("ltuid").unwrap_or_else(|_| var("ltuid_v2").unwrap());
        let ltoken = var("ltoken").unwrap_or_else(|_| var("ltoken_v2").unwrap());
        let name = if ltoken.contains("v2") {
            (String::from("ltuid_v2"), String::from("ltoken_v2"))
        } else {
            (String::from("ltuid"), String::from("ltoken"))
        };

        let dict = HashMap::from([
            (name.0, ltuid),
            (name.1, ltoken),
        ]);

        self.set_cookies(CookieType::Dict(dict))
    }

    // Vec<Account>
    pub async fn get_game_accounts(&self, lang: Option<Languages>) -> anyhow::Result<Vec<Account>> {
        let result = self.client.request_hoyolab("binding/api/getUserGameRolesByCookie",
             lang,
         None,
         None,
         None,
         None
        ).await?;

        match result.json::<Base<AccountList>>().await {
            Ok(val) => Ok(val.data.list),
            Err(why) => {
                panic!("{}", why)
            }
        }
    }

    pub async fn get_game_account(&self, game: Option<Game>, lang: Option<Languages>) -> anyhow::Result<Vec<Account>> {
        let game = game.unwrap_or_else(|| self.client.game.clone());
        let accounts = self.get_game_accounts(lang).await?
            .into_iter()
            .filter(|account| {
                account.which_game().eq(&game)
            })
            .collect_vec();
        Ok(accounts)
    }
}

pub enum CookieType {
    Str(&'static str),
    Dict(HashMap<String, String>),
}