use gtk;
use gtk::prelude::*;
use gtk::{Builder, Window};

use anyhow::{anyhow, Result};

use std::fs;
use std::path::Path;

mod shared;

use shared::config::{Config, COMMAND_COUNT};

fn main() -> Result<()> {
    gtk::init()?;

    let builder = Builder::from_string(include_str!("../macro_ui.glade"));

    setup_gui(builder)?;

    gtk::main();

    Ok(())
}

fn setup_gui(builder: Builder) -> Result<()> {
    let config = load_config()?;

    apply_config(&builder, &config)?;
    setup_save(&builder)?;

    let window: Window = builder
        .object("MainWindow")
        .ok_or(anyhow!("failed getting main window"))?;

    window.show_all();

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

    Ok(())
}

fn load_config() -> Result<Config> {
    let home_dir = std::env::var("HOME")?;

    if !Path::new(&format!("{}/.config", home_dir)).exists() {
        fs::create_dir(format!("{}/.config", home_dir))?;
    }

    if !Path::new(&format!("{}/.config/MacroBoard", home_dir)).exists() {
        fs::create_dir(format!("{}/.config/MacroBoard", home_dir))?;
    }

    Config::open(&format!("{}/.config/MacroBoard/commands.cfg", home_dir))
}

fn setup_save(builder: &Builder) -> Result<()> {
    let mut text_fields = Vec::with_capacity(COMMAND_COUNT);

    for i in 0..COMMAND_COUNT {
        let command_text_field: gtk::Entry = builder
            .object(&format!("ButtonCommand{}", i + 1))
            .ok_or(anyhow!("Failed getting Entry for command {}", i + 1))?;

        text_fields.push(command_text_field);
    }

    let save_button: gtk::Button = builder
        .object("SaveButton")
        .ok_or(anyhow!("Failed getting save button"))?;

    save_button.connect_clicked(move |_| {
        let mut config = Config::default();

        for i in 0..COMMAND_COUNT {
            let command = text_fields[i].buffer().text();

            config.commands[i] = Some(command);
        }

        let home_dir = match std::env::var("HOME") {
            Ok(var) => var,
            Err(_) => {
                println!("failed getting home directory");
                return;
            }
        };

        if let Err(err) = config.save(&format!("{}/.config/MacroBoard/commands.cfg", home_dir)) {
            println!("{}", err);
        }
    });

    Ok(())
}

fn apply_config(builder: &Builder, config: &Config) -> Result<()> {
    for i in 0..COMMAND_COUNT {
        if let Some(command) = &config.commands[i] {
            let command_text_field: gtk::Entry = builder
                .object(&format!("ButtonCommand{}", i + 1))
                .ok_or(anyhow!("Failed getting Entry for command {}", i + 1))?;

            command_text_field.buffer().set_text(command);
        }
    }

    Ok(())
}