#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <fitsio.h>
#include "./qckisort.c"
#include "./qcksort.c"
#include "./swapfloat.c"
#include "./getmedf.c"
#include "./getmedi.c"

#ifdef _OPENMP
#include <omp.h>
#endif

/*

twflatcom.c
gcc -O2 -o twflatcom twflatcom.c -lcfitsio -lm

if you have openmp(gcc4.2 or later) and cfitsio 3.181 or later
gcc -O2 -o twflatcom twflatcom.c -lcfitsio -lm -fopenmp

*/

int readfz(short data[], char *fname);
void mkheader(char *header, int ncomb);

int main (int argc, char**argv)
{

  FILE  *fl,*fp;
  char  line[50];
  char  band[2]="a";
  char  date[7],num1[5],num2[5];
  char  fnamefz1[100],fnameic1[100],fname1[100];  
  char  fnamefz2[100],fnameic2[100],fname2[100];  
  char  fits1[100],fits2[100];
  float fdum;
  int   i,xynum=1024*1024,datanum;
  short *data1,*data2;
  int   *data3;
  int   fzstat;
  float midpt;
  float *data4,*data5,*mbox;
  int   lnum,ifnum,j;
  char  *header;
  int   headsize=2880;
  char  comment[2]="0";
  char  **fits1arr,**fits2arr;

  if (argc < 3){
    fprintf(stderr, "usage : twflatcom list out.fits\n");
    return 0;
  }

  strncpy(band,argv[1],1);
  if(strcmp(band,"j")!=0 && strcmp(band,"h")!=0 && strcmp(band,"k")!=0){
    printf("The list name is wrong. Not starting with j,h,k.\n");
    exit(1);
  }

  if(NULL==(fl=fopen(argv[1],"r"))){
    printf("\n [%s] can not be opened. \n",argv[1]);
    exit(1);
  }
  lnum=0;
  while(fgets(line, sizeof(line), fl) !=NULL){
    sscanf(line, "%6s %4s %4s %f %f\n", date,num1,num2,&fdum,&fdum);
    strncpy(comment,date,1);
    if(strcmp(comment,"#")!=0){
      lnum++;
    }
  }
  fclose(fl);

  if(lnum==0){
    printf("\n All the lines are disabled by comment out in [%s]. \n",argv[1]);
    exit(1);
  }

  data4=(float*)malloc(lnum*xynum*sizeof(float));
  fits1arr=(char**)malloc(lnum*sizeof(char)*100);
  fits2arr=(char**)malloc(lnum*sizeof(char)*100);

  ifnum=0;
  fl=fopen(argv[1],"r");
  while(fgets(line, sizeof(line), fl) !=NULL){
    sscanf(line, "%6s %4s %4s %f %f\n", date,num1,num2,&fdum,&fdum);
    strncpy(comment,date,1);
    if(strcmp(comment,"#")==0) continue;

    strcpy(fname1,"../");
    strcat(fname1,date);
    strcat(fname1,"/rawdata/");
    strcat(fname1,band);
    strcat(fname1,date);
    strcat(fname1,"_");

    strcpy(fname2,fname1);

    strcat(fname1,num1);
    strcat(fname1,".fits");
    strcpy(fnamefz1,fname1);
    strcat(fnamefz1,".fz");
    strcpy(fnameic1,fname1);
    strcat(fnameic1,".ic");

    strcat(fname2,num2);
    strcat(fname2,".fits");
    strcpy(fnamefz2,fname2);
    strcat(fnamefz2,".fz");
    strcpy(fnameic2,fname2);
    strcat(fnameic2,".ic");

    if(access(fname1,0)==0) strcpy(fits1,fname1);
    if(access(fnamefz1,0)==0){
       strcpy(fits1,fnamefz1);
       strcat(fits1,"[1]");
    }
    if(access(fnameic1,0)==0){
       strcpy(fits1,fnameic1);
       strcat(fits1,"[1]");
    }
    if(access(fname2,0)==0) strcpy(fits2,fname2);
    if(access(fnamefz2,0)==0){
       strcpy(fits2,fnamefz2);
       strcat(fits2,"[1]");
    }
    if(access(fnameic2,0)==0){
        strcpy(fits2,fnameic2);
        strcat(fits2,"[1]");
    }

    fits1arr[ifnum]=(char*)malloc(100);
    fits2arr[ifnum]=(char*)malloc(100);
    strcpy(fits1arr[ifnum],fits1);
    strcpy(fits2arr[ifnum],fits2);

    ifnum++;

    strcpy(fname1,"");
    strcpy(fnamefz1,"");
    strcpy(fnameic1,"");
    strcpy(fname2,"");
    strcpy(fnamefz2,"");
    strcpy(fnameic2,"");

  }

#ifdef _OPENMP
#pragma omp parallel for private(data1,data2,data3,fzstat,midpt,i)
#endif
  for(j=0; j<ifnum; j++){

    data1=(short*)malloc(xynum*sizeof(short));
    data2=(short*)malloc(xynum*sizeof(short));

    fzstat=readfz(data1,fits1arr[j]);
    if(fzstat==1){
      printf("fzstat==1\n");
    }

    fzstat=readfz(data2,fits2arr[j]);
    if(fzstat==1){
      printf("fzstat==1\n");
    }

    data3=(int*)malloc(xynum*sizeof(int));
    for(i=0; i<xynum; i++){
      data3[i]=data1[i]-data2[i];
    }
    midpt=getmedi(data3,xynum,0,10000);

    for(i=0; i<xynum; i++){
      data4[i+j*xynum]=data3[i]/midpt;
    }

    free(data1);
    free(data2);
    free(data3);

  }

  free(fits1arr);
  free(fits2arr);

  datanum=((int)(xynum*sizeof(float)/2880)+1)*2880/sizeof(float);
  data5=(float*)malloc(datanum*sizeof(float));
#ifdef _OPENMP
#pragma omp parallel for private(mbox,j,midpt)
#endif
  for(i=0; i<xynum; i++){
    mbox=(float*)malloc(lnum*sizeof(float));
    for(j=0; j<lnum; j++){
      mbox[j]=data4[i+j*xynum];
    }
    midpt=getmedf(mbox,lnum,0,2);
    data5[i]=midpt;

    free(mbox);
  }
  free(data4);

  for (i=0; i<datanum; i++){
    swapfloat(&data5[i]);
  }
  
  header=(char*)malloc(headsize*sizeof(char)+1);
  mkheader(header,lnum);

  if(NULL==(fp=fopen(argv[2],"wb"))){
      printf("\n [%s] can not be opened \n",argv[2]);
      exit(1);
  }
  fwrite(header,sizeof(char),headsize,fp);
  fwrite(data5,sizeof(float),datanum,fp);
  fclose(fp);

  free(header);
  free(data5);


  return 0;

}


