#include <skunk_app.h>
#include <skunk_hash.h>
#include <skunk_make.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>

#define outfd 1
#define MAX_RECURSE 64

skunkwr_t sdb;

int begin(const char *path, int maxdepth)
{
	DIR *dir;
	struct dirent *f;
	struct stat st;
	int fd=-1;
	char fn[1024];
	int fnlen;
	int ret=1;

	if ( !(dir=opendir(path)) )
		return 0;

	while ( dir ) {
		if ( !(f=readdir(dir)) )
			break;

		if ( !strcmp(".", f->d_name) ) continue;
		if ( !strcmp("..", f->d_name) ) continue;
		
		fnlen=snprintf(fn, 1024, "%s/%s", path, f->d_name);
		
		if ( (fd=open(fn, O_RDONLY))<0 ) {
			perror("open()");
			ret=0;
			break;
		}

		if ( fstat(fd, &st) ) {
			perror("perror()");
			ret=0;
			break;
		}

		if ( S_ISREG(st.st_mode) ) {
			char *map;
			fprintf(stderr, "Adding: %s\n", fn);

			map=mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
			if ( map==MAP_FAILED ) {
				perror("mmap");
				ret=0;
				break;
			}
			
			make_add(&sdb, fn, map, fnlen, st.st_size);
			close(fd);
		}else if ( S_ISDIR(st.st_mode) && maxdepth ) {
			fprintf(stderr, "Recursing: %s\n", fn);
			close(fd); /* dont wanna exhaust fd's */
			begin(fn, --maxdepth);
		}
	}

	if ( fd != -1 ) close(fd);
	closedir(dir);
	return ret;
}

int main(int argc, char **argv)
{

	if ( !make_init(&sdb, outfd, SKUNK_BUFFER) ) {
		fprintf(stderr, "make_init() failed\n");
		return SKUNK_ERR;
	}
	
	if ( !begin(".", MAX_RECURSE) ) {
		return SKUNK_ERR;
	}

	if ( !make_write(&sdb) ) {
		fprintf(stderr, "make_write() failed\n");
		return SKUNK_ERR;
	}

	if ( fsync(outfd) ) {
		perror("fsync()");
		return SKUNK_ERR;
	}

	if ( close(outfd) ) {
		perror("close()");
		return SKUNK_ERR;
	}
	
	make_close(&sdb);
	
	return SKUNK_OK;
}
