extern crate serde;
extern crate clap;
extern crate cursive;

extern crate tokio;
extern crate reqwest;

use std::{fs, env};
use std::path::PathBuf;

use clap::{Arg, App};
use cursive::Cursive;
use cursive::menu::MenuTree;
use cursive::event::Key;

use serde_json;

mod types;
mod http;

#[tokio::main]
async fn main() {
    let args = App::new("Freechat TUI")
        .version("69.420")
        .author("godrah")
        .about("oh you know")
        .arg(Arg::with_name("config")
            .short("c")
            .long("config")
            .value_name("CONFIG")
            .help("Specify path of config to use")
            .takes_value(true))
        .arg(Arg::with_name("theme")
            .short("t")
            .long("theme")
            .value_name("THEME_FILE")
            .help("Specify theme file on startup")
            .takes_value(true)).get_matches();
    
    let config: types::Config = if args.args.len() == 0 {
        let home = env::var("HOME").unwrap();
        match fs::read_to_string(format!("{}/.config/freechat/config.json", home)) {
            Ok(data) => serde_json::from_str(&data).unwrap(),
            Err(e) => panic!("Bro: {}", e)
        }
    } else{
        let path = args.value_of("config").unwrap();
        match fs::read_to_string(path) {
            Ok(data) => serde_json::from_str(&data).unwrap(),
            Err(e) => panic!("Bro: {}", e)
        }
    };


    // only load a theme if requested
    let theme = if let Some(theme) = args.value_of("theme") {
        Some(PathBuf::from(theme))
    } else {
        None
    };

    let mut app = cursive::default();

    // optionally load optional theme
    if let Some(theme) = theme { let _ = app.load_theme_file(theme); }

    app.add_global_callback('q', Cursive::quit);
    app.add_global_callback(Key::Esc, |s| s.select_menubar());
    app.set_autohide_menu(false); // don't hide the menubar all the time



    // menu bar at the top lets us pick between different servers in the config
    for server in config.servers.iter() {
        let name = match &server.name {
            Some(name) => name.to_string(),
            //None => String::from(&format!("{}", server.ip))
            None => String::from("None") 
        };

        app.menubar().add_subtree(&name, MenuTree::new()); // add server name
        // on action: 
            // open up search able list of channels
            // choose from that list of channels which one you want to see

        // NOTE: not passing the domain as the IP is resolved on server join
        if let Some(channels) = http::fetch_channels(&server.ip, server.port).await {
            // add a bunch of actionable leafs to our sub tree
            for channel in channels {
                app.menubar().find_subtree(name.as_ref()).unwrap().add_leaf(channel.name.clone(), move |s| {
                    let (ip, name) = channel.parts();
                    http::sync::open_channel(ip, name, s);
                });
            }
        }
    }

    app.run();
}
