#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fitsio.h>
#include "./swapfloat.c"
#include "./qckisort.c"
#include "./fastmeds.c"
#include "./getdevs.c"

/*
gcc -O2 -o mkdarkavg mkdarkavg.c -lcfitsio -lm
*/

float getavg(short mbox[], int mnum);

int main(int argc, char *argv[])
{
  FILE      *fp, *fout;
  int       i, j, fnum, lnum, ih;
  int       xynum = 1024*1024;
  int       datanum = ((int)(xynum*sizeof(float)/2880)+1)*2880/sizeof(float);
  char      fname1[50], line[50];
  char      *header;
  int       headsize = 2880;
  float     med, stdev; 
  float     *data3;
  char      **fitsarr;
  char      dname[20];
  short     *sbox;
  char      nheader[600] = "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                    END                                                                               ";
  char      nn[1] = " ";

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


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


/*
 read the dark frame list
*/

  if(NULL == (fp = fopen(argv[1], "r"))){
    printf("\n  argv[1] can not be opened \n");
    exit(1);
  }
  lnum = 0;
  while(fgets(line, sizeof(line), fp) != NULL){
    lnum++;
  }
  fclose(fp);

  fitsarr = (char**)malloc(lnum*sizeof(char)*100);
  fnum = 0;
  fp = fopen(argv[1], "r");
  while(fgets(line, sizeof(line), fp) !=NULL){
    sscanf(line, "%s", fname1);
    fitsarr[fnum] = (char*)malloc(100);
    strcpy(fitsarr[fnum], fname1);
    fnum++;
  }
  fclose(fp);

  data1 = (short*)malloc(lnum*xynum*sizeof(short));
  data3 = (float*)malloc(datanum*sizeof(float));
  fout = fopen("mkdark.tmp", "w");

  for(j=0; j<lnum; j++){
    status = 0;
    fits_open_file(&fptr, fitsarr[j], READONLY, &status);
    data2 = (short*)malloc(xynum*sizeof(short));
    fits_read_pix(fptr, TSHORT, fpixel, xynum, NULL, data2, NULL, &status); 
    fits_close_file(fptr, &status);
    if (status){
      fits_report_error(stderr, status);
      /* return(status);  */
    }
    for(i=0; i<xynum; i++){
      data1[i+j*xynum]=data2[i];
    }
    /* getmeds(data2,xynum,&med,&stdev); */
    fastmeds(data2, xynum, &med);
    getdevs(data2, xynum, med, &stdev);


    memcpy(dname, fitsarr[j]+11, 17);
    fprintf(fout, "%s %.1f %.1f\n", dname, med, stdev);
    free(data2);
    free(fitsarr[j]);
  }

  for(i=0; i<xynum; i++){
    sbox = (short*)malloc(lnum*sizeof(short));
    for(j=0; j<lnum; j++){
      sbox[j] = data1[i+j*xynum];
    }
    data3[i] = getavg(sbox, lnum);
    free(sbox);
  }

  for (i=0; i<datanum; i++){
    swapfloat(&data3[i]);
  }

  free(fitsarr);
  free(data1); 
  fclose(fout); 

  header = (char*)malloc(headsize*sizeof(char)+1);
  for(ih=0; ih<560; ih++){
    header[ih] = nheader[ih];
  }
  for(ih=560; ih<2880; ih++){
    header[ih] = nn[0];
  }

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

  return 0;

}


float getavg(short mbox[], int mnum)
{

  int   i, j, k, cnum;
  float avg, navg, rms;
  short *clip;
  short *iclip;

  avg = 0;
  for(i=0; i<mnum; i++){
    avg = avg + mbox[i];
  }
  avg = avg / mnum;
  rms = 0;
  for(i=0; i<mnum; i++){
    rms = rms + (mbox[i]-avg) * (mbox[i]-avg);
  }
  rms = sqrt(rms/mnum);

  for(k=0; k<5; k++){
    cnum = 0;
    iclip = (short*)malloc(mnum*sizeof(short));
    for(i=0; i<mnum; i++){
      if(fabs(mbox[i]-avg)<3*rms){
	 iclip[i] = 1;
         cnum++;
      } else {
	 iclip[i] = 0;
      }
    }
    clip = (short*)malloc(cnum*sizeof(short));
    j = 0;
    navg = 0;
    for(i=0; i<mnum; i++){
      if(iclip[i] == 1){
        clip[j] = mbox[i];
        navg = navg + mbox[i];
        j++;
      }  
    }
    free(iclip);
    avg = navg / cnum;
    rms = 0;
    for(i=0; i<cnum; i++){
      rms = rms + (clip[i]-avg) * (clip[i]-avg);
    }
    rms = sqrt (rms / cnum);
    free(clip);
  }

  return avg;

}

