#include "ninox.h"

// Command parser:
// "var" or "var=value"
int
SetVariable(char *str)
	{
	char cmdbuffer[1024],fname[1024];
	int i,j,bval;
	char *arg = cmdbuffer;
	char *val = cmdbuffer;

	/* Find the value */
	strcpy(cmdbuffer,str);
	while(*val && *val != '=') ++val;
	if (*val == '=') { 
	   *(val++) = 0;
	   while (*val==' ') ++val; 
	   }

	// Catch "quoted" or 'quoted' arguments
	if (*val=='\'' || *val == '"') {
	   char *ptr = val; while(*(ptr+1)) ++ptr;
	   if (*ptr == '\'' && *val=='\'') { ++val; *ptr=0; }
	   if (*ptr == '"' && *val=='"') { ++val; *ptr=0; }
	   }

	bval=1;
	if (!strcasecmp(val,"on") || 	!strcasecmp(val,"yes") || !strcasecmp(val,"true") ||
					!strcasecmp(val,"1"))
		bval=1;
	else if (!strcasecmp(val,"off") || 	!strcasecmp(val,"no") || !strcasecmp(val,"false") ||
						!strcasecmp(val,"0"))
		bval=0;

	// Find the function to call
	for(i=0; Names[i].func != NULL; ++i) 
	   if (!strcasecmp(arg,Names[i].option))
		return (*Names[i].func)(arg,val,bval);

	// Maybe it's a boolean of the form noX meaning -X=off
	if (arg[0]=='n' && arg[1]=='o') for(i=0; Names[i].func != NULL; ++i) 
	   if (!strcasecmp(arg+2,Names[i].option))
		return (*Names[i].func)(arg+2,val,0);

	
	return 0;
	}

int
Status()
	{
	int i;

	printf("Variables:\n");
	printf("Debug = %d\n",DEBUG);
	printf("CurrentFile = \"%s\"\n",CurrentFile?CurrentFile:"");

	printf("InteractiveMode = %d\n",InteractiveMode);
	printf("cutout = %d\n",DoCutout);
	printf("ForceProcess = %d\n",ForceProcess);
	printf("width = %d\n",newWidth);
	printf("height = %d\n",newHeight);
	printf("White = %d\n",White);
	printf("overwrite = %d\n",AllowOverwrite);
	printf("protect = %d\n",HistoProtect);
	printf("UpScale = %d\n",UpScale);
	printf("DownScale = %d\n",DownScale);
	printf("UpScale_Smoothing = %d\n",UpScale_Smoothing);
	printf("ThreshHold = %d\n",ThreshHold);
	printf("MinPixels = %d\n",MinPixels);
	printf("InputFilter = %d\n",InputFilter);
	printf("InputFilter_ThreshHold = %lf\n",InputFilter_ThreshHold);
	printf("ChangeGamma = %d\n",ChangeGamma);
	printf("Gamma = %lf\n",Gamma);
	printf("CutX = %d\n",CutX);
	printf("CutY = %d\n",CutY);
	printf("BayerBoost = %lf\n",BayerBoost);
	printf("NoSave = %d\n",NoSave);
	printf("OutDir = \"%s\"\n",OutDir?OutDir:"");
	printf("WriteEmptyFiles = %d\n",WriteEmptyFiles);
	printf("Quiet = %d\n",Quiet);
	printf("StackCount = %d\n",StackCount);
	printf("StackMax = %d\n",StackMax);
	printf("StackFile = \"%s\"\n",StackFile?StackFile:"");
	printf("MergeFile = \"%s\"\n",MergeFile?MergeFile:"");
	printf("MergeThreshHold = %lf\n",MergeThreshHold);
	printf("forceWriteEmptyFiles = %d\n",forceWriteEmptyFiles);
	printf("HNoiseFilter = %d\n",HNoiseFilter);

	printf("qwrite = %d\n",QWriteIntermediateFiles);
	printf("renumber = %d\n",QRenumberFiles);
	printf("qestimator = %d\n",QEstimator);
	printf("QSUBSAMPLE_MIN = %d\n",QSUBSAMPLE_MIN);
	printf("QSUBSAMPLE_MAX = %d\n",QSUBSAMPLE_MAX);
	}

