/* ***********************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 "Notification_Equipement.h"
#include "Debug.h"
#include "Scan_Arp.h"
#include "Semaphore.h"
#include "Com/Initialisation_Com.h"
#include "Com/Commun.h"
#include "Thread.h"
#include "Macro.h"

void Thread_Notification_Equipement (void)
{
	struct Struct_Liste_Equipement *Equipement = NULL;
	struct Struct_Liste_Notification_Equipement *Notification_Equipement = NULL;
	struct struct_Retour_Notification_Changement_Etat_Equipement Message;
	gint      Nb_Objet_Liste, i;

#ifdef __LOG_ENABLE
	Create_Log(CATEG_THREAD_NOTIF_EQU,NULL,NULL,TRUE);
#endif
	while (TRUE) {
		i = 0;
		Nb_Objet_Liste = g_list_length (GList_Notification_Equipement);
		while (i < Nb_Objet_Liste) {
		
			PROTECT_CODE (Semaphore_Notification_Equipement);
			Nb_Objet_Liste = g_list_length (GList_Notification_Equipement);
			if (i < Nb_Objet_Liste) {
				Notification_Equipement = g_list_nth_data (GList_Notification_Equipement, i);
				Equipement = Notification_Equipement->Equipement;
				if ((!Equipement->Rafraichissement_Etat_En_Cours) && (Equipement->ID_Equipement[6] != 0)) {
					if (Equipement->Compteur_Notification < TEMP_NOTIFICATION_EQUIPEMENT_CRITIQUE) {
						if (Equipement->Compteur_Notification >= TEMP_NOTIFICATION_EQUIPEMENT_CRITIQUE / 2)
							Envoie_Arp_Equipement (Equipement, 1);
						Equipement->Compteur_Notification++;
					}
					if (Equipement->Compteur_Notification == TEMP_NOTIFICATION_EQUIPEMENT_CRITIQUE) {
						Equipement->Compteur_Notification = 0;
						Equipement->Equipement_Allumer = FALSE;
						if (!Equipement->Alerte_Equipement_Active) {
							bzero (&Message, sizeof (struct struct_Retour_Notification_Changement_Etat_Equipement));
							Message.ID_Reseau = Info_Demarrage.ID_Reseau;
							memcpy (Message.ID_Equipement, Equipement->ID_Equipement, MAC_ADDR_LEN + IP_ADDR_LEN + 1);
							Communication_Envoie_Donnee (RETOUR_NOTIFICATION_CHANGEMENT_ETAT_EQUIPEMENT, (gpointer *) & Message, sizeof (Message));
						}
						Equipement->Alerte_Equipement_Active = TRUE;
					}
				}
			}
			DEPROTECT_CODE (Semaphore_Notification_Equipement);
			i++;
		}
		sleep (1);
	}
}


void Thread_Rafraichir_Tout_Equipement (void)
{
	struct Struct_Liste_Equipement *Equipement = NULL;
	struct struct_Retour_Rachaichir_Etat_Equipement Message;
	gboolean  Sauve_Etat;
	gint      i,Timeout;

#ifdef __LOG_ENABLE
	Create_Log(CATEG_RAFFRAICHIR_EQU,NULL,NULL,TRUE);
#endif
	sleep (600);	
	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Start");
	while (1) {
		i = 0;
		Retour_Pointeur_Equipement (&Equipement,i);
		while (Equipement != NULL) {
			if ((!Equipement->Agent_AutoScan) && (!Equipement->Notification_Equipement) && (!Equipement->Rafraichissement_Etat_En_Cours)) {
				Sauve_Etat = Equipement->Equipement_Allumer;
				Equipement->Compteur_Notification = 0;
				Equipement->Equipement_Allumer = FALSE;
				Equipement->Rafraichissement_Etat_En_Cours = TRUE;
			
				Timeout = 5;
				while ((Timeout!=0) && (!Equipement->Equipement_Allumer)){
				
					Envoie_Arp_Equipement (Equipement, 2);
				
					Ping_equipement(Equipement);
					sleep (1);
					Timeout--;
				}
				Equipement->Rafraichissement_Etat_En_Cours = FALSE;
				if (Sauve_Etat != Equipement->Equipement_Allumer) {
					bzero (&Message, sizeof (struct struct_Retour_Rachaichir_Etat_Equipement));
					Message.ID_Reseau = Info_Demarrage.ID_Reseau;
					memcpy (Message.ID_Equipement, Equipement->ID_Equipement, MAC_ADDR_LEN + IP_ADDR_LEN + 1);
					Message.Equipement_Allumer = Equipement->Equipement_Allumer;
					Message.Derniere_Modification_Etat_Equipement = Equipement->Derniere_Modification_Etat_Equipement;
					Communication_Envoie_Donnee (RETOUR_RAFRAICHIR_ETAT_EQUIMEMENT, (gpointer *) & Message, sizeof (Message));
				}
			}
			i++;
			sleep (1);
			Retour_Pointeur_Equipement (&Equipement,i);
		}
		sleep (600);
	}
}

void Thread_Rafraichir_Etat_Equipement (struct Struct_Liste_Equipement *Equipement)
{
	struct struct_Retour_Rachaichir_Etat_Equipement Message;
	gboolean  Sauve_Etat;
	gint	Timeout;
	
#ifdef __LOG_ENABLE
	Create_Log(CATEG_THREAD_ETAT_EQUIPEMENT,NULL,NULL,TRUE);
#endif
	ERROR_if (Equipement == NULL);
	Sauve_Etat = Equipement->Equipement_Allumer;
	Equipement->Compteur_Notification = 0;
	Equipement->Equipement_Allumer = FALSE;
	Equipement->Rafraichissement_Etat_En_Cours = TRUE;

	Timeout = 5;
	while ((Timeout!=0) && (!Equipement->Equipement_Allumer)){
	
		Envoie_Arp_Equipement (Equipement, 2);
	
		Ping_equipement(Equipement);
		sleep (1);
		Timeout--;
	}
	Equipement->Rafraichissement_Etat_En_Cours = FALSE;

	if (Sauve_Etat != Equipement->Equipement_Allumer) {	
		bzero (&Message, sizeof (struct struct_Retour_Rachaichir_Etat_Equipement));
		Message.ID_Reseau = Info_Demarrage.ID_Reseau;
		memcpy (Message.ID_Equipement, Equipement->ID_Equipement, MAC_ADDR_LEN + IP_ADDR_LEN + 1);
		Message.Equipement_Allumer = Equipement->Equipement_Allumer;
		Message.Derniere_Modification_Etat_Equipement = Equipement->Derniere_Modification_Etat_Equipement;
		Communication_Envoie_Donnee (RETOUR_RAFRAICHIR_ETAT_EQUIMEMENT, (gpointer *) & Message, sizeof (Message));
	}
	Stop_Thread (NULL);
}

void Rafraichir_Etat_Equipement (gpointer * Donnee)
{
	struct struct_Demande_Rachaichir_Etat_Equipement *Message = (struct struct_Demande_Rachaichir_Etat_Equipement *) Donnee;
	struct Struct_Liste_Equipement *Equipement = NULL;
	gint      ID_Equipement;

	ERROR_if (Donnee == NULL);
	Recherche_Index_Equipement (Message->ID_Equipement, TRUE, &ID_Equipement);
	if (ID_Equipement == EQUIPEMENT_UNKNOWN) {
		debug_printf (D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Refresh state (Equipment unknown)");
		return;	
	}
	if (ID_Equipement == EQUIPEMENT_NO_IP) {
		debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Refresh state (no IP)");
		return;	
	}
	Retour_Pointeur_Equipement (&Equipement,ID_Equipement);

	if (!Equipement->Notification_Equipement)
		demmarrage_Thread (&Thread_Rafraichir_Etat_Equipement, (gpointer *) Equipement); 
}


void Ajout_Notification_Equipement (gpointer * Donnee)
{
	struct struct_Demande_Notication_Critique_Etat_Equipement *Message = (struct struct_Demande_Notication_Critique_Etat_Equipement *) Donnee;
	struct Struct_Liste_Equipement *Equipement = NULL;
	gint      ID_Equipement;

	ERROR_if (Donnee == NULL);
	Recherche_Index_Equipement (Message->ID_Equipement, FALSE, &ID_Equipement);
	if (ID_Equipement == EQUIPEMENT_UNKNOWN) {
		debug_printf (D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Add Notification (Equipment unknown)");
		return;	
	}
	/*if (ID_Equipement == EQUIPEMENT_NO_IP) {
	 * debug_printf (D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Add (no IP)");
	 * return;
	 * } */
	Retour_Pointeur_Equipement (&Equipement,ID_Equipement);
	Equipement->Alerte_Equipement_Active = FALSE;
	Ajout_Notification_Equipement_Glist (Equipement);
}

