#include "ninox.h"

/*
 * Read a P6 PPM file on standard input, and write a P6 PPM file on standard output.
 * The output file will have the object centered, with the assumption that any
 * pixels with values >= 10% R/G/B are part of the object, and elsewise are background
 */

int FilesProcessed = 0;

static int ProcessStdin(void);

main(int argc, char *argv[])
	{
	FILE *z;
	char fname[1024];
	int i,j;
	unsigned int Start,Run;
	extern int ShowHist_PrintToStdout;
	extern int SER_QCount[];
	extern char *SER_Filename_map[];
	
	ShowHist_PrintToStdout = 1;

	BlankImageCount=0;
	fname[0]=0;
	Start = time(0);
	Srandom();

	printf("%s\n",argv[0]); fflush(stdout);

	// If called with no arguments then print all possible switches and exit
	if (argc==1) {
	   _CMD_help();
	   exit(0);
	   }

	// Init channel related global arrays
	for(i=0; i<NUM_CHANNELS; ++i) {
	   SER_QCount[i] = 0;
	   SER_Filename_map[i] = NULL;
	   }

	// Init the stacking module
	stack_init();

	if (StreamFilter) init_streamfilter();

	for(i=1; i < argc; ++i) {
	   char *arg = argv[i];

	   if (arg[0]=='-') {
		// set VAR=VALUE
		int n = SetVariable(arg+1);
		if (n == 0 ) {
		   Print("%s: Unknown switch\n",arg);
		   exit(1);
		   }
		if (n < 0) {
		   Print("Error in switch %s\n",arg);
		   exit(1);
		   }
		continue;
		}

	   while(strlen(arg)>0 && arg[strlen(arg)-1] == '/' || arg[strlen(arg)-1] == '\\') 
		   arg[strlen(arg)-1] = 0;

	   if (isFile(arg) && ImageCount > 0) {
		/* Must be a file to align */
	 	int filecount = Align(arg);
	 	if (! filecount) {
		   Print("Alignment failed on [%s]\n",arg);
		   exit(1);
		   }
		--ImageCount;
		FilesProcessed += filecount;
		}
	   else if (isDirectory(arg)) {
		FilesProcessed += ProcessDir(arg);
		}

	   else {
		Print("Unknown argument: '%s'\n",arg);
		exit(1);
		}
	   }
	   
	if (InteractiveMode) {
	   Interact();
	   exit(0);
	   }

	if (FilesProcessed == 0 && UsingStdin) 
		FilesProcessed += ProcessStdin();

	// No files specified? Then process the current directory by default
	if (FilesProcessed == 0 && ! UsingStdin)
	   FilesProcessed += ProcessDir(".");

	if (! FilesProcessed) {
	   Print("Found no files to process.\n");
	   }
	else {
	   Print("\n  -> Processed %d files\n",FilesProcessed);
	   }

        if (StackCount>0 && StackFile != NULL) {
	  if (OutDir && !strstr(StackFile,"\\") && !strstr(StackFile,"/"))
		sprintf(fname,"%s/%s",OutDir,StackFile);
	  else	strcpy(fname,StackFile);
	  if (OutDir) Mkdir(OutDir);
          if (!Quiet) Print("  -> Writing stackfile %s from %d frames\n",fname,StackCount);

          write_stack_data(fname);
          }

//Print("Finished fname='%s' StackFile='%s'\n",fname,StackFile);
//fflush(stdout);
//exit(0);

	if (QEstimator) {
	   int do_trim = 0;
	   if (QTrim_Before || QTrim_After) do_trim = 1;

	   if (do_trim) Mark_Trim(QTrim_Before,QTrim_After);

	   if (QRenumberFiles) {
		Print("\nRenumbering...\n");
		QRenumber(QRenumberFiles);
		}
	   else if (do_trim) Delete_Trim();
	   }

	// Save the commandline
	if (0 && OutDir)sprintf(fname,"%s/ninox.run",OutDir);
	else 		strcpy(fname,"ninox.run");

	for(i=0; fname[i]; ++i) if (fname[i]=='\\') fname[i]='/';

	z = OpenLogfile(fname,"ab");
	if (z != NULL) {
	   for(i=0; i<argc; ++i)
	      if (argv[i][0] == '-')
	      fprintf(z,"%s ",argv[i]);
	   fprintf(z,"\n");
	   fclose(z);
	   }
	else {
	   Print("Cannot save settings file %s\n",fname);
	   }

	if (DetectHotPixels) {
	   WriteHotPixelFile("hotpixels.txt");
	   }

	Run = time(0) - Start;
	printf("running time = %02dm%02ds seconds\n",Run/60,Run%60);
	exit(0);
	}

static int
comp(const void *ptr1, const void *ptr2)
	{
	char **s1 = (char **)ptr1;
	char **s2 = (char **)ptr2;
	char *p1,*p2;

	char *e1 = *s1 + strlen(*s1);	// ends of the strings
	char *e2 = *s2 + strlen(*s2);

	int i1,i2;

	// seek to end of string
	p1 = e1;
	p2 = e2;

	// seek back until we find the last path entry
	while(p1 != *s1 && *(p1-1) != '/' && *(p1-1) != '\\') --p1;
	while(p2 != *s2 && *(p2-1) != '/' && *(p2-1) != '\\') --p2;
	
	if (strcasecmp(e1-4,".fta")==0 && strcasecmp(e2-4,".fta")==0) {
	   int a1,a2,b1,b2,c1,c2;

	   // first try is based on the naming convention for .fta files
	   if (sscanf(p1,"data%d-%d-%d.fta",&a1,&b1,&c1) == 3 &&
	       sscanf(p2,"data%d-%d-%d.fta",&a2,&b2,&c2) == 3) {
		if (a1 != a2) return a1-a2;
		if (b1 != b2) return b1-b2;
		return c1-c2;
		}

	   // second try is normal string-based
	   return strcasecmp(*s1,*s2);
	   }

	// Go forward until we find a digit
	while(*p1 && ! isdigit(*p1)) ++p1;
	while(*p2 && ! isdigit(*p2)) ++p2;

	// Hopefully we are now on a substring that can be used for comparison
	i1 = atoi(p1);
	i2 = atoi(p2);

	if (i1<i2) return -1;
	if (i1>i2) return 1;
	return 0;
	}