int readfz(short data[], char *fname)
{

  fitsfile  *fptr;         
  int       status = 0;  /* MUST initialize status */
  int       datanum=1024*1024;
  long      fpixel[2]={1,1};

  fits_open_file(&fptr, fname, READONLY, &status);
  fits_read_pix(fptr,TSHORT,fpixel,datanum,NULL,data,NULL,&status); 
  fits_close_file(fptr, &status);

  if (status)          /* print any error messages */
    fits_report_error(stderr, status);
  return(status);

}


void mkheader(char *header, int ncomb)
{
  int       ih;
  int       id3,id2,id1;
  char      cd3[2],cd2[2],cd1[2];
  char      nheader[760]="SIMPLE  =                    T / Fits standard                                  BITPIX  =                  -32 / Bits per pixel                                 NAXIS   =                    2 / Number of axes                                 NAXIS1  =                 1024 / Axis length                                    NAXIS2  =                 1024 / Axis length                                    EXTEND  =                    F / File may contain extensions                    NCOMBINE=                      / NCOMBINE                                       OBJECT  = 'flat'               / OBJECT NAME                                    END                                                                               ";
  char      nn[1]=" ";


  for(ih=0; ih<720; ih++){
    header[ih]=nheader[ih];
  }
  for(ih=720; ih<2880; ih++){
    header[ih]=nn[0];
  }

  id3=ncomb/100;
  id2=(ncomb-id3*100)/10;
  id1=ncomb-id3*100-id2*10;

  sprintf(cd3, "%d", id3);
  sprintf(cd2, "%d", id2);
  sprintf(cd1, "%d", id1);

  if(id3>0){
    header[507]=cd3[0];
  }
  if(id2>0){
    header[508]=cd2[0];
  }
  header[509]=cd1[0];


}

