#ifndef LISTE_H
#define LISTE_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <string.h>
template <class T>
class Cellule
{
public:
	T _valeur ;
	Cellule *_suivant ;
	Cellule() ;
	Cellule( const T &valeur ) ;
	~Cellule() ;
	//Accesseur
	T getValeur() ;
	Cellule<T> *getSuivant() ;
	//Modificateur
	void setSuivant( Cellule<T> * cellSuivante ) ;
	void supprSuivant() ;
};
template <class T>
Cellule<T>::Cellule()
{
	_suivant = NULL ;
}
template <class T>
Cellule<T>::Cellule( const T &valeur )
{
	_valeur = valeur ;
	_suivant = NULL ;
}
template <class T>
Cellule<T>::~Cellule()
{
	if( _suivant != NULL )
	{
		_suivant->~Cellule() ;
	}
	free( _suivant ) ;
}
template <class T>
T Cellule<T>::getValeur()
{
	return( _valeur ) ;
}
template <class T>
Cellule<T> *Cellule<T>::getSuivant()
{
	return( _suivant );
}
template <class T>
void Cellule<T>::setSuivant( Cellule<T> * cellSuivante )
{
	if( cellSuivante == NULL )
	{
		_suivant=NULL ;
	}
	else
	{
		_suivant = new Cellule ;
		*_suivant = *cellSuivante ;
	}
}
template <class T>
void Cellule<T>::supprSuivant()
{
	_suivant->~Cellule() ;
	free( _suivant ) ;
}
//------------------------------------------
template <class T>
class Liste
{
public:
	Cellule<T> **_debut ;
	int _nbElement ;
	Liste() ;
	Liste( const T &element ) ;
	Liste( const Liste &uneListe ) ;
	~Liste() ;
	//Accesseurs
	int getNbElements () ;
	T * operator []( int position );
	void insertionPosition( int position, const T &element ) ;
	