// Look in the named directory for files to process
int
ProcessDir(char *dir)
	{
	char fname[256];
	struct dirent *e;
	DIR *d = opendir(dir);
	int i,count=0,prepend_dir,FileCount;
	char *file_list[DIR_MAX_COUNT];
	char OutDir_Save[1024];

	Print("ProcessDir %s, OutDir='%s'\n",dir,OutDir);

	if (d==NULL) {
	   Print("Error opening directory %s\n",dir);
	   return 0;
	   }

	// Munch off trailing slash
	i = strlen(dir) - 1; 
	if (dir[i] == '/' || dir[i] == '\\') dir[i] = 0;

	if (dir[0]=='.' && dir[1]==0)
	   prepend_dir = 0;
	else
	   prepend_dir = 1;

	// If we have -outdir-append-src then append the last component
	// of d onto OutDir
	OutDir_Save[0]=0;
	if (OutDir && OutDirAppendSrc) {
	   int i = strlen(dir)-1;

	   Print("OutDirAppend\n");
	   while(i>0 && dir[i-1] != '/' && dir[i-1] != '\\') --i;
	   if (i) {
	   	strcpy(OutDir_Save,OutDir);
		strcat(OutDir,"/");
		strcat(OutDir,dir+i);
		printf("Using '%s' for OutDir\n",OutDir);
	   	}
	   }
	else if (OutDir && OutDirPrependSrc) {
	   // If we have -outdir-prepend-src then prepend the last component
	   // of d before OutDir
	   int i = strlen(dir)-1;

	   Print("Prepend\n"); fflush(stdout);
	   while(i>0 && dir[i-1] != '/' && dir[i-1] != '\\') --i;
	   if (i) {
		   Print("Changing OutDir\n");
	   	strcpy(OutDir_Save,OutDir);
		free(OutDir);
		OutDir = Malloc(strlen(dir+i) + 8);
		strcpy(OutDir,"./");
		if (! NoSave) Mkdir(dir+i);
		strcat(OutDir,dir+i);
		strcat(OutDir,"/");
		strcat(OutDir,OutDir_Save);
		Print("Using '%s' for OutDir\n",OutDir);
	   	}
	   }
	
	if (OutDir && ! NoSave) Mkdir(OutDir);

	while(e = readdir(d)) {
	   if (strlen(e->d_name)>4) {
		if (prepend_dir) sprintf(fname,"%s/%s",dir,e->d_name);
		else strcpy(fname,e->d_name);

		if (LoadedConfig==0 && strcmp(e->d_name,"ninox.ini")==0) {
		   Print("Loading default config file %s\n",fname);
		   LoadConfigFile(fname,"ninox",NULL,NULL);
		   }

	   	if (! access(fname,R_OK|F_OK) && 
		   (	strcasestr(fname,".bmp") ||
		   	strcasestr(fname,".ppm") || strcasestr(fname,".pgm") ||
			strcasestr(fname,".fit") || strstr(fname,".fta") ||
			strcasestr(fname,".ser"))) {
		   	file_list[count++] = strdup(fname);
			if ((count%1000)==0) {
				Print("Loaded %d files...\n",count);
				fflush(stdout);
				}
			}

		if (count>=DIR_MAX_COUNT) {
		   Print("Max count of %d files reached!\n",DIR_MAX_COUNT);
		   exit(1);
		   }
		}
	   }
	closedir(d);

	// Turn off archive chaining since we've explicitly found
	// all the files.
	ChainArchives = 0;
	qsort(file_list,count,sizeof(char *),comp);

	for(i=0; i<count; ++i) Print("Added %s\n",file_list[i]);

	for(i=FileCount=0; i<count; ++i) {
	   char *fname = file_list[i];
	   int fc = 0;

	   if (ImageCount > 0) {
	      fc = Align(fname);
	      if (! fc) Print("Alignment failed on [%s]\n",fname);
	      FileCount += fc;
	      if (ImageCount < IMAGECOUNT_MAX) {
	         Print("%d images remaining\n",ImageCount);
		 }
	      }

	   free(file_list[i]);
	   }

	if (OutDir && OutDir_Save) {
	   strcpy(OutDir, OutDir_Save);
	   }

	return FileCount;
	}

// We're reading a stream of frames from standard input
static int
ProcessStdin()
	{
	int i,fc;
	int FileCount=0;

	for(i=FileCount=0; i<IMAGECOUNT_MAX; ++i) {
	   if (ImageCount > 0) {
	      fc = Align("-");
	      if (fc <= 0) {
		  Print("Alignment failed on STDIN\n");
		  return FileCount;
	   	  }

	      FileCount++;
	      ImageCount--;
	      if (ImageCount < IMAGECOUNT_MAX) {
	         Print("%d images remaining\n",ImageCount);
		 }
	      }

	   }

	return FileCount;
	}
