/**************************************************************************
 *                                                                        *
 * Copyright (c) 1996 Michael Richmond and Richard Treffers               *
 *                                                                        *
 *                    This software may be copied and distributed for     *
 *                    educational, research and not for profit services   *
 *                    provided that this copyright and statement are      *
 *                    included in all such copies.                        *
 *                                                                        *
 **************************************************************************/


/*
	IMPLANT file0 [file1,row,col]  [file2,row,col] [..]  [add]

	writes file1 into file0 with origin (of file1) at row,col of
	file0. The new data overwrites the existing data, unless
	the 'add' mode is specified.

	added 'fits_resetscale() and the 'copydata()' function to make
	sure that BSCALE/BZERO are reset to 1/0 whenever this program runs. 
	also, it is an undocumented 'feature' that the keyword 'add' means
	the same thing as 'overlay'.  
	   ... MWR 8/1/1993
	11/3/94 - increase MAXPLANT 10-->100 -rrt
	4/12/97 - fixed bug that over-wrote one extra column. -MWR
*/
#include "pcvista.h"
#include "fits.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <string.h>

#define MAXPLANT    	100		/* maximum number of files to glue together */

struct p_type{
	char fname[NBUF];
	int row;
	int col;
};

#ifdef PROTO
int main(int, char **);
static void do_plant( FITS_HANDLE fin,FITS_HANDLE fout,
	int nrow,int ncol, struct p_type *pp,int overlay_flag);
static void copydata(FITS_HANDLE, FITS_HANDLE, int, int);
static int crack_field(char *in, struct p_type *pp);
#else
static void do_plant();
int main();
static void copydata();
static int crack_field();
#endif

#define USAGE "usage: implant file [fileb,row,col] [...] [overlay] [help]"


int
main(argc,argv)
int argc;
char *argv[];
{
	FITS_HANDLE fin, fout;
	int i;
	int  nrow, ncol;
#ifdef OUTFILE
	char *gotit;
#endif
	char outfile[NBUF];
	int overlay_flag=0;
	int new_file=0;
	int nplant=0;
	struct p_type p[MAXPLANT];

	if(argc == 1) {
		error(-1,USAGE); 
	}
	if (strcmp(argv[1], "help") == 0) {
		printf("%s\n", USAGE);
		exit(0);
	}

	fin = fits_open(argv[1], "r", &nrow, &ncol);
	strcpy(outfile,argv[1]);

	for(i = 2; i < argc; i++) {
		if (keyword("help", argv[i])) {
			printf("%s\n", USAGE);
			exit(0);
		}
#ifdef OUTFILE
		/* This is dangerous !! */
		if ((gotit = find("outfile", argv[i])) != NULL) {
			strcpy(outfile,gotit);
			new_file=1;
			continue;
		}
#endif
		if (keyword("add", argv[i])){
			overlay_flag = 1;
			continue;
		}
		if (keyword("overlay", argv[i])){
			overlay_flag = 1;
			continue;
		}
		/* arg must be another file name if we got here */
		if(crack_field(argv[i],&p[nplant++])){
			fprintf(stderr,"improperly formed argument '%s'\n",argv[i]);
			exit(1);
		}
		if (nplant == MAXPLANT)
			error(1,"implant: too many files");
	}

	fout = fits_open(outfile, new_file?"w":"x", &nrow, &ncol);

	if(new_file) {
		fits_copyheader(fin,fout, FITS_CHECK);
	}
	else {
		/* we have to copy the entire file onto itself first, to re-set
		   the data to BSCALE=1/BZERO=0.  Painful, but necessary */
		copydata(fin, fout, nrow, ncol);
		fits_resetscale(fin);
	}	
			
	for(i=0; i<nplant; i++){
		do_plant(fin,fout,nrow,ncol,&p[i],overlay_flag);
	}

	fits_close(fout);

	exit(0);
}

static void do_plant(fin,fout,nrow,ncol,pp,overlay_flag)
FITS_HANDLE fin,fout;
int nrow,ncol;
struct p_type *pp;
int overlay_flag;
{
	int i,nrow_other,ncol_other,row;
	int sr,er,sc,ec,nc;
	FITS_HANDLE fother;
	int16 data[NMAX], other[NMAX];

	fother=fits_open(pp->fname,"r",&nrow_other,&ncol_other);

	/* now determine the limits in the reference image */
	sr=(pp->row > 0) ? pp->row : 0 ;
	er=((pp->row + nrow_other) < nrow ) ? 
			(pp->row+nrow_other) :  nrow;
	sc=(pp->col > 0) ? pp->col : 0 ;
	ec=((pp->col + (ncol_other-1)) < ncol ) ? 
			(pp->col+(ncol_other-1)) :  ncol;
	nc=ec-sc+1;

	for (row = sr; row < er ; row++) {
	    fits_get_data(fother, row-pp->row, sc-pp->col, other, nc);
		if(overlay_flag){
	    	fits_get_data(fin, row, sc, data, nc);
			for (i = 0; i < nc; i++)
				other[i]+=data[i];		
		}
		fits_put_data(fout, row, sc, other, nc);
	}
}

/*	returns 1 if error
*/

static int
crack_field(in,pp)
char *in;
struct p_type *pp;
{
	int i,nfield;
	char copy[NBUF];

	strcpy(copy,in);
	for(i=0; copy[i]; i++)
		if(copy[i] == ',')
			copy[i]=' ';
	nfield=sscanf(copy,"%s %d %d", pp->fname,&pp->row,&pp->col);

	return (nfield-3);
}

static void copydata(fh,fout,nrow,ncol)
FITS_HANDLE fh,fout;
int nrow,ncol;
{
        int i;
        int16 data[NMAX];
 
        for(i=0; i<nrow; i++){
                fits_get_data(fh,i,0,data,ncol);
                fits_put_data_fast(fout,data,ncol);
        }
}

