#include <stdlib.h>
#include <math.h>
#include <string.h>
/*#include <time.h>*/
#include <fits.h>
#include <misc.h>

#ifdef IBM
#include <strings.h>
#endif

#ifdef WIN32
//#include "../utils/winsupp.h"
#endif

int main(void)
{
	char fname1[256];
	char fname2[256];
	char fname3[256];
	char fname4[256];
	char fname5[256];
	char fname6[256];
	
	int niter, iter;
	ULONG i;
	float thresh, flux, sum, sukn, suk, xmax, th;
	Fits dbeam, dmap, xmap, w, imap, cxmap, lastxmap;
/*	time_t begin, end;*/
	
	printf("input dirty map : ");
	scanf("%s", fname1);
	printf("input dirty beam : ");
	scanf("%s", fname2);
	printf("input restart name: ");
	scanf("%s", fname4);
	printf("output lucy name: ");
	scanf("%s", fname3);
	printf("output restart name: ");
	scanf("%s", fname5);
	printf("output reconvolved clean name: ");
	scanf("%s", fname6);

	printf("number of iterations: ");
	niter = get_integer(1, 1000000);
	printf("threshhold in fraction of peak flux in dirty map: ");
	thresh = get_float();
	
	dmap.ReadFITS(fname1);
	dmap.setType(R4);
	dmap.clip(0.0, -1.0);
	flux = dmap.get_flux();
	
	dbeam.ReadFITS(fname2);
	dbeam.setType(R4);
	sum = dbeam.get_flux();
	xmax = dmap.get_max();
	dbeam /= sum;
	dbeam.fft();
//	dbeam.conj();
	
// should read input restart file here

	if (strncasecmp(fname4, "none", 4) != 0) {
		xmap.ReadFITS(fname4);
		xmap.setType(R4);
	} else {
		printf("NO RESTART IMAGE SPECIFIED...USING DIRTYMAP\n");
		xmap.copy(dmap);
	}
	
	if (fabs(thresh) < EPS) thresh = -0.1;
	th = fabs(thresh) * xmax;
	printf("th = %f\n", th);
	w.copy(dmap);
	
	for (i = 0; i < dmap.Nelements(); i++)
		if (dmap.r4data[i] > th) w.r4data[i] = 1.0;
		else w.r4data[i] = 0.0;
	
// should compute new threshold here

	if (thresh < 0.0) {
		float er;
		
		sum = suk = sukn = 0.0;
		for (i = 0; i < w.Nelements(); i++) {
			if (w.r4data[i] < 0.5) {
				sum += dmap.r4data[i];
				suk += sqr(dmap.r4data[i]);
				sukn++;
			}
		}
		printf("%f %f %f\n", sukn, sum*sum/sukn, suk);
		er = sqrt(fabs(suk-sum*sum/sukn) / (sukn - 1.0));
		sum /= sukn;
		printf("%f %f\n", sum, er);
		thresh = sum + 3.0 * er;
		printf("%f\n", thresh);
		for (i = 0; i < dmap.Nelements(); i++)
			if (dmap.r4data[i] > th) w.r4data[i] = 1.0;
	}

// should handle restart file here

	cxmap.copy(xmap);
	
	if (strncasecmp(fname4, "none", 4) != 0) {
		cxmap.fft();
		imap.copy(cxmap);
		imap *= dbeam;
		imap.fft();
		imap.reass();
		sum = imap.get_flux();
		imap *= flux/sum;
		
//	computing ratio map in area where weighting function is unity

		for (i = 0; i < imap.Nelements(); i++) {
			if ((w.r4data[i] < 0.5) || (imap.r4data[i] < 1e-6))
				imap.r4data[i] = 1.0;
			else
				imap.r4data[i] = dmap.r4data[i] / imap.r4data[i];
		}
		
//	convolving ratio map with dirty beam

		imap.fft();
		imap *= dbeam;
		imap.fft();
		imap.reass();
		imap /= (float)(imap.Nelements());
		
//	multiplying current lucy map with convolved ratio map

		xmap *= imap;
		sum = xmap.get_flux();
		xmap *= flux/sum;
	}
	
	lastxmap.copy(xmap);
	cxmap.copy(xmap);
	cxmap.fft();
	
/*	begin = time(NULL);*/

	for (iter = 0; iter <	niter; iter++) {
		lastxmap.copy(xmap);
		imap.copy(cxmap);
		imap *= dbeam;
		imap.fft();
		imap.reass();
		sum = imap.get_flux();
		imap *= flux/sum;
		
//	computing ratio map in area where weighting function is unity

		for (i = 0; i < imap.Nelements(); i++) {
			if ((w.r4data[i] < 0.5) || (imap.r4data[i] < 1e-6))
				imap.r4data[i] = 1.0;
			else
				imap.r4data[i] = dmap.r4data[i] / imap.r4data[i];
		}
		
//	convolving ratio map with dirty beam

		imap.fft();
		imap *= dbeam;
		imap.fft();
		imap.reass();
		imap /= (float)(imap.Nelements());
		
//	multiplying current lucy map with convolved ratio map

		xmap *= imap;
		sum = xmap.get_flux();
		xmap *= flux/sum;
		
// convolving new iteration with dirty beam

		imap.copy(xmap);
		imap.fft();
		
		cxmap.copy(imap);
		
		imap *= dbeam;
		imap.fft();
		imap.reass();
		imap /= (float)(imap.Nelements());
		
//	renormalizing reconvolved map to flux of input dirty map
		
		sum = imap.get_flux();
		imap *= flux/sum;
		
		sum = sukn = 0.0;
		for (i = 0; i < imap.Nelements(); i++) {
			sum += w.r4data[i]*sqr(dmap.r4data[i]-imap.r4data[i]);
			sukn += w.r4data[i];
		}
		sum = sqrt(sum/(sukn-1));
		
		printf("lucy ===> niter = %i,  sum = %f %f\n", iter+1, sum, sum/thresh);

	}
/*	end = time(NULL);*/
	xmap.WriteFITS(fname3);
	if (strncasecmp(fname5, "none", 4) != 0) lastxmap.WriteFITS(fname5);
	if (strncasecmp(fname6, "none", 4) != 0) imap.WriteFITS(fname6);
	
/*	printf("This took %li seconds\n", end-begin);*/
	
	exit(0);
}
