/* ***********************IMPORTANT *********************************************
 *  Copyright (C) 2004-2007 Thierry Lagarde <tlagarde@users.sourceforge.net>
 *  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.
 *
 *
 *                      ********************
 *
 *
 *  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 Library General Public License for more details.
 *
 *
 *                      ********************
 *
 *
 * You are highly encouraged to send your changes to <tlagarde@users.sourceforge.net>
 * for possible incorporation into the main distribution.
 * By sending these changes to <tlagarde@users.sourceforge.net>,
 * it is assumed that you are offering <tlagarde@users.sourceforge.net>
 * the unlimited, non-exclusive right to reuse, modify, and relicense the code.
 *
 *
 *                      ********************
 *
 *  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 <gtk/gtk.h>
#include "Add_Network_Subnet.h"
#include "Interface/Wizard_Interface_Add_Network.h"
#include "Debug.h"
#include "main.h"
#include "Macro.h"


void Subnet_Sensible (gboolean bool)
{
	gtk_widget_set_sensitive (combobox_Network_Private_Subnet, bool);
	gtk_widget_set_sensitive (spinbutton_Network_Private_Subnet_A, bool);
	gtk_widget_set_sensitive (spinbutton_Network_Private_Subnet_B, bool);
	gtk_widget_set_sensitive (spinbutton_Network_Private_Subnet_C, bool);
}


void Supprime_Subnet_liste (struct Struct_Subnet *Subnet)
{
	GtkTreeModel *model = NULL;

	ERROR_if (Subnet == NULL);
	G_LIST_REMOVE (GList_Subnet, Subnet);
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview_Network_Private_Subnet));
	gtk_tree_store_remove (GTK_TREE_STORE (model), &Subnet->ID_Arbre_Ligne);
	MYFREE (Subnet);	
}


void Affiche_Subnet (struct Struct_Subnet *Subnet)
{
	GtkTreeModel *model = NULL;
	gchar    *Masque = NULL, *IP = NULL;
	GtkTreeIter Ligne;

	ERROR_if (Subnet == NULL);
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview_Network_Private_Subnet));
	gtk_tree_store_append (GTK_TREE_STORE (model), &Ligne, NULL);
	Subnet->ID_Arbre_Ligne = Ligne;
	switch (Subnet->Masque) {
	    case 0:
		    Masque = g_strdup ("255.0.0.0");
		    break;
	    case 1:
		    Masque = g_strdup ("255.255.0.0");
		    break;
	    case 2:
		    Masque = g_strdup ("255.255.255.0");
		    break;
	    default:
		    Masque = g_strdup ("?.?.?.?");
	}
	IP = g_strdup_printf ("%d.%d.%d.0", Subnet->A, Subnet->B, Subnet->C);
	gtk_tree_store_set (GTK_TREE_STORE (model), &Ligne, COL_MASQUE, Masque, COL_IP, IP, POINTER_SUBNET, Subnet, -1);
	MYFREE (Masque);
	MYFREE (IP);
}


void Afficher_Liste_Subnet (void)
{
	struct Struct_Subnet *Subnet = NULL;
	guint     Nb_Objet_Liste, i;

	Nb_Objet_Liste = g_list_length (GList_Subnet);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Subnet = g_list_nth_data (GList_Subnet, i);
		Affiche_Subnet (Subnet);
	}
}


struct Struct_Subnet *Modifie_Ajouter_Subnet_Dans_Glist (void)
{
	struct Struct_Subnet *Subnet = NULL;

	if (Subnet_Modification == NULL) {
		MALLOC (Subnet, sizeof (struct Struct_Subnet));
	}
	else
		Subnet = Subnet_Modification;

	Subnet->Masque = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox_Network_Private_Subnet));
	Subnet->A = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_A));
	Subnet->B = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_B));
	Subnet->C = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_C));
	if (Subnet_Modification == NULL)
		G_LIST_APPEND (GList_Subnet, Subnet);
	return Subnet;	
}


void Modifie_Ajoute_Nouveau_Subnet (void)
{
	struct Struct_Subnet *Subnet = NULL;
	GtkTreeModel *model = NULL;
	gchar    *Masque = NULL, *IP = NULL;

	if (Subnet_Modification != NULL) {
		Modifie_Ajouter_Subnet_Dans_Glist ();
		model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview_Network_Private_Subnet));
		switch (Subnet_Modification->Masque) {
		    case 0:
			    Masque = g_strdup ("255.0.0.0");
			    break;
		    case 1:
			    Masque = g_strdup ("255.255.0.0");
			    break;
		    case 2:
			    Masque = g_strdup ("255.255.255.0");
			    break;
		    default:
			    Masque = g_strdup ("?.?.?.?");
		}
		IP = g_strdup_printf ("%d.%d.%d.0", Subnet_Modification->A, Subnet_Modification->B, Subnet_Modification->C);
		gtk_tree_store_set (GTK_TREE_STORE (model), &Subnet_Modification->ID_Arbre_Ligne, COL_MASQUE, Masque, COL_IP, IP, -1);
		MYFREE (Masque);
		MYFREE (IP);
		return;
	}
	else {
		Subnet = Modifie_Ajouter_Subnet_Dans_Glist ();
		Affiche_Subnet (Subnet);
		return;	
	}
}


static void Write_Subnet_to_xml (xmlNodePtr xmlnode, struct Struct_Subnet *Subnet)
{
	xmlNodePtr newxml = NULL;
	gchar     Subnet_Char[4];

	ERROR_if (xmlnode == NULL);
	ERROR_if (Subnet == NULL);
	newxml = xmlNewChild (xmlnode, NULL, "Subnet", NULL);
	sprintf (Subnet_Char, "%d", Subnet->Masque);
	xmlSetProp (newxml, "Mask", Subnet_Char);
	sprintf (Subnet_Char, "%d", Subnet->A);
	xmlSetProp (newxml, "Subnet_A", Subnet_Char);
	sprintf (Subnet_Char, "%d", Subnet->B);
	xmlSetProp (newxml, "Subnet_B", Subnet_Char);
	sprintf (Subnet_Char, "%d", Subnet->C);
	xmlSetProp (newxml, "Subnet_C", Subnet_Char);
}


static gboolean write_xml_file_Subnet (char *fname)
{
	struct Struct_Subnet *Subnet = NULL;
	xmlNode *root_element = NULL;
	xmlDocPtr doc = NULL;
	guint     Nb_Objet_Liste, i;

	ERROR_if (fname == NULL);




	doc = xmlNewDoc(BAD_CAST "1.0");
    root_element = xmlNewNode(NULL, BAD_CAST "Subnet_AutoScan");
    xmlDocSetRootElement(doc, root_element);
	
	xmlAddChild (root_element, xmlNewDocComment (doc, "Copyright (c) Lagarde thierry. \nThis Database is available for free use by open source software under the terms of the GNU General Public License.\nContact <tlagarde@users.sourceforge.net>  for more information"));
	/*doc->root = xmlNewDocNode (doc, NULL, "Subnet_AutoScan", NULL);
	xmlAddChild (doc->root, xmlNewDocComment (doc, "Copyright (c) Lagarde thierry. \nThis Database is available for free use by open source software under the terms of the GNU General Public License.\nContact <tlagarde@user.sourceforge.net>  for more information"));
	*/
	Nb_Objet_Liste = g_list_length (GList_Subnet);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Subnet = g_list_nth_data (GList_Subnet, i);
		Write_Subnet_to_xml (root_element, Subnet);
	}
	if (xmlSaveFile (fname, doc) == -1) {
		xmlFreeDoc (doc);
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "impossible d'enregistrer le fichier xml");
		return FALSE;
	}
	xmlFreeDoc (doc);
	debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Save Subnet (%d)", Nb_Objet_Liste);
	return TRUE;
}