void Enlever_Notification_Equipement (gpointer * Donnee)
{
	struct struct_Annulation_Notification_Etat_Equipement *Message = (struct struct_Annulation_Notification_Etat_Equipement *) Donnee;
	struct Struct_Liste_Equipement *Equipement = NULL;
	gint      ID_Equipement;

	
	ERROR_if (Donnee == NULL);
	Recherche_Index_Equipement (Message->ID_Equipement, TRUE, &ID_Equipement);
	if (ID_Equipement == EQUIPEMENT_UNKNOWN) {
		debug_printf (D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Delete Notification (Equipment unknown)");
		return;	
	}
	if (ID_Equipement == EQUIPEMENT_NO_IP) {
		debug_printf (D_WARN_USER, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Delete Notification (no IP)");
		return;	
	}
	Retour_Pointeur_Equipement (&Equipement,ID_Equipement);
	Enlever_Notification_Equipement_Glist (Equipement);

}

void Affiche_Debug_Liste_Notification_Equipement_Securiser (void)
{
	PROTECT_CODE(Semaphore_Notification_Equipement);
	struct Struct_Liste_Notification_Equipement *Notification_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "************* Afficher liste notification equipement");
	Nb_Objet_Liste = g_list_length (GList_Notification_Equipement);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Notification_Equipement = g_list_nth_data (GList_Notification_Equipement, i);
		debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Notification Equipement : %s [%s]", Notification_Equipement->Equipement->Adresse_Ip_Char, Notification_Equipement->Equipement->Adresse_MAC_Char);
	}
	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "************* fin");
	DEPROTECT_CODE(Semaphore_Notification_Equipement);
}

