mod canvas;
mod picker;

use gdk;
use gtk::prelude::*;
// use gtk::{
//     self,
//     BoxExt,
//     EntryExt,
//     ContainerExt,
//     HeaderBarExt,
//     PanedExt,
//     WindowExt,
//     WidgetExt,
//     DialogExt,
//     FileChooserExt,
//     ButtonExt,
// };
use std::process;

use crate::constants;
use crate::strings;
use self::canvas::GridCanvas;
use self::picker::Picker;


/// The `App` is the main window that contains everything
pub struct App {
    pub window: gtk::Window,
    pub canvas: GridCanvas,
    pub container: gtk::Paned,
    pub toolbar: Toolbar,
    pub header: Header,
}

impl App {
    fn new() -> App {
        let window = gtk::Window::new(gtk::WindowType::Toplevel);
        let container = gtk::Paned::new(gtk::Orientation::Horizontal);
        let header = Header::new();
        let canvas = GridCanvas::new();

        window.add_events(gdk::EventMask::POINTER_MOTION_MASK);
        window.set_titlebar(Some(&header.container));
        window.set_title(constants::PROGRAM_NAME);
        window.set_wmclass(
            constants::PROGRAM_SLUG,
            constants::PROGRAM_NAME,
        );

        gtk::Window::set_default_icon_name("iconname");

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

        let toolbar = Toolbar::new();
        container.pack1(&canvas.canvas, true, true);
        container.pack2(&toolbar.toolbar, false, true);
        window.add(&container);

        App { window, header, canvas, toolbar, container }
    }

    pub fn run() {
        if gtk::init().is_err() {
            eprintln!("Failed to initialize GTK application");
            process::exit(1);
        }

        let app = App::new();
        app.window.show_all();
        gtk::main();
    }
}

// HEADER

/// The `Header` is the top toolbar; it contains buttons for opening
/// and saving documents as well as document status
pub struct Header {
    pub container: gtk::HeaderBar,
    pub open_btn: gtk::Button,
    pub save_btn: gtk::Button,
    pub save_as_btn: gtk::Button,
}

impl Header {
    fn new() -> Header {
        let container = gtk::HeaderBar::new();
        container.set_title(Some(constants::PROGRAM_NAME));
        container.set_show_close_button(true);

        let open_btn = gtk::Button::with_label(
            strings::OPEN_BTN
        );
        let save_btn = gtk::Button::with_label(
            strings::SAVE_BTN,
        );
        let save_as_btn = gtk::Button::with_label(
            strings::SAVE_AS_BTN,
        );

        container.pack_start(&open_btn);
        container.pack_end(&save_btn);
        container.pack_end(&save_as_btn);

        open_btn.connect_clicked(Header::do_open);
        open_btn.connect_clicked(Header::do_save);
        open_btn.connect_clicked(Header::do_save);

        Header { container, open_btn, save_btn, save_as_btn }
    }

    fn do_open(_: &gtk::Button) {
        let open_dialog = gtk::FileChooserDialog::new(
            Some("Open"),
            Some(&gtk::Window::new(gtk::WindowType::Popup)),
            gtk::FileChooserAction::Open,
        );

        open_dialog.add_button(
            strings::CANCEL_DIALOG_BTN,
            gtk::ResponseType::Cancel.into(),
        );
        open_dialog.add_button(
            strings::OPEN_DIALOG_BTN,
            gtk::ResponseType::Ok.into(),
        );

        // if open_dialog.run() == gtk::ResponseType::Ok.into() {
        //     println!("got {:?}", open_dialog.get_filename());
        // }

        unsafe { open_dialog.destroy(); }
    }

    fn do_save(_: &gtk::Button) {
        let save_dialog = gtk::FileChooserDialog::new(
            Some("Open"),
            Some(&gtk::Window::new(gtk::WindowType::Popup)),
            gtk::FileChooserAction::Open,
        );

        save_dialog.add_button(
            strings::CANCEL_DIALOG_BTN,
            gtk::ResponseType::Cancel.into(),
        );
        save_dialog.add_button(
            strings::OPEN_DIALOG_BTN,
            gtk::ResponseType::Ok.into(),
        );

        // if save_dialog.run() == gtk::ResponseType::Ok.into() {
        //     println!("got {:?}", save_dialog.get_filename());
        // }

        unsafe { save_dialog.destroy(); }
    }
}

/// The `Toolbar` is the pane on the right that contains tileset
/// information: this includes tileset info like width, height, and
/// source image, as well as the tile picker for elsewhere
pub struct Toolbar {
    toolbar: gtk::Box,
    tile_width: gtk::Entry,
    tile_height: gtk::Entry,
    load_tileset_btn: gtk::Button,
    picker: Picker,
}

impl Toolbar {
    fn new() -> Toolbar {
        let container = gtk::Box::new(gtk::Orientation::Vertical, 5);

        let tile_label = gtk::Label::new(
            Some(strings::TILESET_LABEL),
        );

        let tile_width = gtk::Entry::new();
        tile_width.set_text("16");
        let tile_height = gtk::Entry::new();
        tile_height.set_text("16");

        let load_tileset_btn = gtk::Button::with_label(
            strings::TILESET_LOAD_BTN,
        );

        let picker = Picker::new();

        container.pack_start(&tile_label, false, true, 0);
        container.pack_start(&tile_width, false, true, 0);
        container.pack_start(&tile_height, false, true, 0);
        container.pack_start(&load_tileset_btn, false, true, 0);
        container.pack_start(&picker.canvas, false, true, 0);

        Toolbar {
            toolbar: container,
            tile_width,
            tile_height,
            load_tileset_btn,
            picker,
        }
    }
}
