/************************************************************
esListePlaylistImplementataMedianteClasse.cpp

Implementare il servizio di playlist (aggiungi, elimina, cerca, stampa,...)
mediante classe invece che mediante struttura & funzioni globali.

Dotare la classe di distruttore, costruttore di copia 
ed operatore di assegnamento.



Utilizzare il seguente main per testare la classe

int main() {

   cout<<"Test costruttore senza parametri e funzione di stampa"<<endl;
   Playlist i1;	
   i1.stampa();

   cout<<"Test della aggiungi(...)" <<endl;
   i1.aggiungi("titolo1 (autore1)");
   i1.aggiungi("titolo2 (autore1)");
   i1.aggiungi("titolo3 (autore2)");
   i1.aggiungi("titolo2 (autore1)"); //non viene aggiunto perche' gia' presente
   i1.stampa();
   
   cout<<"Test della elimina(...)" <<endl;
   i1.elimina("titolo2 (autore1)");
   i1.elimina("titolo8 (autore1)"); //non viene rimosso perche' non presente
   i1.stampa();

   
   cout<<"Test della cerca(...)" <<endl;
   cout<<i1.cerca("titolo3 (autore2)")<<endl; //visualizza 1
   cout<<i1.cerca("titolo5 (autore1)")<<endl; //visualizza 0
   
   { 
      cout<<endl<<"Test costruttore di copia" << endl;
      Playlist i2(i1);
	  i2.stampa();
	  
	  cout<<"Test del distruttore (sta per essere chiamato in automatico sulla istanza i2)" << endl;
   }
   
   Playlist i3;
   i3.aggiungi("titolo4 (autore3)");         
   
   cout<<endl<<"Test operatore di assegnamento"<<endl;
   i3 = i1;
   i3.stampa();
   
   return 0;
}

********************************************************/



// ----------------------------------------------------------------------------
//                  MODULO SERVITORE - INTERFACCIA
// ( questa parte va messa dentro un file denominato ad esempio "Playlist.h" )
// ----------------------------------------------------------------------------
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <cstring>
using namespace std;

struct elem{
   char titolo[64];  
   elem* pun;
};

class Playlist{
   elem* p0;
   // funzioni di utilita'
   void dealloca();
   void copia(const Playlist&);
public:
   Playlist(){ p0 = NULL; };
   void stampa();
   bool aggiungi( const char* );
   bool elimina( const char* );
   bool cerca( const char* ); 
   Playlist(const Playlist& dx) {copia(dx);}; // costruttore di copia   
   Playlist& operator=(const Playlist&); // costruttore di copia   
   ~Playlist(){dealloca();};	
};



// -----------------------------------------------------------------------------------
//                        MODULO SERVITORE - IMPLEMENTAZIONE
// ( questa parte andrebbe messa dentro un file denominato ad esempio "Playlist.cpp" )
// -----------------------------------------------------------------------------------


void Playlist::stampa() {
   elem* p = p0;
   cout<<"Album della playlist:"<<endl;
   while( p!= 0 ) {
      cout<<p->titolo<<endl;
      p = p->pun;
   }
   cout<<endl;
}

bool Playlist::aggiungi(const char* alb) {

   elem* p = p0;

   // scorro la lista per verificare se l'album era gia' presente
   while( p != 0 ){
      if( strcmp(p->titolo,alb) == 0 ) // se l'album e' gia presente, non lo inserisco, 
         return false;                 // in modo da non creare duplicati
      p = p->pun;
   }

   //inserimento in testa
   p = p0;
   p0 = new elem;
   strcpy(p0->titolo, alb);
   p0->pun = p;
   return true;
}



bool Playlist::elimina(const char* alb) {
   elem* p = p0;
   elem* q = p;
   while( q != 0 && strcmp(q->titolo,alb) != 0 ) {
      p = q;
      q = q->pun;
   }
   if ( q!= 0 ) {
      if( q == p0 )
         p0 = p0->pun;					
      else
         p->pun = q->pun;		
	  delete q;
      return true;
   }
   return false;
}

bool Playlist::cerca(const char* alb) {
   elem* p = p0;
   while( p != 0 ) {
      if( strcmp(p->titolo, alb) == 0)
		  return true;
      p = p->pun;
   }
   return false;
}

void Playlist::dealloca() {   
   elem* p = p0;
   while( p != NULL ) {
      elem* q = p;
	  p = p->pun;
	  delete q;
   }
}

void Playlist::copia(const Playlist &dx){
   if ( dx.p0 == NULL){
       p0 = NULL;
	   return;
   }
   
   elem* r = dx.p0;  // r è il puntatore che uso per scorrere gli elementi 
                     // della lista dell'oggetto di destra
   
   p0 = new elem;
   strcpy(p0->titolo, r->titolo);
   
   elem *p = p0;  // p e' il puntatore all'oggetto precedente nella lista associata all'oggetto di sinistra
   
   elem* q;       // q e' il puntatore all'oggetto corrente nella lista associata 
	              // all'oggetto di sinistra (q va di pari passo con r, anche se puntato a liste diverse)
   r = r->pun;
   
   while( r != NULL ) {
      q = new elem;						 
	  strcpy(q->titolo, r->titolo);	  
	  p->pun = q;
	  p = q;
	  r = r->pun;
   }
   
   q->pun = NULL;
}

Playlist& Playlist::operator=(const Playlist &dx){
	if (this != &dx){
		dealloca();
		copia(dx);
	}
	return *this;
}




// -----------------------------------------------------------------------------------
//                                   MODULO CLIENTE
//                          (va messa dentro al file "main.cpp" )
// -----------------------------------------------------------------------------------


// #include "Playlist.h"  // Togliere il commento a questa riga, 
// nel caso si usino più file (Playlist.h, Playlist.cpp e main.cpp)

int main() {

   cout<<"Test costruttore senza parametri e funzione di stampa"<<endl;
   Playlist i1;	
   i1.stampa();

   cout<<"Test della aggiungi(...)" <<endl;
   i1.aggiungi("titolo1 (autore1)");
   i1.aggiungi("titolo2 (autore1)");
   i1.aggiungi("titolo3 (autore2)");
   i1.aggiungi("titolo2 (autore1)"); //non viene aggiunto perche' gia' presente
   i1.stampa();
   
   cout<<"Test della elimina(...)" <<endl;
   i1.elimina("titolo2 (autore1)");
   i1.elimina("titolo8 (autore1)"); //non viene rimosso perche' non presente
   i1.stampa();

   
   cout<<"Test della cerca(...)" <<endl;
   cout<<i1.cerca("titolo3 (autore2)")<<endl; //visualizza 1
   cout<<i1.cerca("titolo5 (autore1)")<<endl; //visualizza 0
   
   { 
      cout<<endl<<"Test costruttore di copia" << endl;
      Playlist i2(i1);
	  i2.stampa();
	  
	  cout<<"Test del distruttore (sta per essere chiamato in automatico sulla istanza i2)" << endl;
   }
   
   Playlist i3;
   i3.aggiungi("titolo4 (autore3)");         
   
   cout<<endl<<"Test operatore di assegnamento"<<endl;
   i3 = i1;
   i3.stampa();
   
   return 0;
}