extern crate meltdown;
extern crate url;
extern crate gtk;

use url::Url;
use std::thread;
use std::path::Path;
use std::ffi::OsStr;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;

use gtk::prelude::*;
use gtk::Builder;
use gtk::MessageDialog;

use meltdown::{manager, join_part_files, config};

pub enum UIMessage {
    Finished,
    Paused,
    Aborted
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }
    let glade_src = include_str!("meltdown_ui.glade");
    let builder = Builder::new();
    builder.add_from_string(glade_src).unwrap();

    let window: gtk::Window = builder.get_object("window").unwrap();
    let open_button: gtk::ToolButton = builder.get_object("open_button").unwrap();
    let text_view: gtk::TextView = builder.get_object("text_view").unwrap();
    open_button.connect_clicked(move |_| {
        let text_buffer = text_view.get_buffer().unwrap();
        let (left, right) = text_buffer.get_bounds();
        let download_url = text_buffer.get_slice(&left, &right, false);
        let (tx, rx) = channel();
        let handler = thread::spawn(move|| {
            init_manager(download_url.unwrap(), tx.clone());
        });
    });

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    window.show_all();
    gtk::main();
}

pub fn init_manager(url_vec: String, ui_sender: Sender<UIMessage>) 
{
    let _ = config::setup_config_directories();
    let configurations = config::read_config();
    let url_vec = url_vec.split("\n").collect::<Vec<&str>>();
    let submitted_tasks = url_vec.len();
    let (main_tx, main_rx) = channel();

    for url in url_vec {
        let prefix = config::default_cache_dir().unwrap();
        let mut manager = manager::DownloadManager::new();
        let download_url = match Url::parse(&url) {
            Ok(url) => url,
            Err(_) => {
                println!("{:?} is not a valid Url", url);
                continue
            }
        };
        let url_path_vec = download_url.path_segments().unwrap().collect::<Vec<&str>>();
        let file_name = url_path_vec[url_path_vec.len() - 1].to_owned();
        manager.add_url(download_url.clone())
               .max_connection(configurations.max_connection)
               .file(&file_name)
               .finish();
        let complete_name = file_name.clone();
        let (tx, rx) = channel();
        let main_tx_clone = main_tx.clone();
        let _ = thread::spawn(move || {
            match manager.start(rx) {
                manager::State::Completed(bytes) => {
                    let ext = Path::new(&complete_name);
                    let ext_str = ext.extension().unwrap_or(&OsStr::new("unknown")).to_str();
                    let mut prefix_nested = prefix.clone();
                    prefix_nested.push(complete_name.clone());
                    join_part_files(&complete_name, prefix_nested.to_str().unwrap(), ext_str.unwrap());
                    let _ = main_tx_clone.send(manager::State::Completed(bytes));
                }
                manager::State::Aborted => {
                    println!("A Network Error occured");
                    return;
                }
                _ => {}
            }
        });
    }
    let mut complete_tasks = 0;
    loop {
        match main_rx.try_recv() {
            Ok(state) => {
                match state {
                    manager::State::Completed(bytes) => {
                        let _ = ui_sender.send(UIMessage::Finished);
                        println!("Download Complete of {:?} bytes", bytes);
                    }
                    _ => {}
                }
                complete_tasks += 1;
            }
            Err(_) => {}
        }
        if complete_tasks == submitted_tasks {
            println!("All tasks complete");
            break;
        }
    }
}