/**************************************************************

main_dlg.cpp (C-Munipack project)
Main dialog
Copyright (C) 2008 David Motl, dmotl@volny.cz

This program 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 2
of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/

#include <stdlib.h>
#include <glib.h>
#include <math.h>
#include <string.h>

#include "graph_main.h"
#include "graph_dlg.h"
#include "cmpack_graph_view.h"
#include "cmpack_curve_plot.h"

enum tCommandId
{
	CMD_EXPORT = 100
};

static const CPopupMenu::tPopupMenuItem GraphTestMenu[] = {
	{ CPopupMenu::MB_ITEM, CMD_EXPORT,		"_Save as image" },
	{ CPopupMenu::MB_END }
};

static char *get_icon_file(const char *)
{
	return NULL;
}

static gint LimitInt(gint x, gint min, gint max)
{
	if (x < min)
		return min;
	else if (x > max)
		return max;
	else
		return x;
}

static void set_rgb(GdkColor *color, gdouble red, gdouble green, gdouble blue)
{
	color->red = LimitInt((gint)(red*65535.0), 0, 65535);
	color->green = LimitInt((gint)(green*65535.0), 0, 65535);
	color->blue = LimitInt((gint)(blue*65535.0), 0, 65535);
}

//-------------------------   GRAPH TEST DIALOG   --------------------------------

CMainWindow::CMainWindow():m_pDlg(NULL), m_Updating(false), m_UpdatePos(false), 
	m_TimerId(-1), m_StatusCtx(-1), m_StatusMsg(-1)
{
	GtkWidget *vbox, *hbox, *scrwnd;
	CmpackGraphItem item;
	gdouble xmin = DBL_MAX, xmax = -DBL_MAX;

	static const int len = 21;
	static const double amp = 100.0, offset = 0.0;

	memset(&item, 0, sizeof(CmpackGraphItem));

	// Light curve data
	m_GraphData = cmpack_graph_data_new(2, len);
	for (int i=0; i<len; i++) {
		item.x = 2453000.123456789 + 10.0*i;
		if (xmin > item.x)
			xmin = item.x;
		if (xmax < item.x)
			xmax = item.x;
		item.y = amp*sin(i*2.0*3.14159/20) + offset;
		item.color = (item.y<0 ? CMPACK_COLOR_RED : CMPACK_COLOR_DEFAULT);
		cmpack_graph_data_set(m_GraphData, 0, i, &item, sizeof(item));

		item.y = amp*cos(i*2.0*3.14159/20)*cos(i*2.0*3.14159/20);
		item.color = (item.y<0.5 ? CMPACK_COLOR_BLUE : CMPACK_COLOR_DEFAULT);
		cmpack_graph_data_set(m_GraphData, 1, i, &item, sizeof(item));
	}
	
	// Main window
	m_pDlg = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW (m_pDlg), "Graph test");
	gtk_window_set_position(GTK_WINDOW(m_pDlg), GTK_WIN_POS_CENTER);
	gtk_window_set_default_size(GTK_WINDOW(m_pDlg), 800, 600);
	g_signal_connect(G_OBJECT(m_pDlg), "delete_event", G_CALLBACK (exit_event), this);
	gtk_widget_realize(GTK_WIDGET(m_pDlg));

	// Window layout
	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(m_pDlg), vbox);

	// Central widget layout
	hbox = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

	// Graph view
	m_pGraph = cmpack_graph_view_new_with_model(m_GraphData);
	scrwnd = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwnd),
		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwnd), 
		GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(scrwnd), m_pGraph);
	gtk_box_pack_start(GTK_BOX(hbox), scrwnd, TRUE, TRUE, 0);
	cmpack_graph_view_set_selection_mode(CMPACK_GRAPH_VIEW(m_pGraph), GTK_SELECTION_MULTIPLE);
	cmpack_graph_view_set_scales(CMPACK_GRAPH_VIEW(m_pGraph), TRUE, TRUE);
	cmpack_graph_view_set_grid(CMPACK_GRAPH_VIEW(m_pGraph), TRUE, TRUE);
	cmpack_graph_view_set_mouse_control(CMPACK_GRAPH_VIEW(m_pGraph), TRUE);

	cmpack_graph_view_set_x_axis(CMPACK_GRAPH_VIEW(m_pGraph), FALSE, FALSE, 
		xmin, xmax, 1.0, GRAPH_TIME, 1, 3, "X");
	cmpack_graph_view_set_y_axis(CMPACK_GRAPH_VIEW(m_pGraph), FALSE, FALSE, 
		offset-amp, offset+amp, 1.0, GRAPH_FIXED, 1, 3, "Y");

	/*cmpack_graph_view_set_cursors(CMPACK_GRAPH_VIEW(m_pGraph), CMPACK_AXIS_Y, 2);
	cmpack_graph_view_set_cursor_visibility(CMPACK_GRAPH_VIEW(m_pGraph), CMPACK_AXIS_Y, -1, TRUE);
	cmpack_graph_view_set_cursor_caption(CMPACK_GRAPH_VIEW(m_pGraph), CMPACK_AXIS_Y, 0, "X1");
	cmpack_graph_view_set_cursor_caption(CMPACK_GRAPH_VIEW(m_pGraph), CMPACK_AXIS_Y, 1, "X2");
	
	/* Curve plot
	m_pGraph = cmpack_curve_plot_new_with_model(m_GraphData);
	scrwnd = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwnd),
		GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwnd), 
		GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(scrwnd), m_pGraph);
	gtk_box_pack_start(GTK_BOX(vbox), scrwnd, TRUE, TRUE, 0);
	cmpack_curve_plot_set_selection_mode(CMPACK_CURVE_PLOT(m_pGraph), GTK_SELECTION_MULTIPLE);
	cmpack_curve_plot_set_scales(CMPACK_CURVE_PLOT(m_pGraph), TRUE, TRUE);
	cmpack_curve_plot_set_grid(CMPACK_CURVE_PLOT(m_pGraph), TRUE, TRUE);
	cmpack_curve_plot_set_mouse_control(CMPACK_CURVE_PLOT(m_pGraph), TRUE);
	cmpack_curve_plot_set_style(CMPACK_CURVE_PLOT(m_pGraph), PLOT_HISTOGRAM);

	cmpack_curve_plot_set_x_axis(CMPACK_CURVE_PLOT(m_pGraph), 1.0, 0.0,  
		1.0, PLOT_FIXED, 0, 3, "X");
	cmpack_curve_plot_set_y_axis(CMPACK_CURVE_PLOT(m_pGraph), FALSE, FALSE, 
		-100, 100, 1.0, PLOT_FIXED, 0, 3, "Y");*/

	g_signal_connect(G_OBJECT(m_pGraph), "mouse-moved", G_CALLBACK (mouse_moved), this);
	g_signal_connect(G_OBJECT(m_pGraph), "button_press_event", G_CALLBACK(button_press_event), this);

	// Status bar
	m_pStatus = gtk_statusbar_new();
	gtk_box_pack_start(GTK_BOX(vbox), m_pStatus, FALSE, FALSE, 0);
	m_StatusCtx = gtk_statusbar_get_context_id(GTK_STATUSBAR(m_pStatus), "Main");

	// Popup menu
	m_Menu.Create(GraphTestMenu);

	// Timers
	m_TimerId = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 100, GSourceFunc(update_sbar), this, NULL);

	// Show window
	gtk_widget_show_all(vbox);
	gtk_window_present(GTK_WINDOW(m_pDlg));
}