void Enregistrement_Donnee_Xml_Subnet (void)
{
	gchar    *Chemin = NULL;

	Chemin = g_strdup_printf ("%s/.autoscan-network/config/Subnet.xml", Info_User->pw_dir);
	write_xml_file_Subnet (Chemin);
	MYFREE (Chemin);
}



void Lit_Donnee_Xml_Subnet (xmlNodePtr xmlnode)
{
	struct Struct_Subnet *Subnet = NULL;
	xmlChar  *chaine = NULL;

	ERROR_if (xmlnode == NULL);

	if (!xmlnode->name || g_strcasecmp (xmlnode->name, "Subnet") != 0)
		return;

	MALLOC (Subnet, sizeof (struct Struct_Subnet));

	chaine = xmlGetProp (xmlnode, "Mask");
	if (chaine) {
		if (sscanf (chaine, "%d", &Subnet->Masque) != 1)
			Subnet->Masque = 0;
		xmlFree (chaine);
		chaine = xmlGetProp (xmlnode, "Subnet_A");
		if (sscanf (chaine, "%d", &Subnet->A) != 1)
			Subnet->A = 0;
		xmlFree (chaine);
		chaine = xmlGetProp (xmlnode, "Subnet_B");
		if (sscanf (chaine, "%d", &Subnet->B) != 1)
			Subnet->B = 0;
		xmlFree (chaine);
		chaine = xmlGetProp (xmlnode, "Subnet_C");
		if (sscanf (chaine, "%d", &Subnet->C) != 1)
			Subnet->C = 0;
		xmlFree (chaine);
		G_LIST_APPEND (GList_Subnet, Subnet);
	}
	else {
		MYFREE (Subnet);
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Mask error");
		return;
	}
}


void Lit_Xml_Subnet (xmlDocPtr doc)
{
	xmlNodePtr node = NULL;
	xmlNode *root_element = NULL;
	
	ERROR_if (doc == NULL);
	root_element = xmlDocGetRootElement(doc);

	/*for (node = doc->root->childs; node != NULL; node = node->next) {
		Lit_Donnee_Xml_Subnet (node);
	}*/
	for (node = root_element->children; node != NULL; node = node->next) {
		if (node->type == XML_ELEMENT_NODE) 
			Lit_Donnee_Xml_Subnet (node);
	}
}


