/*
 * main.cpp
 *
 *  Created on: 15. stu 2014.
 *  Author: Karlo Grlic
 */

/*
 * U programskom jeziku C++ napišite program koji će evidentirati računalne igre prema žanru. Zapis treba sadržavati sljedeće podatke: šifra , naziv igre, proizvođač, žanr i PEGI oznaku (3, 7, 12, 16, 18).
 * Testna verzija programa mora imati minimalno tri različita žanra , barem dva različita podžanra unutar pojedinog žanra , te najmanje tri različite računalne igre evidentirane unutar pojedinog podžanra.
 * Program treba raditi neovisno o implementaciji liste.
 * 	a. Napišite funkciju koja će korisniku omogućiti unos podataka o računalnoj igri. Funkcija treba nasumično generirati šifru od alfanumeričkih znakova te istu pridružiti računalnoj igri prilikom njenog unosa u evidenciju. Ako je zapis uspješno dodan, funkcija za dodavanje zapisa vraća 1 dok u slučaju neuspjeha vraća 0 .
 * 	b. Napišite funkciju koja će primjenom algoritma sortiranja spajanjem (merge sort) uzlazno sortirati računalne igre prema šifri te potom ispisati šifru, naziv, žanr i PEGI oznaku za sve evidentirane računalne igre .
 * 	c. Napišite funkciju koja će nakon primjene binarnog pretraživanja , ispisati sve strateške računalne igre i njihov ukupan broj .
 * 	d. Napišite funkciju koja će brisati pojedinačne unose prema šifri te funkciju koja će obrisati sve računalne igre određene PEGI oznake. Obje funkcije vraća ju 1 ako je zapis uspješno izbrisan, a 0 u slučaju neuspjeha.
 */

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime> //za rand()

#include "lista_polje.h"

using namespace std;

char* funk_generator_sifri(){
	char s[10];
    static const char alfanum[] =
        "01234567890123456789"
        "abcdefghijklmnoprstuvz";

    for (int i = 0; i < 10; ++i) {
        s[i] = alfanum[rand() % (sizeof(alfanum) - 1)];
    }
    s[10] = 0;//null terminirani string
    return s;
}//Prema http://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c

void funk_unos_testnih_podataka(st_IGRA &igra, st_LISTA &lista){
	const char* nazivi_igara[]={"StarCraft II: Legacy of the Void","Anno 2070","Command & Conquer 4: Tiberian Twilight","Total War: Rome II","March of the Eagles","Supreme Ruler: Cold War","Far Cry 4","Wolfenstein: The New Order","Titanfall","SpongeBob SquarePants: Plankton's Robotic Revenge","Lost Planet 3","Dead Space 3","NBA 2K","NBA Give 'n Go","NBA in the Zone","FIFA Street 3","Pro Evolution Soccer 2015","Football Manager"};
	const char* proizvodjaci[]={"Blizzard","Ubisoft","EA","The Creative Assembly","Paradox","BattleGoat Studios","Ubisoft Montreal","MachineGames","Respawn Entertainment","Behaviour Interactive","Capcom","Visceral Games","2K","Konami","Konami","EA Sports BIG","PES Productions","Addictive Games"};
	const char* zanrevi[]={"real-time strategy","real-time strategy","real-time strategy","grand strategy","grand strategy","grand strategy","first-person shooters","first-person shooters","first-person shooters","third-person shooters","third-person shooters","third-person shooters","basketball","basketball","basketball","football","football","football"};
	unsigned short PEGI_oznake[]={16,7,12,7,7,7,16,12,12,7,12,16,7,7,7,7,7,7};

	for(int i = 0; i < 18; i++){
		strcpy(igra.sifra,funk_generator_sifri());
		strcpy(igra.naziv_igre,nazivi_igara[i]);
		strcpy(igra.proizvodjac,proizvodjaci[i]);
		strcpy(igra.zanr,zanrevi[i]);
		igra.PEGI_oznaka = PEGI_oznake[i];
		INSERT_L(igra, END_L(lista), lista);
	}
}

