#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>

const char CHECK_SUFFIX[] = "SDLALLINONE";
const long l_size = sizeof(long);
const long suffix_len = sizeof(CHECK_SUFFIX);

int append_file (int packfd, const char *path) {
	int isOK = 1;
	int datafd;
	char buffer[4096];
	long bufferlen;
	long taille;

	// une donnée pour le nom
	bufferlen = strlen(path);
	write (packfd, path, bufferlen);
	write (packfd, &bufferlen, l_size);
	printf ("Ajout de %s\n", path);

	// une donnée pour le contenu
	taille = 0;
	datafd = open (path, O_RDONLY);
	if (-1 == datafd) {
		printf ("Attention, erreur sur %s\n", path);
		write (packfd, &taille, l_size);
		isOK = 0;
	}
	do {
		bufferlen = read (datafd, buffer, sizeof(buffer));
		if (bufferlen > 0)
			taille += write (packfd, buffer, bufferlen);
		else
			break;
	} while (1);

	write (packfd, &taille, l_size);
	close (datafd);

	return isOK;
}

int append_res (int packfd, const char *path, long* nb_res) {
	DIR *rep;
	struct dirent *entry;
	struct stat s;
	char* tmp_path = NULL;
	int isOK = 1;
	if ((rep = opendir(path))) {
		while ((entry = readdir(rep))) {
			tmp_path = (char*)realloc (tmp_path, strlen(path)+strlen(entry->d_name)+2);
			strcpy (tmp_path, path);
			strcat (tmp_path, "/");
			strcat (tmp_path, entry->d_name);
			if (!strcmp (entry->d_name, ".")) {
				continue;
			}
			if (!strcmp (entry->d_name, "..")) {
				continue;
			}
			if (-1 == stat (tmp_path, &s)) {
				fprintf (stderr, "Can't stat %s\n", tmp_path);
				isOK = 0;
				break;
			}
			if (S_ISDIR(s.st_mode)) {
				append_res (packfd, tmp_path, nb_res);
			} else if (S_ISREG(s.st_mode)) {
				if (append_file (packfd, tmp_path)) {
					++(*nb_res);
				} else {
					fprintf (stderr, "Can't append %s\n", tmp_path);
					isOK = 0;
					break;
				}
			}
		}
		closedir(rep);
		free (tmp_path);
	} else {
		fprintf (stderr, "Can't open %s\n", path);
		isOK = 0;
	}
	return isOK;
}

int main (int argc, char** argv) {
	int packfd;
	long nb_resources = 0;
	long nb_couples = 0;
	char* pack;
	char* topdir = "res";

	if (argc < 2 || argc > 3) {
		fprintf (stderr, "USAGE: %s executable [res_top_dir]\n", argv[0]);
		fprintf (stderr, "       res_top_dir defautls to res\n");
		return 1;
	}

	pack = argv[1];
	if (argc == 3) {
		topdir = argv[2];
	}

	// On ouvre l'exe en écriture et on se place à la fin.
	printf ("Packaging de %s\n", pack);
	packfd = open (pack, O_APPEND | O_WRONLY);
	if (-1 == packfd) {
		fprintf (stderr, "Impossible d'ouvrir %s pour y ajouter les ressources.\n", pack);
		return 1;
	}

	// Ensuite, on ajoute les fichiers trouvés dans le dossier de ressources
	append_res (packfd, topdir, &nb_resources);

	// on ajoute le nombre de données
	// 2 fois le nombre de resources parce qu'on compte 
	// 	1 pour le nom
	//	1 pour les données
	nb_couples = 2 * nb_resources;

	printf ("%lu resources\n", nb_resources);
	write (packfd, &nb_couples, l_size);

	// on ajoute le suffixe
	write (packfd, CHECK_SUFFIX, suffix_len);

	close (packfd);
	return 0;
}
