/*
 * Copyright 2019 University of Toronto
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Authors: Mario Badr, Sameh Attia and Tanner Young-Schultz
 */

#include "ezgl/application.hpp"

namespace ezgl {
// A flag to disable event loop (default is false)
bool disable_event_loop = false;

void application::startup(GtkApplication *, gpointer user_data)
{
  auto ezgl_app = static_cast<application *>(user_data);
  g_return_if_fail(ezgl_app != nullptr);

  char const *main_ui_resource = ezgl_app->m_main_ui.c_str();

  // Build the main user interface from the XML resource.
  GError *error = nullptr;
  if(gtk_builder_add_from_resource(ezgl_app->m_builder, main_ui_resource, &error) == 0) {
    g_error("%s.", error->message);
  }

  for(auto &c_pair : ezgl_app->m_canvases) {
    GObject *drawing_area = ezgl_app->get_object(c_pair.second->id());
    c_pair.second->initialize(GTK_WIDGET(drawing_area));
  }

  g_info("application::startup successful.");
}

void application::activate(GtkApplication *, gpointer user_data)
{
  auto ezgl_app = static_cast<application *>(user_data);
  g_return_if_fail(ezgl_app != nullptr);

  // The main parent window needs to be explicitly added to our GTK application.
  GObject *window = ezgl_app->get_object(ezgl_app->m_window_id.c_str());
  gtk_application_add_window(ezgl_app->m_application, GTK_WINDOW(window));

  // Setup the default callbacks for the mouse and key events
  register_default_events_callbacks(ezgl_app);

  if(ezgl_app->m_register_callbacks != nullptr) {
    ezgl_app->m_register_callbacks(ezgl_app);
  } else {
    // Setup the default callbacks for the prebuilt buttons
    register_default_buttons_callbacks(ezgl_app);
  }

  if(ezgl_app->initial_setup_callback != nullptr)
    ezgl_app->initial_setup_callback(ezgl_app);

  g_info("application::activate successful.");
}

application::application(application::settings s)
    : m_main_ui(s.main_ui_resource)
    , m_window_id(s.window_identifier)
    , m_canvas_id(s.canvas_identifier)
    , m_application(gtk_application_new("ezgl.app", G_APPLICATION_FLAGS_NONE))
    , m_builder(gtk_builder_new())
    , m_register_callbacks(s.setup_callbacks)
{
#ifdef EZGL_USE_X11
  // Prefer x11 first, then other backends.
  gdk_set_allowed_backends("x11,*");
#endif

  // Connect our static functions application::{startup, activate} to their callbacks. We pass 'this' as the userdata
  // so that we can use it in our static functions.
  g_signal_connect(m_application, "startup", G_CALLBACK(startup), this);
  g_signal_connect(m_application, "activate", G_CALLBACK(activate), this);

  first_run = true;
}

application::~application()
{
  // GTK uses reference counting to track object lifetime. Since we called *_new() for our application and builder, we
  // need to unreference them. This should set their reference count to 0, letting GTK know that they should be cleaned
  // up in memory.
  g_object_unref(m_builder);
  g_object_unref(m_application);
}

canvas *application::get_canvas(const std::string &canvas_id) const
{
  auto it = m_canvases.find(canvas_id);
  if(it != m_canvases.end()) {
    return it->second.get();
  }

  g_warning("Could not find canvas with name %s.", canvas_id.c_str());
  return nullptr;
}

canvas *application::add_canvas(std::string const &canvas_id,
    draw_canvas_fn draw_callback,
    rectangle coordinate_system,
    color background_color)
{
  if(draw_callback == nullptr) {
    // A NULL draw callback means the canvas will never render anything to the screen.
    g_warning("Canvas %s's draw callback is NULL.", canvas_id.c_str());
  }

  // Can't use make_unique with protected constructor without fancy code that will confuse students, so we use new
  // instead.
  std::unique_ptr<canvas> canvas_ptr(new canvas(canvas_id, draw_callback, coordinate_system, background_color));
  auto it = m_canvases.emplace(canvas_id, std::move(canvas_ptr));

  if(!it.second) {
    // std::map's emplace does not insert the value when the key is already present.
    g_warning("Duplicate key (%s) ignored in application::add_canvas.", canvas_id.c_str());
  } else {
    g_info("The %s canvas has been added to the application.", canvas_id.c_str());
  }

  return it.first->second.get();
}

GObject *application::get_object(gchar const *name) const
{
  // Getting an object from the GTK builder does not increase its reference count.
  GObject *object = gtk_builder_get_object(m_builder, name);
  g_return_val_if_fail(object != nullptr, nullptr);

  return object;
}

int application::run(setup_callback_fn initial_setup_user_callback,
    mouse_callback_fn mouse_press_user_callback,
    mouse_callback_fn mouse_move_user_callback,
    key_callback_fn key_press_user_callback)
{
  if(disable_event_loop)
    return 0;

  initial_setup_callback = initial_setup_user_callback;
  mouse_press_callback = mouse_press_user_callback;
  mouse_move_callback = mouse_move_user_callback;
  key_press_callback = key_press_user_callback;

  // The result of calling g_application_run() again after it returns is unspecified.
  // So we have to destruct and reconstruct the GTKApplication
  if(!first_run) {
    // Destroy the GTK application
    g_object_unref(m_application);
    g_object_unref(m_builder);

    // Reconstruct the GTK application
    m_application = (gtk_application_new("edu.toronto.eecg.ezgl.app", G_APPLICATION_FLAGS_NONE));
    m_builder = (gtk_builder_new());
    g_signal_connect(m_application, "startup", G_CALLBACK(startup), this);
    g_signal_connect(m_application, "activate", G_CALLBACK(activate), this);
  }

  // set the first_run flag to false
  first_run = false;

  g_info("The event loop is now starting.");

  // see: https://developer.gnome.org/gio/unstable/GApplication.html#g-application-run
  return g_application_run(G_APPLICATION(m_application), 0, 0);
}

void application::quit()
{
  // Close the current window
  GObject *window = get_object(m_window_id.c_str());
  gtk_window_close(GTK_WINDOW(window));

  // Quit the GTK application
  g_application_quit(G_APPLICATION(m_application));
}

void application::register_default_events_callbacks(ezgl::application *application)
{
  // Get a pointer to the main window GUI object by using its name.
  std::string main_window_id = application->get_main_window_id();
  GObject *window = application->get_object(main_window_id.c_str());

  // Get a pointer to the main canvas GUI object by using its name.
  std::string main_canvas_id = application->get_main_canvas_id();
  GObject *main_canvas = application->get_object(main_canvas_id.c_str());

  // Connect press_key function to keyboard presses in the MainWindow.
  g_signal_connect(window, "key_press_event", G_CALLBACK(press_key), application);

  // Connect press_mouse function to mouse presses and releases in the MainWindow.
  g_signal_connect(main_canvas, "button_press_event", G_CALLBACK(press_mouse), application);

  // Connect release_mouse function to mouse presses and releases in the MainWindow.
  g_signal_connect(main_canvas, "button_release_event", G_CALLBACK(release_mouse), application);

  // Connect release_mouse function to mouse presses and releases in the MainWindow.
  g_signal_connect(main_canvas, "motion_notify_event", G_CALLBACK(move_mouse), application);

  // Connect scroll_mouse function to the mouse scroll event (up, down, left and right)
  g_signal_connect(main_canvas, "scroll_event", G_CALLBACK(scroll_mouse), application);
}

void application::register_default_buttons_callbacks(ezgl::application *application)
{
  // Connect press_zoom_fit function to the Zoom-fit button
  GObject *zoom_fit_button = application->get_object("ZoomFitButton");
  g_signal_connect(zoom_fit_button, "clicked", G_CALLBACK(press_zoom_fit), application);

  // Connect press_zoom_in function to the Zoom-in button
  GObject *zoom_in_button = application->get_object("ZoomInButton");
  g_signal_connect(zoom_in_button, "clicked", G_CALLBACK(press_zoom_in), application);

  // Connect press_zoom_out function to the Zoom-out button
  GObject *zoom_out_button = application->get_object("ZoomOutButton");
  g_signal_connect(zoom_out_button, "clicked", G_CALLBACK(press_zoom_out), application);

  // Connect press_up function to the Up button
  GObject *shift_up_button = application->get_object("UpButton");
  g_signal_connect(shift_up_button, "clicked", G_CALLBACK(press_up), application);

  // Connect press_down function to the Down button
  GObject *shift_down_button = application->get_object("DownButton");
  g_signal_connect(shift_down_button, "clicked", G_CALLBACK(press_down), application);

  // Connect press_left function to the Left button
  GObject *shift_left_button = application->get_object("LeftButton");
  g_signal_connect(shift_left_button, "clicked", G_CALLBACK(press_left), application);

  // Connect press_right function to the Right button
  GObject *shift_right_button = application->get_object("RightButton");
  g_signal_connect(shift_right_button, "clicked", G_CALLBACK(press_right), application);

  // Connect press_proceed function to the Proceed button
  GObject *proceed_button = application->get_object("ProceedButton");
  g_signal_connect(proceed_button, "clicked", G_CALLBACK(press_proceed), application);
}

void application::update_message(std::string const &message)
{
  // Get the StatusBar Object
  GtkStatusbar *status_bar = (GtkStatusbar *)get_object("StatusBar");

  // Remove all previous messages from the message stack
  gtk_statusbar_remove_all(status_bar, 0);

  // Push user message to the message stack
  gtk_statusbar_push(status_bar, 0, message.c_str());
}

void application::create_button(const char *button_text,
    int left,
    int top,
    int width,
    int height,
    button_callback_fn button_func)
{
  // get the internal Gtk grid
  GtkGrid *in_grid = (GtkGrid *)get_object("InnerGrid");

  // create the new button with the given label
  GtkWidget *new_button = gtk_button_new_with_label(button_text);

  // connect the buttons clicked event to the callback
  if(button_func != NULL) {
    g_signal_connect(G_OBJECT(new_button), "clicked", G_CALLBACK(button_func), this);
  }

  // add the new button
  gtk_grid_attach(in_grid, new_button, left, top, width, height);

  // show the button
  gtk_widget_show(new_button);
}

void application::create_button(const char *button_text,
    int insert_row,
    button_callback_fn button_func)
{
  // get the internal Gtk grid
  GtkGrid *in_grid = (GtkGrid *)get_object("InnerGrid");

  // add a row where we want to insert
  gtk_grid_insert_row(in_grid, insert_row);

  // create the button
  create_button(button_text, 0, insert_row, 3, 1, button_func);
}

bool application::destroy_button(const char *button_text_to_destroy)
{
  // get the inner grid
  GtkGrid *in_grid = (GtkGrid *)get_object("InnerGrid");

  // the text to delete, in c++ string form
  std::string text_to_del = std::string(button_text_to_destroy);

  // iterate over all of the children in the grid and find the button by it's text
  GList *children, *iter;
  children = gtk_container_get_children(GTK_CONTAINER(in_grid));
  for(iter = children; iter != NULL; iter = g_list_next(iter)) {
    // iterator to widget
    GtkWidget *widget = GTK_WIDGET(iter->data);

    // check if widget is a button
    if(GTK_IS_BUTTON(widget)) {
      // convert to button
      GtkButton *button = GTK_BUTTON(widget);

      // get the button label
      const char *button_label = gtk_button_get_label(button);
      if(button_label != nullptr) {
        std::string button_text = std::string(button_label);

        // does the label of the button match the one we want to delete?
        if(button_text == text_to_del) {
          // destroy the button (widget) and return true
          gtk_widget_destroy(widget);
          // free the children list
          g_list_free (children);
          return true;
        }
      }
    }
  }

  // free the children list
  g_list_free (children);
  // couldn't find the button with the label 'button_text_to_destroy'
  return false;
}

void application::change_button_text(const char *button_text, const char *new_button_text)
{
  // get the inner grid
  GtkGrid *in_grid = (GtkGrid *)get_object("InnerGrid");

  // the text to change, in c++ string form
  std::string text_to_change = std::string(button_text);

  // iterate over all of the children in the grid and find the button by it's text
  GList *children, *iter;
  children = gtk_container_get_children(GTK_CONTAINER(in_grid));
  for(iter = children; iter != NULL; iter = g_list_next(iter)) {
    // iterator to widget
    GtkWidget *widget = GTK_WIDGET(iter->data);

    // check if widget is a button
    if(GTK_IS_BUTTON(widget)) {
      // convert to button
      GtkButton *button = GTK_BUTTON(widget);

      // get the button label
      const char *button_label = gtk_button_get_label(button);
      if(button_label != nullptr) {
        std::string button_text_str = std::string(button_label);

        // does the label of the button match the one we want to change?
        if(button_text_str == text_to_change) {
          // change button label
          gtk_button_set_label(button, new_button_text);
        }
      }
    }
  }

  // free the children list
  g_list_free (children);
}

void application::change_canvas_world_coordinates(std::string const &canvas_id,
    rectangle coordinate_system)
{
  // get the canvas
  canvas *cnv = get_canvas(canvas_id);

  // reset the camera system with the new coordinates
  if (cnv != nullptr) {
    cnv->get_camera().reset_world(coordinate_system);
  }
}

void application::refresh_drawing()
{
  // get the main canvas
  canvas *cnv = get_canvas(m_canvas_id);

  // force redrawing
  cnv->redraw();
}

void application::flush_drawing()
{
  // get the main drawing area widget
  GtkWidget *drawing_area = (GtkWidget *)get_object(m_canvas_id.c_str());

  // queue a redraw of the GtkWidget
  gtk_widget_queue_draw(drawing_area);
}

renderer application::get_renderer()
{
  // get the main canvas
  canvas *cnv = get_canvas(m_canvas_id);

  return cnv->create_temporary_renderer();
}

void set_disable_event_loop(bool new_setting)
{
  disable_event_loop = new_setting;
}
}
