/*
 * $RCSfile: ilink.c,v $  $Revision: 1.33 $  $Name:  $
 * $Id: ilink.c,v 1.33 2007/09/09 18:10:48 bpaauwe Exp $
 * $Author: bpaauwe $
 * $Date: 2007/09/09 18:10:48 $
 * ----------------------------------------------------------------------------
 *
 *  Copyright (c) Bob Paauwe (2006)
 *
 *  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
 *
 * ----------------------------------------------------------------------------
 *
 *  Description:
 *    Header file for insteon message sending functions.
 * ----------------------------------------------------------------------------
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <glade/glade-build.h>

#ifdef WITH_GNOME
#  include <libgnomeui/libgnomeui.h>
#endif
#include "ilink.h"
#include "scenes.h"
#include "timers.h"
#include "libilib/ilib.h"

scene_t *scene_list = NULL;
device_t device_array[2000];
int last_device = -1;
unsigned char plc_id[10];
timer_timerec_t *timers = NULL;
char *current_file = NULL;

extern void initialize_device_discovery(GladeXML *xml);
extern void initialize_keypadlinc_configuration(GladeXML *xml);
extern void initialize_timers_configuration(GladeXML *xml);
extern void initialize_copy_scene(GladeXML *xml);
extern void initialize_progress_bar(GladeXML *xml);
extern void initialize_controlinc(GladeXML *xml);
extern void initialize_device_control(GladeXML *xml);
extern void initialize_scene_verify(GladeXML *xml);

int main (int argc, char **argv)
{
	const char *filename = "ilink-2.glade";
	const char *rootnode = NULL;
	GladeXML *xml;
	GtkCellRenderer *renderer;
	GtkTreeViewColumn *col;
	GtkListStore *store;
	gchar *window_name;

	progress_bar_active = 0;

	/* Default scene information file FIXME: command line option? */
	current_file = (char *)malloc(16);
	strcpy(current_file, "ilink_scene.inf");

	/* initialise libraries */
	gtk_init(&argc, &argv);

#ifdef WITH_GNOME
	if (!gnome_program_init ("Terminal", VERSION, LIBGNOMEUI_MODULE,
				argc, argv, NULL)) {
		g_error ("Cannot gnome_program_init ()");
	}