bool funk_korisnicki_unos(st_IGRA &igra, st_LISTA &lista){
	cout << "Unesite naziv igre \n\t -:";
	cin >> igra.naziv_igre;
	cout << "Unesite proizvodjaca igre \n\t -:";
	cin >> igra.proizvodjac;
	cout << "Unesite zanr igre \n\t -:";
	cin >> igra.zanr;
	cout << "Unesite PEGI oznaku \n\t -:";
	cin >> igra.PEGI_oznaka;
	strcpy(igra.sifra, funk_generator_sifri());
	cout << "Igri je pridodan autogenerirani ID: " << igra.sifra << endl;
	INSERT_L(igra, END_L(lista), lista);
	if(LOCATE_L(igra.sifra, lista) == END_L(lista))
		return 0;
	return 1;
}

void funk_formatirani_ispis(int duljina){
	for(int i = duljina; i<50; i++)
		cout << " ";
	cout << "|";
}

void funk_ispis(st_LISTA &lista){

	for(int i = 1; i <= END_L(lista); i++){
		cout << "\n+----------------------------------------------------------+\n";
		cout << "| Sifra: " <<lista.elementi[i].sifra;
		funk_formatirani_ispis(strlen(lista.elementi[i].sifra));
		cout << "\n| Naziv: " <<lista.elementi[i].naziv_igre;
		funk_formatirani_ispis(strlen(lista.elementi[i].naziv_igre));
		cout << "\n| Proizvodjac: " <<lista.elementi[i].proizvodjac;
		funk_formatirani_ispis(strlen(lista.elementi[i].proizvodjac)+6);
		cout <<"===========[" << i <<"]";
		cout << "\n| Zanr: " <<lista.elementi[i].zanr;
		funk_formatirani_ispis(strlen(lista.elementi[i].zanr)-1);
		cout << "\n| PEGI: " <<lista.elementi[i].PEGI_oznaka;
		funk_formatirani_ispis((lista.elementi[i].PEGI_oznaka/10));
	}
cout << "\n+----------------------------------------------------------+\n\n";
}

bool funk_usporedi_sifru(st_LISTA &privremena_lista, int i1, int i2){
	int i = 0;
ponovi:
	if(int(privremena_lista.elementi[i1].sifra[i]) > int(privremena_lista.elementi[i2].sifra[i]))
		return 1;
	else if(int(privremena_lista.elementi[i1].sifra[i]) < int(privremena_lista.elementi[i2].sifra[i]))
		return 0;
	else if(int(privremena_lista.elementi[i1].sifra[i]) == int(privremena_lista.elementi[i2].sifra[i])){
	i++; goto ponovi;}
}

void funk_sort(st_LISTA &lista, st_LISTA &privremena_lista, int lijevi, int desni){
	if (lijevi == desni) return; //lista ima jedan ili nijedan zapis
	int srednji = (lijevi+desni)/2;   // odaberi srednji
	funk_sort(lista, privremena_lista, lijevi, srednji);     // sortiraj prvu polovicu
	funk_sort(lista, privremena_lista, srednji+1, desni);  // sortiraj drugu polovicu
	for (int i = lijevi ; i <= desni; i++)    // kopiraj u temp
		privremena_lista.elementi[i] = lista.elementi[i];
	int i1 = lijevi;
	int i2 = srednji + 1;
	for (int tekuci = lijevi; tekuci <= desni; tekuci++) {
		if (i1 == srednji+1)                 // lijeva podlista potrošena
			lista.elementi[tekuci] = privremena_lista.elementi[i2++];
		else if (i2 > desni)             // desna podlista potrošena
			lista.elementi[tekuci] = privremena_lista.elementi[i1++];
		else if(!funk_usporedi_sifru(privremena_lista, i1, i2))  // odredi "vrijedniju" šifru
			lista.elementi[tekuci] = privremena_lista.elementi[i1++];
		else
			lista.elementi[tekuci] = privremena_lista.elementi[i2++];
	}
}//Prema http://algoviz.org/OpenDSA/Books/OpenDSA/html/MergesortImpl.html