CMainWindow::~CMainWindow()
{
	g_source_remove(m_TimerId);
	g_object_unref(m_GraphData);
}

gint CMainWindow::exit_event(GtkWidget *widget, GdkEvent *event, CMainWindow *pMe)
{
	gtk_main_quit();
	return FALSE;
}

void CMainWindow::mouse_moved(GtkWidget *button, CMainWindow *pDlg)
{
	pDlg->m_UpdatePos = true;
}

//
// Mouse button handler
//
gint CMainWindow::button_press_event(GtkWidget *widget, GdkEventButton *event, CMainWindow *pMe)
{
	if (event->type==GDK_BUTTON_PRESS && event->button==3) {
		gtk_widget_grab_focus(widget);
		if (widget==pMe->m_pGraph) {
			gint col, row;
			if (cmpack_graph_view_get_focused(CMPACK_GRAPH_VIEW(widget), &col, &row) && !cmpack_graph_view_is_selected(CMPACK_GRAPH_VIEW(widget), col, row)) {
				cmpack_graph_view_unselect_all(CMPACK_GRAPH_VIEW(widget));
				cmpack_graph_view_select(CMPACK_GRAPH_VIEW(widget), col, row);
			}
		}
		pMe->OnContextMenu(widget, event);
		return TRUE;
	}
	return FALSE;
}

//
// Show context menu
//
void CMainWindow::OnContextMenu(GtkWidget *widget, GdkEventButton *event)
{
	int res, selected;

	if (widget==m_pGraph) {
		selected = cmpack_graph_view_get_selected_count(CMPACK_GRAPH_VIEW(m_pGraph));
		res = m_Menu.Execute(event);
		switch (res) 
		{
		case CMD_EXPORT:
			// Show frame preview
			SaveAsImage();
			break;
		}
	}
}

gboolean CMainWindow::update_sbar(CMainWindow *pDlg)
{
	if (pDlg->m_UpdatePos) {
		pDlg->m_UpdatePos = false;
		pDlg->UpdateStatus();
	}
	return TRUE;
}

void CMainWindow::UpdateStatus(void)
{
	gchar buf[256];
	double x, y;

	if (m_StatusMsg>=0) {
		gtk_statusbar_pop(GTK_STATUSBAR(m_pStatus), m_StatusCtx);
		m_StatusMsg = -1;
	}

	if (CMPACK_IS_CHART_VIEW_CLASS(m_pGraph)) {
		if (cmpack_graph_view_mouse_pos(CMPACK_GRAPH_VIEW(m_pGraph), &x, &y)) {
			sprintf(buf, "x = %.1f, y = %.1f", x, y);
			m_StatusMsg = gtk_statusbar_push(GTK_STATUSBAR(m_pStatus), m_StatusCtx, buf);
		}
	}
}

void CMainWindow::SaveAsImage(void)
{
	cmpack_graph_view_write_to_file(CMPACK_GRAPH_VIEW(m_pGraph), "graph.png", "png");
}
