/************************************\
 *                                  *
 *   scritto da zero per CloseBSD   *
 *                                  *
 *   ultima modifica: xx/xx/2026    *
 *                                  *
\************************************/

// stampa su piu' colonne se nfiles > ROW
// alloca giusta lunghezza linkbuf (strdup?)

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>

#define	COL_DEF	"\x1b[0m"
#define	COL_DIR	"\x1b[34m"

int nfiles, maxlen;

int stats(char**, char*);
void ordina(char**);

int stats(char** files, char *dir)
{
	char *path, *pathfile;
	struct stat st;
	FILE *fp;
	int ch;
	int linee;
	int linklen;
	char linkbuf[30];

//	non basta riallocare "dir"?
	path = malloc((strlen(dir) + 2) * sizeof(char));
	strcpy(path, dir);
	if ((path[strlen(dir) - 1] != '/') &&  strcmp(path, "") != 0)
		strcat(path, "/");
	pathfile = malloc((strlen(dir) + maxlen + 2) * sizeof(char));

	for (int i = 0; i < nfiles; i++)
	{
		strcpy(pathfile, path);
		strcat(pathfile, files[i]);
		if (lstat(pathfile, &st) == -1) {
			perror(pathfile);
			continue;
		}

		linee = 0;
		if (S_ISREG(st.st_mode) && (fp = fopen(pathfile, "r")) != NULL) {
			while ((ch = fgetc(fp)) != EOF) {
				if (ch == '\n')
					linee++;
			} fclose(fp);
		}

		printf("\t");
		if (linee == 0)
			printf("%5c", ' ');
		else {
			printf("%4d ", linee);
			linee = 0;
		}

		if (S_ISDIR(st.st_mode))
			printf(COL_DIR);
		if (st.st_flags == 131072)
			printf("# ");
		else printf("  ");

		if (files[i][0] == '.')
			printf("%s", files[i]);
		else printf(" %s", files[i]);
		if (S_ISLNK(st.st_mode)) {
			linklen = readlink(pathfile, linkbuf, 30);
			linkbuf[linklen] = '\0';
			stat(pathfile, &st);
			printf(" -> ");
			if (S_ISDIR(st.st_mode))
				printf(COL_DIR);
			printf("%s", linkbuf);
		}
		if (S_ISDIR(st.st_mode))
			printf(COL_DEF);
		printf("\n");
	}

	return 0;
}

int main(int argc, char *argv[])
{
	DIR *dirp;
	struct dirent *dp;
	int max = 50;
	char** files = malloc(max * sizeof(char*));

	if (argc == 1)
		dirp = opendir(".");
	else dirp = opendir(argv[1]);
	
	if (dirp == NULL) {
		printf("%s: non-directory o file inesistente\n", argv[0]);
		return 1;
	}

	nfiles = maxlen = 0;
	while ((dp = readdir(dirp)) != NULL) {
		if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0)) {
			if (strlen(dp->d_name) > maxlen)
				maxlen = strlen(dp->d_name);
			files[nfiles] = malloc((maxlen + 1) * sizeof(char));
			strcpy(files[nfiles++], dp->d_name);

			if (nfiles == max) {
				max *= 2;
				files = realloc(files, max * sizeof(char*));
			}
		}
	} closedir(dirp);

	ordina(files);
	if (argc == 1)
		stats(files, "");
	else stats(files, argv[1]);

	return 0;
}

void ordina(char** files)
{
	char buf[maxlen + 1];
	int i, j;

	for (i = 0; i < nfiles; i++) {
		if (strlen(files[i]) < maxlen)
			files[i] = realloc(files[i], (maxlen + 1) * sizeof(char));
	}

	for (i = 0; i < nfiles - 1; i++) {
		for (j = i + 1; j < nfiles; j++) {
			if (strcmp(files[j], files[i]) < 0) {
				strcpy(buf, files[i]);
				strcpy(files[i], files[j]);
				strcpy(files[j], buf);
			}
		}
	}
}