	//Modificateur
	void insererElementA( int position, const T &element ) ;
	int *rechercherElement( const T &element ) ;
	//Lecture / ecriture dans les fichiers
	int ecriture( char *chemin_fichier );
	int lecture( char *chemin_fichier );
private :
	T * getElement( int position );
};
template <class T>
Liste<T>::Liste()
{
	_debut=NULL ;
}
template <class T>
Liste<T>::Liste( const T &element )
{
	_debut = new Cellule<T>(element) ;
}
template <class T>
Liste<T>::Liste( const Liste &uneListe )
{
	Cellule<T> *courant ;
	int i ;
	if ( uneListe._debut != NULL )
	{
		_debut = new Cellule<T>( uneListe._debut->getValeur() ) ;
		_debut.setSuivant( uneListe_debut->getSuivant() ) ;
		courant = uneListe._debut->getSuivant() ;
		i = 1 ;
		while ( courant != NULL )
		{
			this->insererElementA ( ++ i, courant._debut->getValeur() ) 			
			courant = courant->getSuivant() ;
		}
	}
	else
	{
		_debut = NULL ;
	}
}
template <class T>
Liste<T>::~Liste()
{
	if( _debut!=NULL )
	{
		_debut->~Cellule() ;
	}
	free( _debut ) ;
}
template <class T>
T * Liste<T>::operator []( int position )
{
	int i ;
	Cellule<T> *courant ;
	T *element ;
	
	i = 1 ;
	courant = *_debut ;
	element = NULL ;
	if( position > 0 )
	{
		while( courant != NULL && i<position )
		{
			courant = courant->getSuivant() ;
			i ++ ;
		}
		if(courant!=NULL)
		{
			element = new T ;
			*element = courant->getValeur() ;
		}
		else
		{
			printf( "erreur" ) ;
		}
	}
	else
	{
		
*element = *_debut->getValeur() ;
	}
	return( element ) ;	
}
template <class T>
T *Liste<T>::getElement( int position )
{
	int i ;
	Cellule<T> *courant ;
	T *element ;
	
	i = 1 ;
	courant = _debut ;
	element = NULL ;
	if( position > 0 )
	{
		while( courant != NULL && i<position)
		{
			courant = courant->getSuivant() ;
			i++ ;
		}
		if(courant!=NULL)
		{
			element = new T ;
			*element = courant->getValeur() ;
		}
		else
		{
			printf("erreur") ;
		}
	}
	else
	{
		*element = _debut->getValeur() ;
	}
	return( element ) ;	
}
template <class T>
void Liste<T>::insererElementA( int position, const T &element )
{
	int i ;
	Cellule<T> nouvelElement( element ), *courant ;
	if( position==0 )
	{
		if( getNbElements()!=0 )
		{
			nouvelElement.setSuivant( *_debut ) ;
		}
		else
		{
			nouvelElement.setSuivant( NULL ) ;
		}
		*_debut = new Cellule<T> ;
		*_debut = &nouvelElement ;
	}
	else if( position > 0 )
	{
		if( position >= ( getNbElements() ) ) //Insertion à la fin
		{
			courant = *_debut ;
			while( courant->getSuivant() != NULL )
			{
				courant = courant->getSuivant() ;
			}
			if( courant->getSuivant() == NULL )
			{
				courant->setSuivant( &nouvelElement ) ;
			}
			else
			{
				printf( "erreur : Insertion à la fin \n" ) ;
			}
		}
		else //insertion dans la liste
		{
			courant = *_debut ;
			i = 0 ;
			while( courant->getSuivant() != NULL && i != position )
			{
				courant = courant->getSuivant() ;
			}
			if( courant->getSuivant() != NULL && i == position )
			{
				nouvelElement.setSuivant( courant->getSuivant() );
				courant->setSuivant( &nouvelElement ) ;
			}
			else
			{
				printf( "erreur : insertion dans la liste\n" ) ;
			}
		}
	}
}
template <class T>
int Liste<T>:: getNbElements ()
{
	Cellule<T> *courant ;
	courant = *_debut ;
	int i =0 ;
	while ( courant != NULL )
	{
		courant = courant->getSuivant() ;
		i ++ ;
	}
	return i ;
}
template <class T>
int *Liste<T>::rechercherElement( const T &element )
{
	int *position, n, i ;
	
	position = NULL ;
	i = 1 ;
	
	n = getNbElements();
	
	while( position == NULL && i <= n )
	{
		if( *getElement( i ) == element )
		{
			position = new int ;
			*position = i ;
		}
		i ++ ;
	}
	return( position ) ;
}
template <class T>
int Liste<T>::ecriture( char *chemin_fichier )
{
	FILE *fichier ;
    int ecriture = 0 ;
	Cellule<T> *courant = *_debut ;
	fichier = fopen( chemin_fichier, "wb" ) ;
    if ( fichier == NULL )
    {
		printf( "Erreur sur ouverture en ecriture du fichier binaire : %s", chemin_fichier ) ;
        //exit(-1);
    }
	else
	{
		while(courant != NULL)
		{
			fwrite( courant, sizeof( Cellule<T> ), 1, fichier ) ;
			courant = courant->getSuivant() ;
		}
		ecriture = 1 ;
	}
	return ecriture ;
}
template <class T>
int Liste<T>::lecture( char * chemin_fichier )
{
	FILE *fichier ;
    int lecture = 0 ;
	int premierMaillon = 0 ;
	Cellule<T> *courant ;
	Cellule<T> *precedent, *nouveau = NULL ;
	//Cellule<T> **leDebut ;
	precedent = NULL ;//_debut;
	fichier = fopen(chemin_fichier, "rb") ;
    if (fichier == NULL)
    {
		printf("Erreur sur ouverture en lecture du fichier binaire : %s\n", chemin_fichier);
		//printf("La reinstallation du programme est necessaire!!!");
        //exit(-1);
    }
	else
	{
		nouveau = new Cellule<T> ;
		while( fread( nouveau, sizeof( Cellule<T>), 1, fichier ) )
		{
			if ( premierMaillon == 0 )
			{
				premierMaillon = 1 ;
				_debut = &nouveau ;
			}
			else
			{
				courant->setSuivant( nouveau ) ;
			}
			courant = nouveau ;
			nouveau->setSuivant( NULL ) ;
			nouveau = new Cellule<T> ;
		}
		lecture = 1;
	}
    fclose( fichier ) ;
	return lecture ;
}
#endif
			
		
 
	
Partager