use std::{
    sync::Arc,
    rc::Rc, cell::RefCell
};

use alfis::Keystore;
use crate::{Mutex, Context, ui::KeyData};
use log::{error, info, warn};

use gtk::{
    prelude::*,
    ApplicationWindow,
    Button,
    Label,
    Box,
    Orientation,
    Entry,
    FileDialog
};


pub fn menu(window: &ApplicationWindow, parent: &gtk::Box, context: &Arc<Mutex<Context>>) {
    let key_data = Rc::new(RefCell::from(KeyData{hash: String::new(), path: String::new(), public: String::new()}));
    let keys = Box::new(Orientation::Horizontal, 8);
    keys.set_hexpand(true);
    parent.append(&keys);

    let key_hash = Entry::builder()
        .placeholder_text("No key loaded")
        .editable(false)
        .tooltip_text("If you load or mine a keypair the public key will be displayed here")
        .hexpand(true)
        .focusable(false)
        .build();
    keys.append(&key_hash);

    let load_btn = Button::with_label("Load key");

    let window = window.clone();
    let context = context.clone();
    load_btn.connect_clicked(move |_| {
        open_file(&window, &key_hash, &context, key_data.clone());
    });
    keys.append(&load_btn);

    let save_btn = Button::builder()
        .label("Save key")
        .sensitive(false)
        .build();
    keys.append(&save_btn);

    let mine_btn = Button::with_label("Mine new key");
    mine_btn.add_css_class("suggested-action");
    keys.append(&mine_btn);
    
    parent.append(&Label::new(Some("To mine domains you need a strong pair of signing keys and a pair of ecryption keys.")));
}

fn open_file(window: &ApplicationWindow, key_hash: &Entry ,context: &Arc<Mutex<Context>>, keydata: Rc<RefCell<KeyData>>) {
    let filter = gtk::FileFilter::new();
    filter.add_pattern("*.key");
    filter.add_pattern("*.toml");
    filter.set_name(Some("Key files"));

    let fc = FileDialog::builder()
        .title("Select key")
        .default_filter(&filter)
        .build();

    let context = context.clone();
    let key_hash = key_hash.clone();
    fc.open(Some(window), None::<gtk::gio::Cancellable>.as_ref(), move |result| {
        match result {
            Ok(file) => {
                match Keystore::from_file(file.path().unwrap().to_str().unwrap(), "") {
                    None => {
                        error!("Error loading keystore '{}'!", &file.path().unwrap().to_str().unwrap());
                        // show_warning(web_view, "Error loading key!<br>Key cannot be loaded or its difficulty is not enough.");  # TODO: display warnings
                        // event_fail(web_view, &format!("Error loading key from \\'{}\\'!", &file_name));
                    }
                    Some(keystore) => {
                        info!("Loaded keystore with keys: {:?}, {:?}", &keystore.get_public(), &keystore.get_encryption_public());

                        let path   = keystore.get_path().to_owned();
                        let public = keystore.get_public().to_string();
                        let hash   = keystore.get_hash().to_string();
                        let _ = &key_hash.set_text(public.as_str());
                        
                        let key_data = KeyData { path, public, hash };
                        *keydata.borrow_mut() = key_data;

                        if !context.lock().unwrap().select_key_by_public(&keystore.get_public()) {
                            context.lock().unwrap().add_keystore(keystore);
                        } else {
                            warn!("This key is already loaded!");
                        }
                    }
                }
            }
            Err(e) => {
                if !e.matches(gtk::gio::IOErrorEnum::Cancelled) {
                    error!("Error selecting file: {}", e);
                }
            }
        }
    });
}