struct Struct_Liste_Equipement *Recupere_Pointeur_Notification_Equipement_Dans_Une_Liste (int rang)
{
	return g_list_nth_data (GList_Notification_Equipement, rang);
}

gint Recherche_Index_Notification_Equipement_Non_Securiser (struct Struct_Liste_Equipement * Equipement)
{			
	struct Struct_Liste_Notification_Equipement *Notification_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	Nb_Objet_Liste = g_list_length (GList_Notification_Equipement);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Notification_Equipement = g_list_nth_data (GList_Notification_Equipement, i);
		if (Notification_Equipement->Equipement == Equipement)
			return i;
	}
	return -1;	
}

void Enlever_Notification_Equipement_Glist (struct Struct_Liste_Equipement *Equipement)
{
	ERROR_if (Equipement == NULL);
	PROTECT_CODE(Semaphore_Notification_Equipement);
	gint      ID_Equipement;
	
	Equipement->Notification_Equipement = FALSE;
	if ((ID_Equipement = Recherche_Index_Notification_Equipement_Non_Securiser (Equipement)) != -1)
		G_LIST_REMOVE(GList_Notification_Equipement, Recupere_Pointeur_Notification_Equipement_Dans_Une_Liste (ID_Equipement));
	else
		debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Enlever Notification Equipement n'existe pas: [%s]", Equipement->Adresse_MAC_Char);
	DEPROTECT_CODE(Semaphore_Notification_Equipement);
	Affiche_Debug_Liste_Notification_Equipement_Securiser ();
}


void Ajout_Notification_Equipement_Glist (struct Struct_Liste_Equipement *Equipement)
{
	ERROR_if (Equipement == NULL);
	PROTECT_CODE(Semaphore_Notification_Equipement);// Permet de securiser la suppression (ex si le thread de notification d'equipement est en train de lire la liste des notifications et quand meme temps on enleve un equipement dans cette liste il y aurait une erreur de segmentation)
	struct Struct_Liste_Notification_Equipement *Notification_Equipement = NULL;

	Equipement->Notification_Equipement = TRUE;
	if (Recherche_Index_Notification_Equipement_Non_Securiser (Equipement) == -1) {
		MALLOC(Notification_Equipement,sizeof (struct Struct_Liste_Notification_Equipement));
		Notification_Equipement->Equipement = Equipement;
		Equipement->Compteur_Notification = 0;
		G_LIST_APPEND (GList_Notification_Equipement, Notification_Equipement);
	}
	else
		debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Nouveau Notification Equipement existe deja: [%s]", Equipement->Adresse_MAC_Char);
	DEPROTECT_CODE(Semaphore_Notification_Equipement);
	Affiche_Debug_Liste_Notification_Equipement_Securiser ();
}


void Initialisation_Notification_Equipement (void)
{
	GList_Notification_Equipement = NULL;
}