#endif

	/* construct the interface */
	xml = glade_xml_new(filename, rootnode, NULL);
	if (!xml) {
		g_warning("something bad happened while creating the interface");
		return 1;
	}

	main_window = glade_xml_get_widget(xml, "ilink_main_window");

	/* Get widget pointers for each of widgets that contain user entered data */
	device_id = glade_xml_get_widget(xml, "add_device_id");
	device_name = glade_xml_get_widget(xml, "add_device_name");
	device_type = glade_xml_get_widget(xml, "add_device_type");
	about_close = glade_xml_get_widget(xml, "about_close");

	new_scene_name = glade_xml_get_widget(xml, "new_scene_name");
	scene_selector = glade_xml_get_widget(xml, "scene_selector");
	scene_controller = glade_xml_get_widget(xml, "scene_controller");
	scene_group = glade_xml_get_widget(xml, "scene_group");

	responder_selector = glade_xml_get_widget(xml, "responder_selector");
	responder_data1 = glade_xml_get_widget(xml, "responder_data1");
	responder_data2 = glade_xml_get_widget(xml, "responder_data2");
	responder_data3 = glade_xml_get_widget(xml, "responder_data3");
	responder_list = glade_xml_get_widget(xml, "responder_list");

	device_selector = glade_xml_get_widget(xml, "device_selector");

	replace_dialog = glade_xml_get_widget(xml, "replace");
	replace_src = glade_xml_get_widget(xml, "replace_device_src");
	replace_dst = glade_xml_get_widget(xml, "replace_device_dst");

	link_list = glade_xml_get_widget(xml, "link_list");
	status_bar = glade_xml_get_widget(xml, "statusbar");
	device_bar = glade_xml_get_widget(xml, "statusbar1");

	open_file = glade_xml_get_widget(xml, "open_file_chooser");
	save_file = glade_xml_get_widget(xml, "save_file_chooser");

	about_dialog = glade_xml_get_widget(xml, "about");

	sr_dialog = glade_xml_get_widget(xml, "sr_dialog");
	sr_selector = glade_xml_get_widget(xml, "sr_selector");
	sr_entry = glade_xml_get_widget(xml, "sr_entry");
	sr_cancel = glade_xml_get_widget(xml, "sr_cancel");
	sr_apply = glade_xml_get_widget(xml, "sr_apply");
	sr_ok = glade_xml_get_widget(xml, "sr_ok");

	initialize_device_discovery(xml);
	initialize_device_control(xml);
	initialize_keypadlinc_configuration(xml);
	initialize_timers_configuration(xml);
	initialize_copy_scene(xml);
	initialize_controlinc(xml);
	initialize_progress_bar(xml);
	initialize_scene_verify(xml);

	glade_xml_signal_autoconnect(xml);

	g_object_unref(G_OBJECT(xml));

	gtk_widget_hide(about_dialog);
	gtk_widget_hide(replace_dialog);
	gtk_widget_hide(dc_dialog);

	/* Display a status message? */
	gtk_statusbar_push((GtkStatusbar *)status_bar, 1, "Loading Scene Info...");
	get_scene_info(current_file);
	build_tables();
	populate_combo_boxes();
	window_name = (gchar *)malloc(strlen(current_file) + 32);
	sprintf(window_name, "ilink INSTEON Scene Manager - %s", current_file);
	gtk_window_set_title((GtkWindow *)main_window, window_name);
	free(window_name);


	/* Create the columns for the responder list widget */
	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Responder", renderer,
			"text", 0, NULL);
	gtk_tree_view_append_column((GtkTreeView *)responder_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Level", renderer,
			"text", 1, NULL);
	gtk_tree_view_append_column((GtkTreeView *)responder_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Ramp", renderer,
			"text", 2, NULL);
	gtk_tree_view_append_column((GtkTreeView *)responder_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Group", renderer,
			"text", 3, NULL);
	gtk_tree_view_append_column((GtkTreeView *)responder_list, col);

	store = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
			G_TYPE_STRING);
	gtk_tree_view_set_model((GtkTreeView *)responder_list,
			(GtkTreeModel *)store);
	g_object_unref (G_OBJECT (store));

	/* Create the columns for the device link list widget */
	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Flags", renderer,
			"text", 0, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Group", renderer,
			"text", 1, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Device", renderer,
			"text", 2, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Level", renderer,
			"text", 3, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Ramp", renderer,
			"text", 4, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Extra", renderer,
			"text", 5, NULL);
	gtk_tree_view_append_column((GtkTreeView *)link_list, col);

	store = gtk_list_store_new(6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
			G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
	gtk_tree_view_set_model((GtkTreeView *)link_list,
			(GtkTreeModel *)store);
	g_object_unref (G_OBJECT (store));

	/* Create the columns for the timer list widget */
	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("ID", renderer,
			"text", 0, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Time", renderer,
			"text", 1, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Options", renderer,
			"text", 2, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Days Active", renderer,
			"text", 3, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("CID", renderer,
			"text", 4, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes("Command", renderer,
			"text", 5, NULL);
	gtk_tree_view_append_column((GtkTreeView *)tm_list, col);

	store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
			G_TYPE_STRING, G_TYPE_STRING);
	gtk_tree_view_set_model((GtkTreeView *)tm_list, (GtkTreeModel *)store);
	g_object_unref (G_OBJECT (store));


	gtk_statusbar_pop((GtkStatusbar *)status_bar, 1);

	/* if ((iplc = ilib_open(USE_IPLC, "/dev/usb/iplc0")) == NULL) { */
	if ((iplc = ilib_open(USE_HIDDEV, "/dev/hiddev0")) == NULL) {
		gtk_statusbar_push((GtkStatusbar *)status_bar, 1,
				"ERROR: PLC Uninitialized");
		return 0;
	} else {
		char status_str[35];
		unsigned char version;

		if (ibios_get_version(iplc, &version, plc_id) == 0) {
			sprintf(status_str, "PowerLinc %s Ver. %d.%d", plc_id,
					((version & 0xf0) >> 4), (version & 0xf));
		} else {
			sprintf(status_str, "PowerLinc -- <unknown>");
		}
		gtk_statusbar_push((GtkStatusbar *)status_bar, 1, status_str);
	}


	/* start the event loop */
	gtk_main();

	/* Program Exiting, clean up all the various memory allocations */
	if (current_file) {
		free(current_file);
	}

	if (timers) {
		free_timers(timers);
	}

	if (iplc) {
		ilib_close(iplc);
	}

	return 0;
}

/*
 * populate_combo_boxes
 *
 * Fill in all the combo boxes with the device and scene info
 */

void populate_combo_boxes()
{
	scene_t *scene;
	int i;
	char str[256];

	/* populate the device selector combo box */
	for (i = 0; i <= last_device; i++) {
		sprintf(str, "%s (%02x.%02x.%02x)", device_array[i].device_name,
				device_array[i].device_id[0],
				device_array[i].device_id[1],
				device_array[i].device_id[2]);
		gtk_combo_box_append_text((GtkComboBox *)device_selector, str);
		gtk_combo_box_append_text((GtkComboBox *)responder_selector,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)scene_controller,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)replace_src,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)replace_dst,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)dc_selector,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)tm_device_selector,
				device_array[i].device_name);
		gtk_combo_box_append_text((GtkComboBox *)cs_new_controller,
				device_array[i].device_name);
	}

	/* populate the scene selector list */
	scene = scene_list;
	while (scene != NULL) {
		gtk_combo_box_append_text((GtkComboBox *)scene_selector,
				scene->name);
		gtk_combo_box_append_text((GtkComboBox *)sr_selector,
				scene->name);
		scene = scene->next;
	}
}