char* funk_odredi_zanr(char *podzanr){
	char zanr[9];
	if(strcmp(podzanr, "real-time strategy") == 0 || strcmp(podzanr, "grand strategy") == 0)
		strcpy(zanr,"Strategy");
	else if(strcmp(podzanr, "first-person shooters") == 0 ||strcmp(podzanr, "third-person shooters") == 0 )
		strcpy(zanr,"Action");
	else if(!strcmp(podzanr, "basketball") == 0 ||strcmp(podzanr, "football") == 0 )
		strcpy(zanr,"Sports");
	else
		strcpy(zanr,"Nepostojeci");
	return zanr;
}

bool funk_D_b(st_LISTA &lista){
	DELETE_ALL_L(lista);
	if(FIRST_L(lista) != END_L(lista))
		return 0;
	return 1;
}

bool funk_D_a(st_LISTA &lista){
	char sifra[30];
	cout << "Unesi sifru igre koju treba obrisati: \n\t-:";
	cin >> sifra;
	for(int i = 0; i <= END_L(lista); i++){
		if(strcmp(lista.elementi[i].sifra, sifra) == 0){
			DELETE_L(i, lista);
			return 1;
		}
	}
	return 0;
}

void funk_C(st_LISTA &lista){
	char zanr[] = {"Strategy"};
	cout << "Igre pod zanrom strategija: \n";
	cout << "\n+----------------------------------------------------------+";
	for(int i = 0; i < END_L(lista); i++){
		if(!strcmp(funk_odredi_zanr(lista.elementi[i].zanr),zanr)){
			cout <<"\n| "<<lista.elementi[i].naziv_igre;
			funk_formatirani_ispis(strlen(lista.elementi[i].naziv_igre)-7);
		}
	}
	cout << "\n+----------------------------------------------------------+\n\n";
}

void funk_B(st_LISTA &lista, st_LISTA &privremena_lista, int arg3, int arg4){
	funk_sort(lista, privremena_lista, arg3, arg4);
	funk_ispis(lista);
}

bool funk_A(st_IGRA &igra, st_LISTA &lista){
	return funk_korisnicki_unos(igra, lista);
}

int main(){
	int c;
	srand((unsigned)time(NULL)); // za bolje randomiziranje
	st_LISTA lista;
	st_LISTA privremena_lista; //za potrebe mergesorta
	st_IGRA igra;
	INIT_L(lista);
	do{
		cout << "Izbornik:\n";
		cout << "0. Unos testnih podataka\n";
		cout << "1. Unos igre\n";
		cout << "2. Sortiranje\n";
		cout << "3. Ispis strateskih\n";
		cout << "4. Brisanje elementa\n";
		cout << "5. Brisanje SVIH elemenata\n";
		cout << "9. Izlaz iz programa\n";
		cout << "\t-:";
		cin >> c;
		switch(c){
		case 0: //UNOS TESTNIH PODATAKA
			funk_unos_testnih_podataka(igra, lista);
			break;
		case 1: //UNOS IGRE OD STRANE KORISNIKA
			if(funk_A(igra, lista) == 1)
				cout << "Uspijeh! Igra unesena!\n";
			else
				cout << "Neuspijeh! Igra nije unesena!\n";
			break;
		case 2: //SORT I ISPIS
			funk_B(lista, privremena_lista, FIRST_L(lista),END_L(lista));
			break;
		case 3: //ISPIS STRATESKIH IGARA
			funk_C(lista);
			break;
		case 4: //BRISANJE ELEMENATA
			if(funk_D_a(lista) == 1)
				cout << "Uspijeh! Igra obsirana!\n";
			else
				cout << "Neuspijeh! Igra nije obrisana!\n";
			break;
		case 5:// BRISANJE SVIH ELEMENATA
			if(funk_D_b(lista) == 1)
				cout << "Uspijeh! Svi elementi obrisani!\n";
			else
				cout << "Neuspijeh! Svi elementi obrisani!\n";
			break;
		}
	}while(c!=9);
	return 0;
}