/*
Nome: Mario
Cognome: Montanari
Classe: 3AIN
Data: 26/03/2025

Statistiche caratteri:
   - Contare le occorrenze di ciascun carattere nel file romanzo.txt;
   - Salvare le percentuali in un file di testo con il tracciato:
        - lettera percentuale (con 2 cifre decimali).
   - Contare il numero totale di:
        - Caratteri alfabetici;
        - Caratteri numerici;
        - Linee di testo;
        - Parole.
   - Crittografare il file romanzo.txt con un algoritmo a scorrimento con chiave k;
   - Scambiare i file crittografati con un compagno e cercare di decodificare il file del compagno;

*/


#include <iostream>
#include <iomanip>

#define ALFABETO 26
#define LINEA 1000+1

using namespace std;

void pausa();
void azzeraCount(float count[]);
void leggiEStampaFile(const char *nomeFile);
void creaNuovoFile(const char *nomeFileOrigine, const char *nomeFileDestinazione);
void svuotaNuovoFile(const char *nomeFile);
void criptaCodice(const char *nomeFile, int k);
void contaOcc(const char *nomeFile, float count[], int &lettereTotali, int &numeriTotali);
void contaLinee(const char *nomeFile, int &numeroLinee);
void contaParole(const char *nomeFile, int &numeroParole);
void stampa(float count[], int lettereTotali, int numeriTotali, int numeroLinee, int numeroParole);
void riempiNuovoFile(const char *nomeFile, float count[], int lettereTotali);
void riempiFileCrittografato(const char *nomeFileOrigine, const char *nomeFileDestinazione, int k);

int main(void) {
	float count[ALFABETO];
	int lettereTotali = 0;
	int numeriTotali = 0;
	int numeroLinee = 0;
	int numeroParole = 0;
	int k = 3;
	
	azzeraCount(count);
	
	cout << "Romanzo originale:" << endl << endl;
	leggiEStampaFile("romanzo.txt");
	creaNuovoFile("romanzo.txt", "letteraPercentuale.txt");
	svuotaNuovoFile("letteraPercentuale.txt");
	
	cout << endl << endl << endl << "---------------------------------------------------------------------------------------------------------" << endl << endl << endl << endl;
	
	pausa();
	
	cout << endl << endl << "---------------------------------------------------------------------------------------------------------" << endl << endl << endl << endl;
	
	cout << "Romanzo crittografato:" << endl << endl;
	criptaCodice("romanzo.txt", k);
	
	cout << endl << endl;
	
	contaOcc("romanzo.txt", count, lettereTotali, numeriTotali);
	contaLinee("romanzo.txt", numeroLinee);
	contaParole("romanzo.txt", numeroParole);
	
	cout << endl << "---------------------------------------------------------------------------------------------------------" << endl << endl << endl << endl;
	
	pausa();
	
	cout << endl << endl << "---------------------------------------------------------------------------------------------------------" << endl << endl << endl << endl;
	
	stampa(count, lettereTotali, numeriTotali, numeroLinee, numeroParole);
	riempiNuovoFile("letteraPercentuale.txt", count, lettereTotali);
	
	creaNuovoFile("romanzo.txt", "romanzoCrittografato.txt");
	svuotaNuovoFile("romanzoCrittografato.txt");
	riempiFileCrittografato("romanzo.txt", "romanzoCrittografato.txt", k);
	
	return 0;
}

void pausa() {
	system("pause");
	system("dir");
	system("pause");
}

void azzeraCount(float count[]) {
	for (int i = 0; i < ALFABETO; i++) {
		count[i] = 0;
	}
}

