#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "../util/error.h"
#include "../util/units.h"
#include "../util/zulu.h"
#include "Geomagnetism.h"

// We use WGS84 altitude, no need for the geoid data:
//#   include "EGM9615.h"

#define wmm_IMPORT
#include "wmm.h"

/** If this module has been initialized. */
static int inited;

/** Current date to be used when client asks for year==0. */
static double date_current;

static MAGtype_Geoid Geoid;
static MAGtype_Ellipsoid Ellip;
static MAGtype_MagneticModel * MagneticModels[1], *TimedMagneticModel;

/* If the WMM.COF file becomes outdated, gives warning only once. */
static int warning_date_range_already_given;


void wmm_init(char * coefficients_file)
{
	if( inited )
		return;
	inited = 1;
	
	date_current = zulu_timestampToYear(time(NULL));
	
	int NumTerms, nMax = 0;
	int epochs = 1;
	if (!MAG_robustReadMagModels(coefficients_file, &MagneticModels, epochs))
		error_external("failed reading WMM coefficients file %s", coefficients_file);
	if (nMax < MagneticModels[0]->nMax) nMax = MagneticModels[0]->nMax;
	NumTerms = ((nMax + 1) * (nMax + 2) / 2);
	TimedMagneticModel = MAG_AllocateModelMemory(NumTerms); /* For storing the time modified WMM Model parameters */
	if (MagneticModels[0] == NULL || TimedMagneticModel == NULL) {
		MAG_Error(2);
	}
	MAG_SetDefaults(&Ellip, &Geoid); /* Set default values and constants */
	/* Check for Geographic Poles */

	/* Set EGM96 Geoid parameters */
	//Geoid.GeoidHeightBuffer = GeoidHeightBuffer;
	Geoid.Geoid_Initialized = 0;
}


void wmm_setCurrentTime(double date)
{
	date_current = date;
}


void wmm_getMagneticField(double date, double latitude, double longitude, double altitude, wmm_MagneticField *mf)
{
	if( ! inited )
		error_internal("wmm module not initialized", 0);
	
	if( date == 0 )
		date = date_current;
	
	if( ! warning_date_range_already_given ){
		double date_start = MagneticModels[0]->epoch;
		double date_end = MagneticModels[0]->CoefficientFileEndDate;
		if( !(date_start <= date && date <= date_end) ){
			warning_date_range_already_given = 1;
			fprintf(stderr, "Warning: requested date %.1f is beyond the intended range [%.1f-%.1f] supported by the current coefficients file WMM.COF. The World Magnetic Model Library cannot evaluate the components of the Earth magnetic field with the needed accuracy.\n",
				date, date_start, date_end);
		}
	}
	
	MAGtype_CoordGeodetic CoordGeodetic;
	MAGtype_Date UserDate;
	MAGtype_GeoMagneticElements GeoMagneticElements;
	MAGtype_CoordSpherical CoordSpherical;
	UserDate.DecimalYear = date;
	UserDate.Year = UserDate.Month = UserDate.Day = 0;
	CoordGeodetic.lambda = units_RADtoDEG(longitude);
	CoordGeodetic.phi = units_RADtoDEG(latitude);
	CoordGeodetic.UseGeoid = 0;
	CoordGeodetic.HeightAboveEllipsoid = 0.001 * altitude;
	Geoid.UseGeoid = 0;
	//MAG_ConvertGeoidToEllipsoidHeight(CoordGeodetic, Geoid);
	MAG_GeodeticToSpherical(Ellip, CoordGeodetic, &CoordSpherical);
	MAG_TimelyModifyMagneticModel(UserDate, MagneticModels[0], TimedMagneticModel);
	MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel, &GeoMagneticElements);
	mf->X = GeoMagneticElements.X;
	mf->Y = GeoMagneticElements.Y;
	mf->Z = GeoMagneticElements.Z;
	mf->Incl = units_DEGtoRAD(GeoMagneticElements.Incl);
	mf->Decl = units_DEGtoRAD(GeoMagneticElements.Decl);
}
