#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
#include "lista.h"

// initializeaza o lista noua
LISTA newl() {
	// returneaza NULL, corespunzator unei liste vide
	return NULL;
}

// insereaza un element nou la inceputul listei l
// valoarea inserata este info
LISTA ins_in_fata(LISTA l,DATA info) {
	// se aloca memorie pentru un nou element
	LISTA p=(LISTA)malloc(sizeof(Lista));
	// daca alocarea a reusit
	if(p!=NULL) {
		p->info=info; // se completeaza campul de informatie
		p->urm=l;	  // se completeaza campul de adresa
		return p;	  // se returneaza noua adresa a listei
		}
	// daca alocarea nu a reusit lista ramane nemodificata
	return l;
}

// sterge primul element al listei l
LISTA sterge_prim(LISTA l) {
	// daca lista nu este vida
	if(l!=NULL) {
		LISTA p=l->urm;	// se obtine noua adresa a listei
		free(l);		// se elibereaza spatiul ocupat de primul element
		return p;		// se returneaza noua adresa a listei
	}
	// daca lista este vida, ea ramane nemodificata
	return l;
}

// insereaza un element nou la sfarsitul listei l
// valoarea inserata este info
LISTA ins_la_sfarsit(LISTA l,DATA info) {
	// daca lista este vida, atunci inserarea la sfarsit
	// este identica cu inserarea la inceput
	if (l==NULL)
		return ins_in_fata(l,info);
	// in aux se pastreaza adresa initiala a listei
	LISTA aux = l;
	// se aloca memorie pentru un nou element
	LISTA p=(LISTA)malloc(sizeof(Lista));
	// daca alocarea a reusit
	if(p!=NULL) {
		p->info=info; // se completeaza campul de informatie
		p->urm=NULL;  // se completeaza campul de adresa (va fi ultimul element)
		// se parcurge lista pana ajungem la ultimul element
		while (l->urm!=NULL)
			l=l->urm;
		// conectam fostul ultim element cu elementul de la adresa p
		l->urm = p;
	}
	return aux;	  // se returneaza vechea adresa a listei
}

// sterge ultimul element al listei l
LISTA sterge_ultimul(LISTA l) {
	// daca lista este vida nu avem ce sterge
	if (l==NULL)
		return l;
	// daca lista are un singur element, stergerea ultimului
	// este identica cu stergerea primului element
	if (l->urm==NULL)
		return sterge_prim(l);
	// pastram adresa initiala a listei
	LISTA aux = l;
	// daca lista contine mai mult de un element
	// parcurgem lista pana la sfarsitul ei
	while (l->urm->urm!=NULL)
		l=l->urm;
	//eliberam ultimul element
	free (l->urm);
	// punem NULL pe urm la elementul care a devenit ultimul
	l->urm=NULL;
	return aux;
}

// afiseaza lista l
void afiseaza_lista (LISTA l)	{
	// daca lista este vida
	if(l==NULL)
		printf("\n Lista este vida.");
	// daca lista contine elemente
	else {
		// se parcurg toate elementele pana la sfarsitul listei si se afiseaza
		while(l!=NULL) {
			printf(FORMAT" ",l->info);
			l=l->urm;
		}
	}
}
// converteste lista la sir de caractere
char * toStringl (LISTA l, char * zona){
	char buf[20];
	LISTA p;
	// reprezentarea listei va incepe cu acolada deschisa
	strcpy (zona, "{");
	// daca lista este vida, se concateneaza sirul "este vida}"
	if (este_vida(l))
		strcat (zona,"este vida}");
	// altfel, se adauga la reprezentare fiecare element urmat de virgula sau acolada inchisa (ultimul element)
	else
		for (p=l;p!=NULL;p=p->urm){
			// se scrie in memorie, in variabila buf, reprezentarea textuala a unui element, urmat de virgula sau acolada inchisa
			sprintf (buf,FORMAT"%c",p->info, p->urm==NULL?'}':',');
			// se concateneaza reprezentarea elementului la reprezentarea listei
			strcat (zona,buf);
		}
	// se returneaza reprezentarea textuala completa a listei
	return zona;
}

// returneaza ADEVARAT daca lista este vida si FALS in caz contrar
LOGIC este_vida(LISTA l) {
	if(l==NULL)
		return ADEVARAT;
	else
		return FALS;
}

// returneaza ADEVARAT daca nu mai este memorie libera (lista este plina) si FALS in caz contrar
LOGIC este_plina(LISTA l) {
	// se incearca alocarea memorie pentru un nou element
	LISTA p = (LISTA)malloc(sizeof(Lista));
	// daca alocarea nu reuseste atunci inseamna ca nu mai exista memorie disponibila deci lista este plina
	if (p==NULL)
		return ADEVARAT;
	// in caz contrar, se elibereaza elementul alocat si se returneaza FALS (lista nu este plina)
	free (p);
	return FALS;
}

// elibereaza spatiul ocupat de lista
void destroyl(LISTA l) {
	// daca lista nu este vida
	if(l!=NULL) {
		// se parcurg toate elementele si se elibereaza spatiul ocupat de ele
		while(l!=NULL) {
			LISTA p=l;
			l=l->urm;
			free(p);
		}
	}
}


