/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * Copyright (C) Henning Prömpers 2008 <henning.proempers@uni-jena.de>
 * 
 * main.c 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.
 * 
 * labcontrol 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, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <string.h>
#include <gnome.h>
#include <libgnome/gnome-i18n.h>
#include <glade/glade.h>
#include <gconf/gconf-client.h>
#include <gio/gio.h> // für Dateizugriffe, GVFS-Nachfolger

// Deklaration aller global verwendeten Variablen
enum possible_states {state_off, state_booting, state_on, state_zleaf_running, state_shutdowning, state_undefined}; // automatische nummerierung: 0=aus; 1=wird gestartet; 2=an; 3=zLeaf läuft; 4=wird heruntergefahren; 5= unbekannt
guint num_clients = 0; // number of clients
guint* client_update_wait;							// Zeit, die noch vergehen muss, bis clientstatus wieder aktualisiert werden darf
//gboolean client_update_lock[18];						// true, wenn Status gerade nicht aktualisiert werden darf (z.B. wenn gerade beim hochfahren)
GSList* symbols;										// Kopie der Symbolliste aus gconf, um die Symbolliste während der Laufzeit konsistent zu halten
//GSList* client_states;									// Liste der Zustände der einzelnen Clients, sorteier von client 1 bis client n
//GThread *zleaf_action_thread[18];						// dieser Thread soll nachher ztree starten und beenden, da die methode mit status einlesen etc sequentiell zu lange braucht
//GThreadPool *zleaf_start_threads;
GThreadPool *zleaf_kill_threads;
GOutputStream *logcontent = NULL;
GConfClient *gconf_client;// Verbindung zum GConf-System



#include "get_config_item.h"
#include "gui.h"
#include "get_state.h"
#include "quittungen.h"
#include "client_actions.h"
#include "local_actions.h"




/*
 * Logging Funktion, die alle Meldungen zusätzlich zum Terminal auch in eine Datei schreibt.
 */
void messages_mitschreiben(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data){
//	g_output_stream_write(logcontent, printf("%i", getpid()), strlen(printf("%i", getpid())), NULL, NULL); //PID
//	g_output_stream_write(logcontent, message, sizeof(message), NULL, NULL); //zeit
//	g_output_stream_write(logcontent, log_domain, sizeof(&log_domain), NULL, NULL); //level
//	g_output_stream_write(logcontent, message, strlen(message), NULL, NULL); //message
//	g_output_stream_write(logcontent, "\n", strlen("\n"), NULL, NULL); //neue Zeile
	// Standardhandler, der auf das Terminal schreibt etc.
	g_log_default_handler (log_domain, log_level, message, unused_data);
}


/*
 * Hauptfunktion, initialisiert das Programm und startet die Hauptschleife
 */
int main(int argc, char **argv)
{
	int i; // für lokale Schleifen
	gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv, GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR, NULL);

	// GConf-Verzeichnis zugreifbar machen
	gconf_client = gconf_client_get_default(); // Verbindung zu GConf herstellen
	gconf_client_add_dir(gconf_client, "/apps/labcontrol", GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); // GConf-Verzeichnis anmelden

	// set gettext-environment
	bindtextdomain("labcontrol", "/home/henning/labcontrol/src/po" );
