/*
 * Main menu and button
 *
 * Copyright (C) 2017  Patrick McDermott
 *
 * This file is part of Marquee.
 *
 * Marquee is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Marquee is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Marquee.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "main-menu.h"

#include <glib.h>
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>

#include "../../tab.h"
#include "../../web-view.h"
#include "../find-toolbar.h"

struct _MqMainMenu {
	GtkToolButton  parent_instance;
	MqTabPage     *tab_page;
	MqFindToolbar *find_toolbar;
	MqWebView     *web_view;
	GtkWidget     *popover;
};

enum {
	PROP_TAB_PAGE = 1,
	PROP_FIND_TOOLBAR,
	PROP_WEB_VIEW,
	N_PROPERTIES
};

static GParamSpec *obj_properties[N_PROPERTIES] = {NULL,};

struct _MqMainMenuClass {
	GtkToolButtonClass parent_class;
};

G_DEFINE_TYPE(MqMainMenu, mq_main_menu, GTK_TYPE_TOOL_BUTTON)

static void
zoom_out_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	mq_web_view_zoom_out(main_menu->web_view);
}

static void
zoom_reset_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	mq_web_view_zoom_reset(main_menu->web_view);
}

static void
zoom_in_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	mq_web_view_zoom_in(main_menu->web_view);
}

static void
find_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	gtk_widget_hide(main_menu->popover);
	mq_find_toolbar_reveal(main_menu->find_toolbar);
}

static void
fullscreen_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	gtk_widget_hide(main_menu->popover);
	mq_window_toggle_fullscreen(mq_tab_page_get_window(main_menu->tab_page));
}

static void
developer_tools_clicked_cb(GtkButton G_GNUC_UNUSED *button,
	MqMainMenu *main_menu)
{
	gtk_widget_hide(main_menu->popover);
	webkit_web_inspector_show(webkit_web_view_get_inspector(
			WEBKIT_WEB_VIEW(main_menu->web_view)));
}

static void
preferences_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	gtk_widget_hide(main_menu->popover);
	mq_tab_page_new("about:preferences", main_menu->tab_page);
	/* TODO: Hack: */
	gtk_notebook_next_page(GTK_NOTEBOOK(
			mq_tab_page_get_window(main_menu->tab_page)->notebook));
}

static void
about_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	gtk_widget_hide(main_menu->popover);
	mq_tab_page_new("about:", main_menu->tab_page);
	/* TODO: Hack: */
	gtk_notebook_next_page(GTK_NOTEBOOK(
			mq_tab_page_get_window(main_menu->tab_page)->notebook));
}

static void
quit_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu)
{
	/* mq_tab_page_quit() just calls mq_window_quit(), which just calls
	 * mq_application_quit(), which is asynchronous.  So close the menu. */
	gtk_widget_hide(main_menu->popover);
	mq_tab_page_quit(main_menu->tab_page);
}

#define BUTTON_ROWS 6
#define BUTTON_COLS 3
#define NEW_BUTTON(Y, X, ICON, TOOLTIP) \
	do { \
		buttons[Y * BUTTON_COLS + X] = gtk_button_new_from_icon_name(\
			ICON, GTK_ICON_SIZE_BUTTON); \
		gtk_widget_set_tooltip_text(buttons[Y * BUTTON_COLS + X], \
			TOOLTIP); \
		gtk_grid_attach(GTK_GRID(grid), buttons[Y * BUTTON_COLS + X], \
			X, Y, 1, 1); \
	} while (0)
#define CLICKED_CB(Y, X, CB) \
	g_signal_connect(buttons[Y * BUTTON_COLS + X], "clicked", \
		G_CALLBACK(CB), main_menu)

