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

hcor.c (C-Munipack project)
Heliocentric correction
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 <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <limits.h>

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

/**********************   HELPER FUNCTIONS   ********************************/

static double cmpack_hcor2(double la, double be, double ls, double rs)
/* Pocita heliocentrickou korekci */
{
	return -0.00577552*rs*cos(be)*cos(la-ls);
}

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

double cmpack_helcorr(double jd, double ra, double dec)
/* Pocita heliocentrickou korekci */
{
	double ls, rs, la, be;

	cmpack_sun(jd, &ls, &rs);
	cmpack_rdtolb(ra, dec, &la, &be);
	return cmpack_hcor2(la, be, ls, rs);
}

int cmpack_helcorr_table(CmpackTable *tab, const char *objname, double ra, 
	double dec, CmpackConsole *con, CmpackHCorrFlags flags)
{
	int		res, reverse, no_helcor, no_juldat, modify;
	int		jdin_column, jdout_column, hc_column;
	char	msg[MAXLINE];
	double	ls, rs, la, be, jdin, jdout, hcor;
	CmpackTabColumn col;

	reverse   = (flags & CMPACK_HCORR_REVERSE)!=0;
	no_helcor = (flags & (CMPACK_HCORR_NOHELCOR | CMPACK_HCORR_MODIFYJD))!=0;
	no_juldat = (flags & (CMPACK_HCORR_NOJULDAT | CMPACK_HCORR_MODIFYJD))!=0;
	modify    = (flags & CMPACK_HCORR_MODIFYJD)!=0;

	if (is_debug(con)) {
		printout(con, 1, "Configuration parameters:");
		printpard(con, "R.A.", 1, ra, 3);
		printpard(con, "Dec.", 1, dec, 3);
  	}

	/* Find column with JD */
	if (!reverse) {
		jdin_column = cmpack_tab_find_column(tab, "JD");
		if (jdin_column<0)
			jdin_column = cmpack_tab_find_column(tab, "JDGEO");
	} else {
		jdin_column = cmpack_tab_find_column(tab, "JDHEL");
		if (jdin_column<0)
			jdin_column = cmpack_tab_find_column(tab, "JD");
	}
	if (jdin_column<0) {
		printout(con, 0, (!reverse ? "The table does not have column JD" : "The table does not have column JDHEL"));
		return CMPACK_ERR_KEY_NOT_FOUND;
	}

	/* Column which contains the correction value */
	hc_column = -1;
	if (!no_helcor) {
		hc_column = cmpack_tab_find_column(tab, "HELCOR");
		if (hc_column<0)
			hc_column = cmpack_tab_add_column_dbl(tab, "HELCOR", JD_PRECISION, -1.0, 1.0, INVALID_HCORR);
	}

	jdout_column = -1;
	col.name = (!reverse ? "JDHEL" : "JD");
	if (modify) {
		jdout_column = jdin_column;
		cmpack_tab_set_column(tab, jdout_column, CMPACK_TM_NAME, &col);
	} else {
		if (!no_juldat) {
			jdout_column = cmpack_tab_find_column(tab, col.name);
			if (jdout_column<0)
				jdout_column = cmpack_tab_add_column_dbl(tab, col.name, JD_PRECISION, 1e6, 1e99, INVALID_JD);
		}
	}
			
	cmpack_rdtolb(ra, dec, &la, &be);

	res = cmpack_tab_rewind(tab);
	while (res==0) {
		cmpack_tab_gtdd(tab, jdin_column, &jdin);
		if (jdin<=0) {
			printout(con, 0, "Invalid Julian date of observation");
			return CMPACK_ERR_INVALID_JULDAT;
		}
		cmpack_sun(jdin, &ls, &rs);
		hcor = cmpack_hcor2(la, be, ls, rs);
		if (is_debug(con)) {
			sprintf(msg, "%.7f -> %.7f", jdin, hcor);
			printout(con, 1, msg);
		}
		if (jdout_column>=0) {
			jdout = (!reverse ? jdin + hcor : jdin - hcor);
			cmpack_tab_ptdd(tab, jdout_column, jdout);
			cmpack_tab_next(tab);
		}
		if (hc_column>=0)
			cmpack_tab_ptdd(tab, hc_column, hcor);
		res = cmpack_tab_next(tab);
	}
 	return 0;
}

/* Open output table, start reading sequence */
int cmpack_helcorr_curve(CmpackFrameSet *fset, CmpackTable **ptable, const char *objname, 
	double ra, double dec, CmpackHCorrFlags flags, CmpackConsole *con)
{	
	int cols = CMPACK_FC_JULDAT | CMPACK_FC_HELCOR | CMPACK_FC_HJD;

	if (flags & CMPACK_HCORR_FRAME_IDS)
		cols |= CMPACK_FC_FRAME;
	if (flags & CMPACK_HCORR_NOHELCOR)
		cols &= ~CMPACK_FC_HELCOR;
	if (flags & CMPACK_HCORR_NOJULDAT)
		cols &= ~CMPACK_FC_HJD;

	return cmpack_fset_plot(fset, ptable, CMPACK_TABLE_UNSPECIFIED, (CmpackFSetColumns)cols, 
		0, 0, objname, ra, dec, 0, 0, 0, con);
}

/* Update heliocentric correction in the frame set  */
int cmpack_helcorr_fset(CmpackFrameSet *fset, const char *objname, double ra, 
	double dec, CmpackConsole *con)
{
	int		res;
	char	msg[MAXLINE];
	double	hcor, ls, rs, la, be;
	CmpackFrameInfo info;
	CmpackFrameSetInfo obj;

	/* Print parameters */
	if (is_debug(con)) {
		printout(con, 1, "Configuration parameters:");
		printpard(con, "R.A.", 1, ra, 3);
		printpard(con, "Dec.", 1, dec, 3);
  	}

	obj.objcoords.ra_valid = 1;
	obj.objcoords.ra = ra;
	obj.objcoords.dec_valid = 1;
	obj.objcoords.dec = dec;
	obj.objcoords.designation = (char*)objname;
	cmpack_fset_set_info(fset, CMPACK_FS_OBJECT, &obj);

	cmpack_rdtolb(ra, dec, &la, &be);

	res = cmpack_fset_rewind(fset);
	while (res==0) {
		cmpack_fset_get_frame(fset, CMPACK_FI_JULDAT, &info);
		info.valid_helcor = 0;
		info.helcor = 0.0;
		if (info.juldat<=0) {
			printout(con, 0, "Invalid Julian date of observation");
		} else {
			cmpack_sun(info.juldat, &ls, &rs);
			hcor = cmpack_hcor2(la, be, ls, rs);
			if (is_debug(con)) {
				sprintf(msg, "%.7f -> %.7f", info.juldat, hcor);
				printout(con, 1, msg);
			}
			info.valid_helcor = 1;
			info.helcor = hcor;
		}
		cmpack_fset_set_frame(fset, CMPACK_FI_HELCOR, &info);
		res = cmpack_fset_next(fset);
	}

	/* Normal return */
	return 0;
}