//	bindtextdomain("labcontrol", gconf_client_get_string(gconf_client, "/apps/labcontrol/system_config/po_file_directory", NULL) );
	textdomain("labcontrol");

	// alles graphische initialisieren
	init_GUI();

	// Speicherplatz für die entsprechende Anzahl client_update_wait[] reservieren
	client_update_wait = g_malloc(sizeof(client_update_wait)*num_clients);
	

	// den Status in GConf jeweils auf undefiniert setzten
	for(i=1; i<=num_clients; i++){
		gconf_client_set_int(gconf_client, g_strdup_printf("/apps/labcontrol/temp/status/%i", i), state_undefined, NULL);
	}
	
	// alle Messages auch mitschreiben, dazu wird erst eine Datei im Append-Modus geöffnet und der default handler von g_message neu konfiguriert
	GFile *logfile = NULL;
	logfile = g_file_new_for_path(g_strdup_printf("/ramdisk/%i/labcontrol.log", getuid()));
	logcontent = G_OUTPUT_STREAM(g_file_append_to(logfile, G_FILE_CREATE_NONE, NULL, NULL));
	g_log_set_default_handler(messages_mitschreiben, NULL);
	
		
	{   // installierte zTree-Versionen erkennen und dem Auswahlmenü hinzufügen
		GFileEnumerator *ztreelist;
		ztreelist = g_file_enumerate_children (g_file_new_for_path("/opt/"), "standard::name,standard::type", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
		GFileInfo *unterordner = g_file_enumerator_next_file(ztreelist, NULL, NULL);
		gint entry_no = -1;
		while (unterordner !=NULL)
		{
			if(g_file_info_get_attribute_uint32(unterordner, "standard::type") == G_FILE_TYPE_DIRECTORY) // nur bei Ordnern weitermachen
			{
				if (strncmp(g_file_info_get_attribute_as_string(unterordner, G_FILE_ATTRIBUTE_STANDARD_NAME), "zTree_", 6) == 0){ // nur weitermachen, wenn Verzeichnisname mit zTree_ beginnt
					g_message(_("Erkenne zTree-Version in /opt/%s, Version wird der Auswahlliste hinzugefügt."), g_file_info_get_attribute_as_string(unterordner, G_FILE_ATTRIBUTE_STANDARD_NAME));
					gtk_combo_box_append_text(ztree_version_combobox, g_file_info_get_attribute_as_string(unterordner, G_FILE_ATTRIBUTE_STANDARD_NAME));
					entry_no++;
				
					// Wurde diese Version als letztes genutzt, diese auswählen (zuletzt genutzte aus GConf auslesen)
					// existiert der Wert in GConf noch nicht, dann den letzten Wert als Standart setzen)
					if (gconf_client_get_string(gconf_client, "/apps/labcontrol/temp/current_ztree_version", NULL)==NULL){
						gtk_combo_box_set_active(ztree_version_combobox, entry_no);
					}
					else if (strcmp(g_file_info_get_attribute_as_string(unterordner, G_FILE_ATTRIBUTE_STANDARD_NAME), gconf_client_get_string(gconf_client, "/apps/labcontrol/temp/current_ztree_version", NULL)) == 0){
						g_message("Erkenne, dass %s als letztes benutzt wurde, diese wird in der Auswahlliste aktiv gesetzt.", g_file_info_get_attribute_as_string(unterordner, G_FILE_ATTRIBUTE_STANDARD_NAME));
						gtk_combo_box_set_active(ztree_version_combobox, entry_no);
					}
				}
			
			}
			unterordner = g_file_enumerator_next_file(ztreelist, NULL, NULL);	
		}
		g_file_enumerator_close(ztreelist, NULL, NULL);
		g_object_unref(ztreelist);
	}
	





	// Verzeichnis in Ramdisk anlegen
	g_file_make_directory(g_file_new_for_path(g_strdup_printf("/ramdisk/%i/", getuid())), NULL, NULL);

	init_get_state();

	// ThreadPool anlegen, in dem nachher die zLeafs gestartet und gekillt werden
//	zleaf_start_threads = g_thread_pool_new((GFunc)start_zleaf_on_client, NULL, 18, FALSE, NULL);
	zleaf_kill_threads = g_thread_pool_new((GFunc)kill_zleaf_on_client, NULL, num_clients, FALSE, NULL);	

	// Wenn noch keine Quittung generiert wurde, Überwachung für erwartetes Paymentfile starten
	{gchar path_to_exp_paymentfile[500];
	strcpy(path_to_exp_paymentfile, g_strdup_printf("%s/%s", gconf_client_get_string(gconf_client, "/apps/labcontrol/temp/last_ztree_working_path", NULL), gconf_client_get_string(gconf_client, "/apps/labcontrol/temp/last_ztree_start_time", NULL)));
	if (!g_file_query_exists(g_file_new_for_path(g_strdup_printf("%s.pay", path_to_exp_paymentfile)), NULL)){
		watch_expected_paymentfile(path_to_exp_paymentfile);
		g_message(_("Das erwartete Paymentfile %s existiert noch nicht. Es wird auf ein Paymentfile gewartet und dann Quittungen generiert."), path_to_exp_paymentfile);
	}
	else{
		g_message(_("Das erwartete Paymentfile %s existiert bereits. Das Paymentfile wird nicht überwacht."), path_to_exp_paymentfile);
	}}
	
	// Fenster anzeigen und Hauptschleife starten
	gtk_widget_show (window);
	gtk_main ();
	gconf_client_remove_dir(gconf_client, "/apps/labcontrol", NULL); // GConf-Ordner abmelden
	g_object_unref(logcontent); // Log-OutputStream schließen
	return 0;
}

/*
 about-Box anzeigen
 */
void show_about(){
	gtk_show_about_dialog(GTK_WINDOW(window),  "version", "v0.3", "comments",
						  _("Tool to control oeconomic experiments on your Laboratory running zTree."),
						  "copyright", _("Copyright (c)\nFriedrich-Schiller-Universität Jena\nWirtschaftswissenschaftliche Fakultät\nLehrstuhl für empirische und experimentelle Wirtschafsforschung\n\nerstellt von Henning Prömpers"),
						  "logo", gdk_pixbuf_new_from_file("/usr/share/icons/gnome/scalable/categories/preferences-desktop.svg", NULL), NULL);
}