void leggiEStampaFile(const char *nomeFile) {
	FILE *fp = fopen(nomeFile, "rt");

	if (fp != NULL) {
		char chr;
		
		while ((chr = fgetc(fp)) != EOF) {
			cout << (char)chr;
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void creaNuovoFile(const char *nomeFileOrigine, const char *nomeFileDestinazione) {
	FILE* fileOrigine = fopen(nomeFileOrigine, "r");
	if (fileOrigine != NULL) {
		
		FILE* fileDestinazione = fopen(nomeFileDestinazione, "w");
		if (fileDestinazione != NULL) {
			int chr;
		
			while ((chr = fgetc(fileOrigine)) != EOF) {
				fputc(chr, fileDestinazione);
			}
			
			fclose(fileDestinazione);
		} else {
			perror("Error (destination)");
		}
		fclose(fileOrigine);
	} else {
		perror("Error (source)");
	}
}

void svuotaNuovoFile(const char *nomeFile) {
	FILE *fp = fopen(nomeFile, "wt");

	if (fp != NULL) {

		fclose(fp);
	} else {
		perror("Error");
	}
}

void criptaCodice(const char *nomeFile, int k) {
	FILE *fp = fopen(nomeFile, "rt");

	if (fp != NULL) {
		char chr;
		
		while ((chr = fgetc(fp)) != EOF) {
			if (isalpha(chr)) {
				if (isupper(chr)) {
					chr = ((chr - 'A' + k) % 26) + 'A';
					cout << chr;
				} else if (islower(chr)) {
					chr = ((chr - 'a' + k) % 26) + 'a';
					cout << chr;
				}
			} else if (!isalpha(chr)) {
				cout << chr;
			}
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void contaOcc(const char *nomeFile, float count[], int &lettereTotali, int &numeriTotali) {
	FILE *fp = fopen(nomeFile, "rt");

	if (fp != NULL) {
		char chr;
		
		while ((chr = fgetc(fp)) != EOF) {
			chr = tolower(chr);
			if (isalpha(chr)) {
				lettereTotali++;
				count[chr - 'a']++; // devi veficare che l'indice sia accettabile
			} else if (isdigit(chr)) {
				numeriTotali++;
			}
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void contaLinee(const char *nomeFile, int &numeroLinee) {
	FILE *fp = fopen(nomeFile, "rt");

	if (fp != NULL) {
		char str[LINEA];
		
		while ((fgets(str, sizeof(str), fp)) != NULL) {
			numeroLinee++;
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void contaParole(const char *nomeFile, int &numeroParole) {
	FILE *fp = fopen(nomeFile, "rt");

	if (fp != NULL) {
		char chr;
		
		while ((chr = fgetc(fp)) != EOF) {
			if (!isspace(chr) && !ispunct(chr)) { // ispunct() determina se è un segno di punteggiatura
				numeroParole++;
				while ((chr = fgetc(fp)) != EOF && (!isspace(chr) && !ispunct(chr))) { // Salto alla fine della parola fino a quando non trovo un altro spazio
					;
				}
			}
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void stampa(float count[], int lettereTotali, int numeriTotali, int numeroLinee, int numeroParole) {
	cout << "----------------------------------------------------" << endl;
	cout << "|" << setw(17) << "Lettera |" << setw(17) <<  "Occorrenze |" << setw(17) << "Percentuale |" << endl;
	cout << "----------------------------------------------------" << endl;
	for (int i = 0; i < ALFABETO; i++) {
		cout << "|" << setw(15) << (char)(i + 'a') << " |" << setw(15) << count[i] << " |" << setw(14) << (count[i] / lettereTotali) * 100 << "% |" << endl;
	}
	cout << "----------------------------------------------------" << endl;
	
	cout << endl << "Lettere totali: " << lettereTotali << endl;
	cout << "Numeri totali:  " << numeriTotali << endl;
	cout << "Linee totali:   " << numeroLinee << endl;
	cout << "Parole totali:  " << numeroParole << endl;
}

void riempiNuovoFile(const char *nomeFile, float count[], int lettereTotali) {
	FILE *fp = fopen(nomeFile, "wt");

	if (fp != NULL) {
		
		for (int i = 0; i < ALFABETO; i++) {
			fprintf(fp, "%.2f%\n", (count[i] / lettereTotali) * 100);
		}

		fclose(fp);
	} else {
		perror("Error");
	}
}

void riempiFileCrittografato(const char *nomeFileOrigine, const char *nomeFileDestinazione, int k) {
	FILE* fileOrigine = fopen(nomeFileOrigine, "r");
	if (fileOrigine != NULL) {
		
		FILE* fileDestinazione = fopen(nomeFileDestinazione, "w");
		if (fileDestinazione != NULL) {
			int chr;
		
			while ((chr = fgetc(fileOrigine)) != EOF) {
				if (isalpha(chr)) {
					if (isupper(chr)) {
						chr = ((chr - 'A' + k) % 26) + 'A';
						fputc(chr, fileDestinazione);
					} else if (islower(chr)) {
						chr = ((chr - 'a' + k) % 26) + 'a';
						fputc(chr, fileDestinazione);
					}
				} else if (!isalpha(chr)) {
					fputc(chr, fileDestinazione);
				}
			}
			
			fclose(fileDestinazione);
		} else {
			perror("Error (destination)");
		}
		fclose(fileOrigine);
	} else {
		perror("Error (source)");
	}
}