char *
ReadCommand(char *buffer, int size)
	{
	char *ptr;

	*buffer=0;
	fgets(buffer,size-1,stdin);

	// Strip off leading whitespace
	while(*buffer && *buffer <= 32) ++buffer;
	
	// Strip off trailing whitespace
	ptr = buffer + strlen(buffer);
	while(ptr != buffer && *ptr<=32) *(ptr--)=0;
	
	return buffer;
	}

int
Interact(void)
	{
	char *cmd,buffer[1024];
	Print("Interactive Mode\n");

	while(1) {
	   
	   cmd = ReadCommand(buffer,1024);
	   if (!strcasecmp(cmd,"quit") || !strcasecmp(cmd,"exit"))
		return(1);

	   if (!strncasecmp(cmd,"set ",4)) {
		SetVariable(cmd+4);
		continue;
		}

	   if (!strcasecmp(cmd,"status")) {
		Status();
		continue;
		}
	   }
	
	// notreached
	return 0;
	}

int
LoadConfigFile(char *cfgfile, char **params, char **vals)
	{
	FILE *z;
	char line[1024],tmp[1024],*st,*end,*ptr;
	int i,linenum=0,in_section=0;
	extern int FilesProcessed;

	z = fopen(cfgfile,"r");
	if (! z) {
	   printf("Error: cannot load config file '%s', abort\n",cfgfile);
	   exit(1);
	   }

	while(1) {
	   line[0]=0; ++linenum;
	   if (! fgets(line,1022,z)) { break; }

	   // trim leading and trailing whitespace
	   st=line; while(isblank(*st)) ++st;
	   end=st + strlen(st);
	   while(end>st && *(end-1) <= 32) {--end; *end=0;}

	   if (st[0] == '#') continue;
	   if (!strncmp(st,"//",2)) continue;

	   if (!strcasecmp(st,"[ninox]") || !strcasecmp(st,"[global]"))
	   	{in_section=1; continue;}

	   if (in_section) {
	      if (st[0]==0) break;

	      // Allow simple variable substitution
	      if (params!= NULL && vals != NULL) while(ptr = strchr(st,'$')) {
		char *p = ptr+1; while(isalnum(*p)) ++p;
		for(i=0; params[i]; ++i) if (!strncasecmp(ptr+1,params[i],p-ptr-1)) {
			strncpy(tmp,line,ptr-line); tmp[ptr-line]=0;
			//printf("Config: prefix=[%s] param=[%s] var=[%s] rest=[%s]\n",tmp,ptr+1,vals[i],p);
			strcat(tmp,vals[i]);
			strcat(tmp,p);
			strcpy(line,tmp);
			break;
			}

		// no variable?
		if (! params[i]) {
		   *p=0;
		   printf("LoadConfigFile: required parameter '%s' not given\n",ptr);
		   exit(1);
		   }
		}

	      Print("%s: %s\n",cfgfile,st);
	      if (! SetVariable(st)) {
          	// If it's not a variable then it must be the name of a directory to process  
		if (isDirectory(st)) FilesProcessed += ProcessDir(st);
   		else if (isFile(st) && ImageCount != 0) {
                   /* Must be a file to align */
                   int filecount = Align(st);
                   if (! filecount) { Print("Alignment failed on [%s]\n",st); exit(1); }
                   FilesProcessed += filecount;
                   }
		else {
		   printf("Error parsing line %d of config file '%s': '%s'\n",linenum,cfgfile,st);
		   exit(1);
		   }
		}
	      }
	   }

	fclose(z);
	if (! in_section) printf("oops, did not find '[ninox]' section header\n");

	Print("\n");
	LoadedConfig = 1;
	return 1;
	}
