#include "defs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "printtext.h"
#include "imageio.h"
#include "colorlist.h"
#include "resize.h"
#include "differ.h"
#include "arglist.h"
#ifdef USE_CLUSTER
#include "cluster.h"
#endif

int savecolor (struct colorlist* list,char* colorstring) {
   /*parses a string of an r,g,b:width parameter
     and saves it into the color exclude list*/
   int red,green,blue,width,t,len;
   char *temp,*resultstring;

   if (colorstring==NULL) return -1;
   resultstring=strdup(colorstring);
   temp=resultstring;
   t=0;
   len=strlen(temp);
   while (t<len){
      if (temp[t]==',' || temp[t]==':' || temp[t]==';') {
         len=t;
	 temp[t]='\0';
      }
      t++;
   }
   red=arglist_integer(temp);
   /*Search for the first separator and save the red value*/
   temp=&temp[t];
   t=0;
   len=strlen(temp);
   while (t<len){
      if (temp[t]==',' || temp[t]==':' || temp[t]==';') {
         len=t;
	 temp[t]='\0';
      }
      t++;
   }
   green=arglist_integer(temp);
   /*Search for the 2nd separator and save the green value*/
   temp=&temp[t];
   t=0;
   len=strlen(temp);
   while (t<len){
      if (temp[t]==',' || temp[t]==':' || temp[t]==';') {
         len=t;
	 temp[t]='\0';
      }
      t++;
   }
   blue=arglist_integer(temp);
   /*Search for the 3rd separator and save the blue value*/
   temp=&temp[t];
   width=arglist_integer(temp);
   /*The 4rth value is width and if there are more separators something is wrong*/
   free(resultstring);

   if (width>0) {
      /*This is an excellent method of testing if all args were given, and
        by the way prevents a div/0 in colorlist.c*/
        fprintf(stderr,"Indexed color R:%i G:%i B:%i -- W:%i.\n",red,green,blue,width);
      return(colorlist_addcolor(list,red,green,blue,width));
   }
  fprintf(stderr,"Illegal color specified!\n");
   return -1;
   /*Illegal parameter*/
}

void printerrorstring(char* title,char *errormessage) {

   if (errormessage!=NULL) fprintf(stderr,"%s: Error: %s!\n\n",title,errormessage);
   fprintf(stderr,"This program will create an image containing the\n   brightness difference of source1 and source2!\n\n");
   fprintf(stderr,"Usage: %s \\\n",title);
   fprintf(stderr,"        [ --color-exclude [<r>,<g>,<b>:<width>] ... --color-end ] \\\n");
#ifdef USE_CLUSTER
   fprintf(stderr,"        [ -j <threads> ] \\\n");
#endif
   fprintf(stderr,"        <source1> <source2> [<destination>] [--help] [-h]\n\n");
   fprintf(stderr,"ColorExclude: A list of colors to ignore.\n");
   fprintf(stderr,"              Colors within <width> to this colors in any source\n");
   fprintf(stderr,"              will cause that pixel to be ignored\n");
   fprintf(stderr,"              End the list with --color-end.\n");
   fprintf(stderr,"              default is none\n\n");
}

int main (int argc, char *argv[]) {
   ImagePtr imsource1,imsource2,imdest;		/*Working Images*/
   struct colorlist* excludecolors;		/*List of Colors to exclude*/
   int answer;					/*Return value*/
   char* valuechar;				/*Option string*/
   int t;					/*check integers*/
   struct arglist* carglist;			/*commandline options*/
#ifdef USE_CLUSTER
   int threads;					/*number of threads*/
#endif

   carglist = arglist_new(argc, argv);
   arglist_addarg (carglist,"--help",0);
   arglist_addarg (carglist,"-h",0);
   arglist_addarg (carglist,"--color-end",0);
   arglist_addarg (carglist,"--color-exclude",10000);
   arglist_addarg (carglist,"-j",1);

   printwelcomestring();

   if ((arglist_arggiven(carglist,"--help")==0) || (arglist_arggiven(carglist,"-h")==0)) {
      printerrorstring(argv[0],NULL);
      printusagestring();
      return -1;
   }

   if ((arglist_parameter(carglist,"VOIDARGS",3)!=NULL) || (arglist_parameter(carglist,"VOIDARGS",1)==NULL)){
      printerrorstring(argv[0],"Error parsing commandline");
      printusagestring();
      return -1;
   }
   /*Check parameter count*/

#ifdef USE_CLUSTER
   threads=DEFAULT_THREADS;
   if (arglist_arggiven(carglist,"-j")==0) {
      threads=arglist_integer(arglist_parameter(carglist,"-j",0));
   }
   if (threads<1) {
      printerrorstring(argv[0],"Error parsing commandline,\nprocess amount <threads> has to be greater 0.");
      printusagestring();
      return -1;
   }
   /*Check process count */

   cluster_setpnum(threads);
#endif

   excludecolors=colorlist_new();
   t=0;
   if (arglist_arggiven(carglist,"--color-exclude")==0) {
      if (arglist_arggiven(carglist,"--color-end")!=0) {
         printerrorstring(argv[0],"Color-exclude list has no --color-end ");
         printusagestring();
         return -1;
      }
      valuechar=arglist_parameter(carglist,"--color-exclude",t);
      while (valuechar!=NULL) {
         fprintf(stderr,"Excluding color %i -- %s.\n",t,valuechar);
	 savecolor(excludecolors,valuechar);
	 valuechar=arglist_parameter(carglist,"--color-exclude",++t);
      }
   }
   /*Exclude the specified colors*/
   
   imsource1=loadim(arglist_parameter(carglist,"VOIDARGS",0));
   if (imsource1==NULL) {
      printerrorstring(argv[0],"Error loading source image 1");
      printusagestring();
      return -1;
   }
   /*Load Sourcefile1*/

   imsource2=loadim(arglist_parameter(carglist,"VOIDARGS",1));
   if (imsource2==NULL) {
      destroyim(imsource1);
      printerrorstring(argv[0],"Error loading source image 2");
      printusagestring();
      return -1;
   }
   /*Load Sourcefile2*/

   answer=differ(&imdest,imsource1,imsource2,excludecolors);
   /*Do the main work in differ.h*/

   if (arglist_parameter(carglist,"VOIDARGS",2)!=NULL) {
      if (saveim(imdest,arglist_parameter(carglist,"VOIDARGS",2))!=0) {
         printerrorstring(argv[0],"Error saving destination image");
      }
      /*Save the resulting image*/
   }

   destroyim(imsource1);
   destroyim(imsource2);
   destroyim(imdest);
   /*We free our memory*/

   fprintf(stderr,"Total amount of pixel difference between %s and %s:\n",arglist_parameter(carglist,"VOIDARGS",0),arglist_parameter(carglist,"VOIDARGS",1));
   fprintf(stdout,"%i\n",answer);

   arglist_kill(carglist);
   /*i forgot to kill the commandline argument list*/


   return 0;

}