gboolean Lit_Xml_Subnet_Fichier (char *fname)
{
	xmlDocPtr doc = NULL;
	xmlNode *root_element = NULL;
	
	ERROR_if (fname == NULL);
	if (!g_file_test(fname,G_FILE_TEST_EXISTS))

		debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error loading file : [%s]", fname);

	doc = xmlParseFile (fname);
	if (!doc) {
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Fichier XML Subnet : [%s]", fname);
		return FALSE;
	}
	root_element = xmlDocGetRootElement(doc);

	/*if (!doc->root || !doc->root->name || g_strcasecmp (doc->root->name, "Subnet_AutoScan") != 0) {
		if (!doc->root)
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "l'element n'est pas root");
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Fichier XML Signature mal formaté : [%s]", fname);
		xmlFreeDoc (doc);
		return FALSE;
	}*/
	if (!root_element || !root_element->name || g_strcasecmp (root_element->name,  "Subnet_AutoScan") != 0) {
		if (!root_element)
			debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "l'element n'est pas root");
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Fichier XML Signature mal formaté : [%s]", fname);
		xmlFreeDoc (doc);
		return FALSE;
	}

	Lit_Xml_Subnet (doc);

	xmlFreeDoc (doc);
	return TRUE;
}


gint sort_func_Croissant_Subnet (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data)
{
	gchar    *name_a = NULL, *name_b = NULL;
	int       ret;

	gtk_tree_model_get (model, a, COL_MASQUE, &name_a, -1);
	gtk_tree_model_get (model, b, COL_MASQUE, &name_b, -1);
	ret = g_utf8_collate (name_a, name_b);
	MYFREE (name_a);
	MYFREE (name_b);
	return ret;
}

gboolean Selectionne_Subnet (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
{
	GtkTreeModel *model = NULL;
	struct Struct_Subnet *Subnet = NULL;
	GtkTreePath *path = NULL;
	GtkTreeIter iter;
	gint      x, y;

	if (event->type == GDK_BUTTON_PRESS) {
		GdkEventButton *bev = (GdkEventButton *) event;

		model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
		gdk_window_get_pointer (event->window, &x, &y, NULL);
		if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, &path, NULL, NULL, NULL)) {
			return FALSE;
		}
		gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
		gtk_tree_model_get (model, &iter, POINTER_SUBNET, &Subnet, -1);
		switch (bev->button) {
		    case 1:
			    Liste_Subnet_Modification_Interface = TRUE;
			    gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_Network_Private_Subnet), Subnet->Masque);
			    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_A), (gfloat) Subnet->A);
			    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_B), (gfloat) Subnet->B);
			    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_Network_Private_Subnet_C), (gfloat) Subnet->C);
			    Liste_Subnet_Modification_Interface = FALSE;
			    gtk_widget_set_sensitive (button_Network_Private_Subnet_OK, FALSE);
			    gtk_widget_set_sensitive (button_Network_Private_Subnet_Cancel, FALSE);
			    gtk_widget_set_sensitive (button_Network_Private_Subnet_Delete, TRUE);
			    gtk_widget_set_sensitive (button_Network_Private_Subnet_Add, TRUE);
			    gtk_widget_set_sensitive (combobox_Network_Private_Subnet, TRUE);
			    Subnet_Selectionner = Subnet;
			    break;
		    default:
			    debug_printf (INTERFACE, D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Pas d'actions pour cette combinaison  (%d)", bev->button);
		}
	}
	return FALSE;
}


void Create_Liste_Subnet (void)
{
	GtkTreeModel *model = NULL;
	GtkTreeViewColumn *col = NULL;
	GtkCellRenderer *texte = NULL;
	GtkTreeSelection *selection = NULL;
	GtkTreeStore *store = NULL;

	store = gtk_tree_store_new (NUM_COLS_SUBNET, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store), sort_func_Croissant_Subnet, NULL, NULL);
	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
	model = GTK_TREE_MODEL (store);

	treeview_Network_Private_Subnet = gtk_tree_view_new_with_model (model);
	gtk_widget_show (treeview_Network_Private_Subnet);
	g_object_unref (model);	
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview_Network_Private_Subnet), FALSE);
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_Network_Private_Subnet));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);

	col = gtk_tree_view_column_new ();
	texte = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (col, texte, FALSE);
	gtk_tree_view_column_set_attributes (col, texte, "text", COL_MASQUE, NULL);
	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_Network_Private_Subnet), col);

	col = gtk_tree_view_column_new ();
	texte = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (col, texte, FALSE);
	gtk_tree_view_column_set_attributes (col, texte, "text", COL_IP, NULL);
	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_Network_Private_Subnet), col);

	g_signal_connect ((gpointer) treeview_Network_Private_Subnet, "button-press-event", G_CALLBACK (Selectionne_Subnet), treeview_Network_Private_Subnet);
}


void Initialisation_Subnet (void)
{
	GList_Subnet = NULL;
	Liste_Subnet_Modification_Interface = FALSE;
	Subnet_Modification = NULL;
	Subnet_Selectionner = NULL;
}
