#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <strings.h>
#include <math.h>

short details = 0;
short allFiles = 0;
short humanSizes = 0;
short sizeUnit = 0;
char * sufiksy[] = {"bajtow", "kilobajtow", "megabajtow", "gigabajtow", "terabajtow" };
unsigned int sufiksyRozm = 5;

void usageAndExit(void)
{
	printf("Usage: zad1 [-H] [-a] [-c] [-k] [-m] [KATALOG]\n\n-H\tpomoc\n-a\tuwzglednia rowniez pliki ukryte\n-c\tpokazuje rozmiary poszczegolnych plikow\n-k\trozmiar w kilobajtach\n-m\trozmiar w megabajtach\n");
	exit(1);
}

char * printSize(unsigned int r)
{
	double rozm = r;
	unsigned int rozmBuf = 20;
	char * buf = malloc(sizeof(char *) * rozmBuf);
	int i = 0;
	
	if (humanSizes == 1)
	{
		for(i = 0; rozm > 1024 && i < 5; ++i)
			rozm = rozm / 1024;
	} else if (sizeUnit != 0) {
		rozm = rozm / pow(1024, sizeUnit);
		i = sizeUnit;
	}
	bzero(buf, rozmBuf);
	snprintf(buf, rozmBuf, "%.2f %s", rozm, sufiksy[i]);
	return buf;
}

void do_du(char * path)
{
	DIR *dir_ptr;
	char cwd[1024];
	char buf[1024];
	char buf2[1024];
	unsigned int sumSize = 0;
	unsigned int file_size = 0;
	struct dirent *direntp;
	struct stat info;

	getcwd(cwd, sizeof(cwd));
	if ((dir_ptr = opendir(path)) == NULL)
	{
		fprintf(stderr,"error: cannot open %s\n", path);
	}
	while ((direntp = readdir(dir_ptr))!= NULL)
	{
		snprintf(buf, sizeof(buf), "%s/%s/%s", cwd, path, direntp->d_name);
		realpath(buf, buf2);
		stat(buf2, &info);
		if (S_ISREG(info.st_mode) && ((allFiles == 1) || (*direntp->d_name != '.')))
		{
			file_size = info.st_size;
			if (details == 1)
			{
				printf("%s: %s\n", direntp->d_name, printSize(file_size));
			}
			sumSize += file_size;
		}
	}
	if (details == 1)
	{
		printf("\nSuma: ");
	}
	printf("%s\n", printSize(sumSize));
}

int main(int argc, char *argv[])
{
	char * path = ".";
	char c;

	while((c = getopt(argc, argv, "cahmkH")) != -1)
	{
		switch (c)
		{
			case 'c':
				details = 1;
				break;
			case 'a':
				allFiles = 1;
				break;
			case 'h':
				humanSizes = 1;
				break;
			case 'm':
				sizeUnit = 2;
				break;
			case 'k':
				sizeUnit = 1;
				break;
			default:
				usageAndExit();
				break;
		}
	}
	if (optind <= (argc - 1))
	{
		path = argv[optind];
	}
	do_du(path);
	exit(0);
}

