mod hiddenprotocol;
mod noroom;

use crate::{hiddenprotocol::*, noroom::*};
use gio::prelude::*;
use gtk::prelude::*;
use maraiah::durandal::err::*;

fn hide_on_delete(win: &gtk::Window, _: &gdk::Event) -> Inhibit
{
   win.hide();
   Inhibit(true)
}

fn mk_draw_area(b: &gtk::Builder)
{
   let area: gtk::DrawingArea = get_obj(b, "draw-area");

   let ax: gtk::Adjustment = get_obj(b, "adj-map-horz");
   let ay: gtk::Adjustment = get_obj(b, "adj-map-vert");

   let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1"));

   area.connect_draw(move |area, cr| {
      let w = f64::from(area.get_allocated_width());
      let h = f64::from(area.get_allocated_height());

      ax.set_lower(0.0);
      ax.set_upper(w);

      ay.set_lower(0.0);
      ay.set_upper(h);

      let d = CairoDrawArea::new(cr.clone(), w, h);

      draw_map_none(&d, &im);

      Inhibit(true)
   });
}

fn run_app(app: &gtk::Application)
{
   let b = &gtk::Builder::new_from_resource("/net/greyserv/maraiah/tycho/ui");

   let app_ = app.clone();
   let btn: gtk::MenuItem = get_obj(b, "btn-quit");
   btn.connect_activate(move |_| app_.quit());

   let btn: gtk::MenuItem    = get_obj(b, "btn-about");
   let win: gtk::AboutDialog = get_obj(b, "win-about");
   btn.connect_activate(move |_| {win.run(); win.hide();});

   let btn: gtk::MenuItem = get_obj(b, "btn-show-map-view");
   let win: gtk::Window   = get_obj(b, "win-map-view");
   win.connect_delete_event(hide_on_delete);
   btn.connect_activate(move |_| win.show_all());

   let btn: gtk::MenuItem = get_obj(b, "btn-show-map-tools");
   let win: gtk::Window   = get_obj(b, "win-map-tools");
   win.connect_delete_event(hide_on_delete);
   btn.connect_activate(move |_| win.show_all());

   let btn: gtk::MenuItem = get_obj(b, "btn-show-map-prop");
   let win: gtk::Window   = get_obj(b, "win-map-prop");
   win.connect_delete_event(hide_on_delete);
   btn.connect_activate(move |_| win.show_all());

   mk_draw_area(b);

   let win: gtk::AboutDialog = get_obj(b, "win-about");
   win.set_authors(&env!("CARGO_PKG_AUTHORS").split(';').collect::<Vec<_>>());
   win.set_version(env!("CARGO_PKG_VERSION"));
   win.set_website(env!("CARGO_PKG_HOMEPAGE"));
   win.set_logo(&load_img("/net/greyserv/maraiah/tycho/tycho2"));

   let win: gtk::Window = get_obj(b, "win-main");
   win.set_application(app);
   win.show_all();
}

fn load_img(path: &'static str) -> gdk_pixbuf::Pixbuf
{
   gdk_pixbuf::Pixbuf::new_from_resource(path).unwrap()
}

fn get_obj<T>(b: &gtk::Builder, name: &str) -> T
   where T: glib::object::IsA<glib::object::Object>
{
   b.get_object(name).unwrap()
}

fn main() -> ResultS<()>
{
   // get jacked, punk. opaque data structures are for nerds.
   const RESOURCE_DATA: &[u8] = include_bytes!("data/tycho.res");

   let mut static_resource =
      gio_sys::GStaticResource{data:     RESOURCE_DATA.as_ptr(),
                               data_len: RESOURCE_DATA.len(),
                               resource: std::ptr::null_mut(),
                               next:     std::ptr::null_mut(),
                               padding:  std::ptr::null_mut()};

   unsafe {
      gio_sys::g_static_resource_init(&mut static_resource);
   }

   let app = gtk::Application::new("net.greyserv.maraiah.tycho",
                                   gio::ApplicationFlags::empty())?;

   app.connect_activate(run_app);

   let ret = if app.run(&[]) == 0 {
      Ok(())
   } else {
      Err(err_msg("bad return"))
   };

   unsafe {
      gio_sys::g_static_resource_fini(&mut static_resource);
   }

   ret
}

// EOF
