use twitch_irc::login::StaticLoginCredentials;
use twitch_irc::ClientConfig;
use twitch_irc::SecureTCPTransport;
use twitch_irc::TwitchIRCClient;
use twitch_irc::message::ServerMessage;
use std::env;
// use std::time::Instant;
use rand::Rng;
use dotenv::dotenv;
// mod helpers;

use std::collections::HashMap;


mod ratelimiter;
use ratelimiter::RateLimiter;

#[tokio::main]
pub async fn main() {

    dotenv().ok();

    let login_name = "modulatingforcebot".to_owned();
    let oauth_token = env::var("access_token").unwrap().to_owned();


    /*
        Vector of channels to join
     */

    let mut botchannels = Vec::new();
    /* botchannels.push(String::from("modulatingforcebot"));
    botchannels.push(String::from("notohh"));
    botchannels.push(String::from("modulatingforce"));
    botchannels.push(String::from("secondsocksan"));
    */

    for chnl in env::var("bot_channels").unwrap().split(',') {
        // println!("(Env Var # {})",chnl);
        botchannels.push(String::from(chnl));
    }


    let config = ClientConfig::new_simple(
        StaticLoginCredentials::new(login_name, Some(oauth_token))
    );
    let (mut incoming_messages, client) =
        TwitchIRCClient::<SecureTCPTransport, StaticLoginCredentials>::new(config);


    // client.join("modulatingforcebot".to_owned()).unwrap();
    // client.say("modulatingforcebot".to_owned(), "Connected!".to_owned()).await.unwrap();

    for chnl in &botchannels {
        client.join(chnl.to_owned()).unwrap();
        // client.say(chnl.to_owned(), "Connected!".to_owned()).await.unwrap();
        client.say(chnl.to_owned(), "annytfLurk".to_owned()).await.unwrap();
    }

    // Adding rate limit functionality to be under : https://dev.twitch.tv/docs/irc/#rate-limits


    // ratelimiters are a hashmap of channel and a corresponding rate limiter 
    let mut ratelimiters:HashMap<String,RateLimiter> = HashMap::new();

    for chnl in &botchannels {
        let n = RateLimiter::new();
        ratelimiters.insert(chnl.to_owned(),n);
    }

    println!("{:?}",ratelimiters);

    let join_handle = tokio::spawn(async move {
        while let Some(message) = incoming_messages.recv().await {
            // Below can be used to debug if I want to capture all messages
            // println!("Received message: {:?}", message);

            match message {
                ServerMessage::Notice(msg) => {
                    if let Some(chnl) = msg.channel_login {
                        println!("NOTICE : (#{}) {}", chnl, msg.message_text);
                    }
                }
                ServerMessage::Privmsg(msg) => {
                    println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
                    

                    let contextratelimiter = ratelimiters.get_mut(&msg.channel_login).expect("ERROR: Issue with Rate limiters");

                    match contextratelimiter.check_limiter() {
                        ratelimiter::LimiterResp::Allow => {
                            let maxblanks = rand::thread_rng().gen_range(1..=5);
                            let mut outmsg = "GotTrolled ".to_owned();
        
                            for _i in 1..maxblanks {
                                let blankspace: &str = "󠀀";
                                outmsg.push_str(blankspace);
                            }
        
                            client.say_in_reply_to(&msg,outmsg).await.unwrap();
                            println!("(#{}) > {}", msg.channel_login, "rate limit counter increase");
                            contextratelimiter.increment_counter();
                            println!("{:?}",ratelimiters);
                        },
                        ratelimiter::LimiterResp::Skip => {
                            (); // do nothing otherwise
                        }
                    }
                },
                ServerMessage::Whisper(msg) => {
                    println!("(w) {}: {}", msg.sender.name, msg.message_text);
                },
                ServerMessage::Join(msg) => {
                    println!("JOINED: {}", msg.channel_login);
                },
                ServerMessage::Part(msg) => {
                    println!("PARTED: {}", msg.channel_login);
                },
                _ => {}
            }
        }
    });





    join_handle.await.unwrap();
}