void ilink_add_device(int index)
{
	char str[256];

	sprintf(str, "%s (%02x.%02x.%02x)", device_array[index].device_name,
			device_array[index].device_id[0],
			device_array[index].device_id[1],
			device_array[index].device_id[2]);
	gtk_combo_box_append_text((GtkComboBox *)device_selector, str);
	gtk_combo_box_append_text((GtkComboBox *)responder_selector,
			device_array[index].device_name);
	gtk_combo_box_append_text((GtkComboBox *)scene_controller,
			device_array[index].device_name);
	gtk_combo_box_append_text((GtkComboBox *)replace_src,
			device_array[index].device_name);
	gtk_combo_box_append_text((GtkComboBox *)replace_dst,
			device_array[index].device_name);
	gtk_combo_box_append_text((GtkComboBox *)dc_selector,
			device_array[index].device_name);
}


/*
 * free_combo_boxes
 *
 * Remove all the entries from the various combo boxes. This needs to be
 * done when the scene tables and/or the device list changes.
 */

void free_combo_boxes()
{
	scene_t *scene;
	int i = 0;

	scene = scene_list;
	while (scene != NULL) {
		gtk_combo_box_remove_text((GtkComboBox *)scene_selector, 0);
		scene = scene->next;
	}

	for (i = 0; i <= last_device; i++) {
		gtk_combo_box_remove_text((GtkComboBox *)device_selector, 0);
		gtk_combo_box_remove_text((GtkComboBox *)responder_selector, 0);
		gtk_combo_box_remove_text((GtkComboBox *)scene_controller, 0);
		gtk_combo_box_remove_text((GtkComboBox *)replace_src, 0);
		gtk_combo_box_remove_text((GtkComboBox *)replace_dst, 0);
		gtk_combo_box_remove_text((GtkComboBox *)dc_selector, 0);
		gtk_combo_box_remove_text((GtkComboBox *)tm_device_selector, 0);
		gtk_combo_box_remove_text((GtkComboBox *)cs_new_controller, 0);
	}
}


/*
 * status_message
 *
 * Display a status message
 */
void status_message(char *msg)
{
	gtk_statusbar_pop((GtkStatusbar *)device_bar, 3);
	gtk_statusbar_push((GtkStatusbar *)device_bar, 3, msg);
}

int file_changed(int save)
{
	if (save > 0) {
		need_to_save = 1;
	} else if (save < 0) {
		need_to_save = 0;
	}
	return need_to_save;
}

/*
 * Update kpl Progress
 */
void update_kpl_progress(int amount)
{
	if (amount > 100) {
		return;
	}

	gtk_progress_bar_set_fraction((GtkProgressBar *)kpl_progress,
			(gdouble)amount / 100.0);
	gtk_widget_queue_draw(kpl_progress);
	gtk_widget_queue_draw(kpl_dialog);
	while (gtk_events_pending()) {
		gtk_main_iteration();
	}
}
