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

#include "db.h"

 static int
 cmpstring(const void *p1, const void *p2)
{ return strcmp(* (char * const *) p1, * (char * const *) p2);}


char path[100000];


void mergedb(dbase *olddb,dbase *newdb,char *path){
	static struct stat st;
	struct dirent *e;
	char *fsort=NULL,*dsort=NULL;
	char **filp=NULL,**dirp=NULL;
	char *fp=NULL,*dp=NULL;
	int fn=0,dn=0;
	int i;
	path=strdup(path);	
	if (olddb) readfile(olddb);
	writedir(newdb,(uchar *)path);
	if(chdir(path)) goto ret;
	if (lstat(".",&st)) goto ret2;
	if (!olddb ||st.st_mtime>olddb->mtime){
		DIR *dir=opendir(".");
		if (!dir)goto ret2; 
		fp=fsort=malloc(1000000);dp=dsort=malloc(1000000);filp=malloc(1000000);dirp=malloc(1000000);
		while ((e=readdir(dir))){
			if(lstat(e->d_name,&st)) continue;

			if (strcmp(e->d_name,".")&&strcmp(e->d_name,"..")) {
				if (S_ISDIR(st.st_mode)){
					strcpy(dp,e->d_name); dirp[dn++]=dp;dp+=strlen(dp)+1;
				}else{
					strcpy(fp,e->d_name); filp[fn++]=fp;fp+=strlen(fp)+1;
				}
			}
		}
		closedir(dir);
		qsort(filp,fn,sizeof(char*),cmpstring);		qsort(dirp,dn,sizeof(char*),cmpstring);
		for (i=0;i<fn;i++)
			writefile(newdb,(uchar *)filp[i]);
		free(fsort);free(filp);
	} else {
			while(1){
				switch (olddb->filetype){
				case FN_FILE:
					writefile(newdb,olddb->name);
					break;
				case FN_DIR:
					mergedb(olddb,newdb,(char *)olddb->dirname);
					break;
				case FN_ENDDIR:
					goto ret2;
				}
				readfile(olddb);
			}
	}
	if (!olddb){
		for (i=0;i<dn;i++){
			mergedb(olddb,newdb,dirp[i]);
		}
		free(dsort);free(dirp);
		goto ret2;
	} else {
		int di=0;char *name;
		while(1){
			switch (olddb->filetype){
				case FN_FILE:
					break;
				case FN_DIR:
					name=strdup((char *)olddb->dirname);
					while (di<dn&& strcmp(dirp[di] ,name)>0 ){
						mergedb(NULL,newdb,dirp[di++]);
					}
					if (di<dn && !strcmp(dirp[di],name)){
						mergedb(olddb,newdb,dirp[di++]);
					} else {
						int co=1;
						while (co){
							readfile(olddb);
							if (olddb->filetype==FN_DIR) co++;
							if (olddb->filetype==FN_ENDDIR) co--;
						}
					}
					free(name);
					break;
				case FN_ENDDIR:
					while (di<dn){
						mergedb(NULL,newdb,dirp[di++]);
					}
				 	free(dsort);free(dirp);
					goto ret2;
			}
			readfile(olddb);
		}
	}
ret2:		chdir("..");
				if(olddb){
					int co=1;
					while (1){
						if (olddb->filetype==FN_DIR) co++;
						if (olddb->filetype==FN_ENDDIR) co--;
						if (!co) break;
						readfile(olddb);
					}
				}
ret: 		writeenddir(newdb);
				free(path);
}

int main(){
	dbase *odb=readdb("/home/wizard/search/search.db");
	if (!odb){
		int hist[256];
		odb=initdbase(hist);
		mergedb(NULL,odb,"/home/wizard");
		writeend(odb);
		odb->fn.fn=odb->fnbegin.fn;
	}
	readfile(odb);
	dbase *db=initdbase(odb->newhist);
	mergedb(odb,db,"/home/wizard");
	writeend(db);
	writedb(db,"/home/wizard/search/search.db");
return 0;
}