static void
menu_clicked_cb(MqMainMenu *main_menu)
{
	GtkWidget *grid;
	GtkWidget *buttons[BUTTON_ROWS * BUTTON_COLS];

	/* Set up the grid. */
	grid = gtk_grid_new();

	NEW_BUTTON(0, 0, "zoom-out",               "Zoom out");
	NEW_BUTTON(0, 1, "zoom-original",          "Reset zoom");
	NEW_BUTTON(0, 2, "zoom-in",                "Zoom in");
	NEW_BUTTON(1, 0, "document-open",          "Open file");
	NEW_BUTTON(1, 1, "document-save-as",       "Save page");
	NEW_BUTTON(1, 2, "mail-message-new",       "E-mail link");
	NEW_BUTTON(2, 0, "edit-find",              "Find");
	NEW_BUTTON(2, 1, "document-print-preview", "Print preview");
	NEW_BUTTON(2, 2, "document-print",         "Print");
	NEW_BUTTON(3, 0, "bookmark-new",           "Bookmarks");
	NEW_BUTTON(3, 1, "document-open-recent",   "History");
	NEW_BUTTON(3, 2, "document-save",          "Downloads");
	NEW_BUTTON(4, 0, "view-fullscreen",        "Full screen");
	NEW_BUTTON(4, 1, "document-properties",    "Developer tools");
	NEW_BUTTON(4, 2, "system-run",             "Preferences");
	NEW_BUTTON(5, 0, "help-about",             "About Marquee");
	NEW_BUTTON(5, 2, "application-exit",       "Quit");

	CLICKED_CB(0, 0, zoom_out_clicked_cb);
	CLICKED_CB(0, 1, zoom_reset_clicked_cb);
	CLICKED_CB(0, 2, zoom_in_clicked_cb);
	/* TODO: 1, 0: Open file */
	/* TODO: 1, 1: Save page */
	/* TODO: 1, 2: E-mail link */
	CLICKED_CB(2, 0, find_clicked_cb);
	/* TODO: 2, 1: Print preview */
	/* TODO: 2, 2: Print */
	/* TODO: 3, 0: Bookmarks */
	/* TODO: 3, 1: History */
	/* TODO: 3, 2: Downloads */
	CLICKED_CB(4, 0, fullscreen_clicked_cb);
	CLICKED_CB(4, 1, developer_tools_clicked_cb);
	CLICKED_CB(4, 2, preferences_clicked_cb);
	CLICKED_CB(5, 0, about_clicked_cb);
	CLICKED_CB(5, 2, quit_clicked_cb);

	/* Set up the popover. */
	main_menu->popover = gtk_popover_new(GTK_WIDGET(main_menu));
	gtk_container_add(GTK_CONTAINER(main_menu->popover), grid);

	/* NB: gtk_popover_popup() is new in GTK+ 3.22. */
	gtk_widget_show_all(main_menu->popover);
}

#undef BUTTON_ROWS
#undef BUTTON_COLS
#undef NEW_BUTTON

static void
get_property(GObject *object, guint property_id, GValue *value,
	GParamSpec *param_spec)
{
	MqMainMenu *main_menu;

	main_menu = MQ_MAIN_MENU(object);

	switch (property_id) {
		case PROP_TAB_PAGE:
			g_value_set_object(value, main_menu->tab_page);
			break;
		case PROP_FIND_TOOLBAR:
			g_value_set_object(value, main_menu->find_toolbar);
			break;
		case PROP_WEB_VIEW:
			g_value_set_object(value, main_menu->web_view);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id,
				param_spec);
			break;
	}
}

static void
set_property(GObject *object, guint property_id, const GValue *value,
	GParamSpec *param_spec)
{
	MqMainMenu *main_menu;

	main_menu = MQ_MAIN_MENU(object);

	switch (property_id) {
		case PROP_TAB_PAGE:
			main_menu->tab_page = g_value_get_object(value);
			break;
		case PROP_FIND_TOOLBAR:
			main_menu->find_toolbar = g_value_get_object(value);
			break;
		case PROP_WEB_VIEW:
			main_menu->web_view = g_value_get_object(value);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id,
				param_spec);
			break;
	}
}

static void
mq_main_menu_class_init(MqMainMenuClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS(klass);

	object_class->get_property = get_property;
	object_class->set_property = set_property;

	obj_properties[PROP_TAB_PAGE] = g_param_spec_object(
		"tab-page",
		"MqTabPage",
		"The ancestral MqTabPage instance",
		MQ_TYPE_TAB_PAGE,
		G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
		G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
	obj_properties[PROP_FIND_TOOLBAR] = g_param_spec_object(
		"find-toolbar",
		"MqFindToolbar",
		"The associated MqFindToolbar instance",
		MQ_TYPE_FIND_TOOLBAR,
		G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
		G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
	obj_properties[PROP_WEB_VIEW] = g_param_spec_object(
		"web-view",
		"MqWebView",
		"The associated MqWebView instance",
		MQ_TYPE_WEB_VIEW,
		G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
		G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
	g_object_class_install_properties(object_class, N_PROPERTIES,
		obj_properties);
}

static void
mq_main_menu_init(MqMainMenu *main_menu)
{
	gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(main_menu),
		gtk_image_new_from_icon_name("open-menu-symbolic",
			GTK_ICON_SIZE_SMALL_TOOLBAR));
	gtk_tool_button_set_label(GTK_TOOL_BUTTON(main_menu), "Menu");
	gtk_widget_set_tooltip_text(GTK_WIDGET(main_menu), "Open menu");
	g_signal_connect(main_menu, "clicked",
		G_CALLBACK(menu_clicked_cb), NULL);
}

GtkToolItem *
mq_main_menu_new(MqTabPage *tab_page, MqFindToolbar *find_toolbar,
	MqWebView *web_view)
{
	return g_object_new(MQ_TYPE_MAIN_MENU,
		"tab-page", tab_page,
		"find-toolbar", find_toolbar,
		"web-view", web_view,
		NULL);
}