#include "defs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "printtext.h"
#include "imageio.h"
#include "patternlist.h"
#include "scale.h"
#include "blur.h"
#include "enhance.h"
#include "findpattern.h"
#include "arglist.h"
#ifdef USE_CLUSTER
#include "cluster.h"
#endif

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

   if (errormessage!=NULL) fprintf(stderr,"%s: Error: %s!\n\n",title,errormessage);
   fprintf(stderr,"This Program will align a test sample image to a reference image\n   and safe the result in a destination image.\n\n");
   fprintf(stderr,"Usage: %s <reference> <test> [<destination>] \\\n",title);
#ifdef USE_CLUSTER
   fprintf(stderr,"        [ -j <threads> ] \\\n");
#endif
   fprintf(stderr,"        [--help] [-h]\n\n");
}

int main (int argc, char *argv[]) {
   ImagePtr imtmp,imrefer,imsource,imdest;	/*Working Images*/
   int blurval;
   int enhsize,enhmul,enhqual;
   int patsize;
   struct pattern topleft,topright;	/*edge patterns*/
   struct pattern bottomleft,bottomright;
   struct patterntarget position;	/*location result*/
   int x11,y11,x12,y12,x13,y13,x14,y14;  /*scaling positions*/
   int x21,y21,x22,y22,x23,y23,x24,y24;
   int t,tt;
   struct arglist* carglist;	/*commandline options*/
#ifdef USE_CLUSTER
   int threads;					/*number of threads*/
#endif

   blurval=300;
   enhsize=400;
   enhmul=2000;
   enhqual=25;
   patsize=24;


   topleft.height=patsize;
   topleft.width=patsize;
   topleft.brightness=(int*)malloc(sizeof(int[patsize*patsize]));
   topright.height=patsize;
   topright.width=patsize;
   topright.brightness=(int*)malloc(sizeof(int[patsize*patsize]));
   bottomleft.height=patsize;
   bottomleft.width=patsize;
   bottomleft.brightness=(int*)malloc(sizeof(int[patsize*patsize]));
   bottomright.height=patsize;
   bottomright.width=patsize;
   bottomright.brightness=(int*)malloc(sizeof(int[patsize*patsize]));
   /* 4 patterns allocated */

   t=0;
   while (t<patsize) {
      tt=0;
      while (tt<patsize) {
         topleft.brightness[t*patsize+tt]=255;
         tt++;
      }
      t++;
   }
   
   carglist = arglist_new(argc, argv);
   arglist_addarg (carglist,"--help",0);
   arglist_addarg (carglist,"-h",0);
   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

   imrefer=loadim(arglist_parameter(carglist,"VOIDARGS",0));
   if (imrefer==NULL) {
      printerrorstring(argv[0],"Error loading reference image");
      printusagestring();
      return -1;
   }
   /*Load Reference file*/

   imsource=loadim(arglist_parameter(carglist,"VOIDARGS",1));
   if (imsource==NULL) {
      printerrorstring(argv[0],"Error loading source image");
      printusagestring();
      return -1;
   }
   /*Load test file*/

   blur(&imtmp,imrefer,blurval);
   /*blur reference image to eliminate scanner clutter*/

   enhance(&imdest,imtmp,enhsize,enhmul,enhqual);
   /*create 1st derivation of reference*/

   topleft.height=(patsize*enhqual)/100;
   topleft.width=(patsize*enhqual)/100;
   t=(widthim(imdest)+heightim(imdest))/16;
   position=findpattern(imdest,topleft,0,0,t,t);
   x21=(position.x*100)/enhqual;
   y21=(position.y*100)/enhqual;
   position=findpattern(imdest,topleft,widthim(imdest),0,t,t);
   x22=(position.x*100)/enhqual;
   y22=(position.y*100)/enhqual;
   position=findpattern(imdest,topleft,0,heightim(imdest),t,t);
   x23=(position.x*100)/enhqual;
   y23=(position.y*100)/enhqual;
   position=findpattern(imdest,topleft,widthim(imdest),heightim(imdest),t,t);
   x24=(position.x*100)/enhqual;
   y24=(position.y*100)/enhqual;
   /*find positions of 4 nice features to compare destination against*/

   destroyim(imdest);
   /*discard enhanced reference*/

   fprintf(stderr,"using reference positions:\n %i,%i\t\t%i,%i\n %i,%i\t\t%i,%i\n",x21,y21,x22,y22,x23,y23,x24,y24);
   
   topleft.height=patsize;
   topleft.width=patsize;
   t=0;
   while (t<patsize) {
      tt=0;
      while (tt<patsize) {
         topleft.brightness[t*patsize+tt]=pixelbrightim(imrefer,tt+x21,t+y21);
         topright.brightness[t*patsize+tt]=pixelbrightim(imrefer,tt+x22,t+y22);
         bottomleft.brightness[t*patsize+tt]=pixelbrightim(imrefer,tt+x23,t+y23);
         bottomright.brightness[t*patsize+tt]=pixelbrightim(imrefer,tt+x24,t+y24);
         tt++;
      }
      t++;
   }
   /*fill patterns with regions of reference image*/

   t=(widthim(imsource)+heightim(imsource))/16;
   position=findpattern(imsource,topleft,(x21*widthim(imsource))/widthim(imrefer),(y21*heightim(imsource))/heightim(imrefer),t,tt);
   x11=position.x;
   y11=position.y;
   position=findpattern(imsource,topright,(x22*widthim(imsource))/widthim(imrefer),(y22*heightim(imsource))/heightim(imrefer),t,tt);
   x12=position.x;
   y12=position.y;
   position=findpattern(imsource,bottomleft,(x23*widthim(imsource))/widthim(imrefer),(y23*heightim(imsource))/heightim(imrefer),t,tt);
   x13=position.x;
   y13=position.y;
   position=findpattern(imsource,bottomright,(x24*widthim(imsource))/widthim(imrefer),(y24*heightim(imsource))/heightim(imrefer),t,tt);
   x14=position.x;
   y14=position.y;
   /*find corresponding positions in test sample*/

   fprintf(stderr,"found target positions:\n %i,%i\t\t%i,%i\n %i,%i\t\t%i,%i\n",x11,y11,x12,y12,x13,y13,x14,y14);

   scale(&imdest,imsource,widthim(imrefer),heightim(imrefer),x11,y11,x12,y12,x13,y13,x14,y14,x21,y21,x22,y22,x23,y23,x24,y24);
   /* scale the test sample */

   destroyim(imsource);
   /* discard unscaled version */

   
   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(imdest);
   /*We free our memory*/

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


   return 0;
}

