/**************************************************************

amass.c (C-Munipack project)
Air-mass coefficient computation
Copyright (C) 2003 David Motl, dmotl@volny.cz

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <limits.h>

#include "comfun.h"
#include "console.h"
#include "cmpack_common.h"
#include "cmpack_amass.h"
#include "cmpack_hcorr.h"
#include "trajd.h"

/**********************   PUBLIC FUNCTIONS   ***************************/

/* Open output table, start reading sequence */
int cmpack_fset_plot(CmpackFrameSet *fset, CmpackTable **ptable, 
	CmpackTableType type, CmpackFSetColumns cols, int object_index, int aperture_index, 
	const char *objname, double ra, double declination, 
	const char *location, double longitude, double latitude, CmpackConsole *con)
{	
	int		res, jd_prec, off_column, hc_column, tmp_column;
	int		hjd_column, exp_column, fil_column, fname_column, aper_valid;
	int		id_column, jd_column, altitude_column, airmass_column;
	int		pos_column, sky_column, fwhm_column, mag_column;
	char	msg[MAXLINE];
	CmpackTable *table;
	CmpackFrameSetInfo info;
	CmpackFrameInfo frame;
	CmpackPhtObject object;
	CmpackPhtData data;
	CmpackPhtAperture aper;

	*ptable = NULL;
	
	cmpack_fset_get_info(fset, CMPACK_FS_JD_PREC, &info);
	jd_prec = info.jd_prec;

	/* Create table */
	table = cmpack_tab_init(type);

	id_column = jd_column = airmass_column = altitude_column = off_column = -1;
	hc_column = hjd_column = tmp_column = exp_column = fil_column = fname_column = -1;
	pos_column = sky_column = fwhm_column = mag_column = -1;
	if (cols & CMPACK_FC_FRAME)
		id_column = cmpack_tab_add_column_int(table, "FRAME", 0, INT_MAX, -1);
	if (cols & CMPACK_FC_JULDAT)
		jd_column = cmpack_tab_add_column_dbl(table, "JD", jd_prec, 1e6, 1e99, INVALID_JD);
	if (cols & CMPACK_FC_HELCOR)
		hc_column = cmpack_tab_add_column_dbl(table, "HELCOR", jd_prec, -1.0, 1.0, INVALID_HCORR);
	if (cols & CMPACK_FC_HJD)
		hjd_column = cmpack_tab_add_column_dbl(table, "JDHEL", jd_prec, 1e6, 1e99, INVALID_JD);
	if (cols & CMPACK_FC_AIRMASS)
		airmass_column  = cmpack_tab_add_column_dbl(table, "AIRMASS", AMASS_PRECISION, 0.0, 1e99, INVALID_AMASS);
	if (cols & CMPACK_FC_ALTITUDE)
		altitude_column  = cmpack_tab_add_column_dbl(table, "ALTITUDE", ALT_PRECISION, -90.0, 90.0, INVALID_ALT);
	if (cols & CMPACK_FC_OFFSET) {
		off_column = cmpack_tab_add_column_dbl(table, "OFFSETX", POS_PRECISION, -1e99, 1e99, 0.0);
		cmpack_tab_add_column_dbl(table, "OFFSETY", POS_PRECISION, -1e99, 1e99, 0.0);
	}
	if (cols & CMPACK_FC_CCDTEMP) 
		tmp_column = cmpack_tab_add_column_dbl(table, "CCDTEMP", TEMP_PRECISION, -999.0, 999.0, INVALID_TEMP);
	if (cols & CMPACK_FC_EXPTIME)
		exp_column = cmpack_tab_add_column_dbl(table, "EXPOSURE", EXP_PRECISION, 0, 1e99, INVALID_EXPTIME);
	if (cols & CMPACK_FC_FILTER)
		fil_column = cmpack_tab_add_column_str(table, "FILTER");
	if (cols & CMPACK_FC_FILENAME)
		fname_column = cmpack_tab_add_column_str(table, "FILENAME");

	/* Object properties */
	if (cols & CMPACK_FC_CENTER) {
		pos_column = cmpack_tab_add_column_dbl(table, "X", POS_PRECISION, 0, 65536.0, INVALID_XY);
		cmpack_tab_add_column_dbl(table, "Y", POS_PRECISION, 0, 65536.0, INVALID_XY);
	}
	if (cols & CMPACK_FC_SKY) 
		sky_column = cmpack_tab_add_column_dbl(table, "SKY", SKY_PRECISION, -999.0, 1e99, INVALID_SKY);
	if (cols & CMPACK_FC_FWHM) 
		fwhm_column = cmpack_tab_add_column_dbl(table, "FWHM", FWHM_PRECISION, 0.0, 1e99, INVALID_FWHM);
	if (cols & CMPACK_FC_MAG) {
		mag_column = cmpack_tab_add_column_dbl(table, "MAG", MAG_PRECISION, -99.0, 99.0, INVALID_MAG);
		cmpack_tab_add_column_dbl(table, "s1", MAG_PRECISION, 0.0, 9.0, INVALID_MAGERR);
	}
	
	/* Table header */
	res = cmpack_fset_rewind(fset);
	if (res==0) {
		if (cmpack_fset_get_frame(fset, CMPACK_FI_FILTER, &frame)==0 && frame.filter && frame.filter[0]!='\0')
			cmpack_tab_pkys(table, "Filter", frame.filter);
		if (cmpack_fset_get_frame_object(fset, object_index, CMPACK_PO_REF_ID, &object)==0 && object.ref_id>0)
			cmpack_tab_pkyi(table, "Object", object.ref_id);
	}

	aper_valid = cmpack_fset_get_aperture(fset, aperture_index, CMPACK_PA_ID | CMPACK_PA_RADIUS, &aper) == CMPACK_ERR_OK;
	if (aper_valid)
		cmpack_tab_pkyi(table, "Aperture", aper.id);
	
	/* Process frames */
	res = cmpack_fset_rewind(fset);
	while (res==0) {
		int frame_valid, object_valid = 0, data_valid = 0;
		cmpack_tab_append(table);
		frame_valid = cmpack_fset_get_frame(fset, CMPACK_FI_ID | CMPACK_FI_JULDAT | CMPACK_FI_HELCOR | 
			CMPACK_FI_AIRMASS_ALT | CMPACK_FI_FILTER | CMPACK_FI_EXPTIME | CMPACK_FI_CCDTEMP |
			CMPACK_FI_OFFSET | CMPACK_FI_FILENAME, &frame) == CMPACK_ERR_OK;
		if (object_index>=0 && (pos_column>=0 || sky_column>=0 || fwhm_column>=0)) {
			object_valid = cmpack_fset_get_frame_object(fset, object_index, CMPACK_PO_REF_ID | 
				CMPACK_PO_CENTER | CMPACK_PO_SKY | CMPACK_PO_FWHM, &object) == CMPACK_ERR_OK;
		}
		if (aperture_index>=0 && mag_column>=0) 
			data_valid = cmpack_fset_get_data(fset, object_index, aperture_index, &data) == CMPACK_ERR_OK;

		/* Check frame header */
		if (!frame_valid)
			continue;

		if ((id_column>=0 && frame.frame_id<0)) {
			if (frame.filename) 
				sprintf(msg, "%s: Invalid frame identifier", frame.filename);
			else
				strcpy(msg, "Invalid frame identifier");
			printout(con, 0, msg);
			continue;
		}
		if (frame.juldat<=0) {
			if (frame.filename) 
				sprintf(msg, "%s: Invalid Julian date of observation", frame.filename);
			else
				strcpy(msg, "Invalid Julian date of observation");
			printout(con, 0, msg);
			continue;
		}

		/* Update computed values */
		if ((res==0) && (airmass_column>=0 || altitude_column>=0)) {
			res = cmpack_airmass(frame.juldat, ra, declination, longitude, latitude, 
				&frame.airmass, &frame.altitude);
		}
		if ((res==0) && (hc_column>=0 || hjd_column>=0)) {
			frame.helcor = cmpack_helcorr(frame.juldat, ra, declination);
			frame.valid_helcor = 1;
		}
		if (res!=0)
			return res;

		/* Fill in the table columns */
		if (id_column>=0)
			cmpack_tab_ptdi(table, id_column, frame.frame_id);
		if (jd_column>=0 && frame.juldat>0)
			cmpack_tab_ptdd(table, jd_column, frame.juldat);
		if (hc_column>=0 && frame.helcor>=-1.0 && frame.helcor<=1.0) 
			cmpack_tab_ptdd(table, hc_column, frame.helcor);
		if (hjd_column>=0 && frame.juldat>0 && frame.helcor>=-1.0 && frame.helcor<=1.0)
			cmpack_tab_ptdd(table, hjd_column, frame.juldat + frame.helcor);
		if (altitude_column>=0 && frame.altitude>=-90.0 && frame.altitude<=90.0)
			cmpack_tab_ptdd(table, altitude_column, frame.altitude);
		if (airmass_column>=0 && frame.airmass>=1.0)
			cmpack_tab_ptdd(table, airmass_column, frame.airmass);
		if (off_column>=0) {
			cmpack_tab_ptdd(table, off_column, frame.offset[0]);
			cmpack_tab_ptdd(table, off_column+1, frame.offset[1]);
		}
		if (tmp_column>=0 && frame.exptime>-999.0 && frame.exptime<999.0)
			cmpack_tab_ptdd(table, tmp_column, frame.ccdtemp);
		if (exp_column>=0 && frame.exptime>0)
			cmpack_tab_ptdd(table, exp_column, frame.exptime);
		if (fil_column>=0 && frame.filter)
			cmpack_tab_ptds(table, fil_column, frame.filter);
		if (fname_column>=0 && frame.filename)
			cmpack_tab_ptds(table, fname_column, frame.filename);
		if (pos_column>=0 && object_valid && object.x>=0 && object.y>=0) {
			cmpack_tab_ptdd(table, pos_column, object.x);
			cmpack_tab_ptdd(table, pos_column+1, object.y);
		}
		if (sky_column>=0 && object_valid && object.skymed>0) 
			cmpack_tab_ptdd(table, sky_column, object.skymed);
		if (fwhm_column>=0 && object_valid && object.fwhm>0) 
			cmpack_tab_ptdd(table, fwhm_column, object.fwhm);
		if (mag_column>=0 && data_valid && data.mag_valid) {
			cmpack_tab_ptdd(table, mag_column, data.magnitude);
			if (data.mag_error>0)
				cmpack_tab_ptdd(table, mag_column+1, data.mag_error);
		}

		/* Debug printout */
		if (is_debug(con)) {

			/* Frame properties */
			sprintf(msg, "FRAME      : %d", frame.frame_id);
			printout(con, 1, msg);
			if (jd_column>=0) {
				sprintf(msg, "JD       : %.*f", jd_prec, frame.juldat); 
				printout(con, 1, msg);
			}
			if (airmass_column>=0) {
				sprintf(msg, "AIRMASS  : %.*f", AMASS_PRECISION, frame.airmass); 
				printout(con, 1, msg);
			}
			if (altitude_column>=0) {
				sprintf(msg, "ALTITUDE : %.*f deg", ALT_PRECISION, frame.altitude); 
				printout(con, 1, msg);
			}
			if (off_column>=0) {
				sprintf(msg, "OFFSET   : %.*f %.*f pxl", POS_PRECISION, frame.offset[0], POS_PRECISION, frame.offset[1]); 
				printout(con, 1, msg);
			}
			if (hjd_column>=0) {
				sprintf(msg, "HJD      : %.*f", jd_prec, frame.juldat + frame.helcor); 
				printout(con, 1, msg);
			}
			if (hc_column>=0) {
				sprintf(msg, "HELCORR  : %.*f", jd_prec, frame.helcor); 
				printout(con, 1, msg);
			}
			if (tmp_column>=0) {
				sprintf(msg, "CCDTEMP  : %.*f C", TEMP_PRECISION, frame.ccdtemp); 
				printout(con, 1, msg);
			}
			if (exp_column>=0) {
				sprintf(msg, "EXPOSURE : %.*f s", EXP_PRECISION, frame.exptime); 
				printout(con, 1, msg);
			}
			if (fil_column>=0) {
				sprintf(msg, "FILTER  : %s", (frame.filter ? frame.filter : "n/a")); 
				printout(con, 1, msg);
			}
			if (fname_column>=0) {
				sprintf(msg, "FILENAME: %s", (frame.filename ? frame.filename : "n/a")); 
				printout(con, 1, msg);
			}

			/* Object properties */
			if (object_valid) {
				sprintf(msg, "OBJECT: %d", object.ref_id);
				printout(con, 1, msg);
				if (pos_column>=0) {
					sprintf(msg, "CENTER: %.*f, %.*f pxl", POS_PRECISION, object.x, POS_PRECISION, object.y); 
					printout(con, 1, msg);
				}
				if (sky_column>=0) {
					sprintf(msg, "SKY: %.*f +- %.*f ADU", SKY_PRECISION, object.skymed, SKY_PRECISION, object.skysig); 
					printout(con, 1, msg);
				}
				if (fwhm_column>=0) {
					sprintf(msg, "FWHM: %.*f pxl", FWHM_PRECISION, object.fwhm); 
					printout(con, 1, msg);
				}
			}

			/* Aperture data */
			if (aper_valid && data_valid) {
				sprintf(msg, "APERTURE: #%d (%.2f pxl)", aper.id, aper.radius);
				printout(con, 1, msg);
				if (mag_column>=0) {
					sprintf(msg, "MAG: %.*f +- %.*f mag", MAG_PRECISION, data.magnitude, MAG_PRECISION, data.mag_error); 
					printout(con, 1, msg);
				}
			}
		}
		res = cmpack_fset_next(fset);
	}

	*ptable = table;
	return CMPACK_ERR_OK;
}
