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

extern "C" {
#include "atm-message-c.h"
}
#include <vector>
#include <iostream>

using namespace std;

#include "atm2009/ATMSkyStatus.h"

using namespace atm;

#define atm_2009_atmosp_get   CFC_EXPORT_NAME(atm_2009_atmosp_get)
#define atm_2009_atmosp_set   CFC_EXPORT_NAME(atm_2009_atmosp_set)
#define atm_2009_atmosp_print CFC_EXPORT_NAME(atm_2009_atmosp_print)
#define atm_2009_atmosp       CFC_EXPORT_NAME(atm_2009_atmosp)
#define atm_2009_transm       CFC_EXPORT_NAME(atm_2009_transm)
#define atm_2009_path         CFC_EXPORT_NAME(atm_2009_path)

static AtmProfile* s_current_atm_profile = NULL;
static Atmospheretype s_atm_type = midlatSummer; // Atmospheric type (to reproduce behavior above the tropopause)
static float s_humidity = 1.0;                   // [%]    Ground Relative Humidity (indication)
static float s_wvsh = 2.0;                       // [km]   Water vapor scale height
static float s_tlr = -5.6;                       // [K/km] Tropospheric lapse rate
static float s_atm_top = 48.0;                   // [km]   Upper atm. boundary for calculations
static float s_p_step = 10.0;                    // [mb]   Primary pressure step
static float s_p_step_factor = 1.2;              // []     Pressure step ratio between two consecutive layers

extern "C" void atm_2009_atmosp_get( int *atm_type, float *humidity, float *wvsh, float *tlr, float *atm_top, float *p_step, float *p_step_factor)
{
  *atm_type = (int) s_atm_type;
  *humidity = s_humidity ;
  *wvsh = s_wvsh;
  *tlr = s_tlr;
  *atm_top = s_atm_top;
  *p_step = s_p_step;
  *p_step_factor = s_p_step_factor ;
}

extern "C" void atm_2009_atmosp_set( int *atm_type, float *humidity, float *wvsh, float *tlr, float *atm_top, float *p_step, float *p_step_factor)
{
  s_atm_type = (Atmospheretype)*atm_type;
  s_humidity = *humidity;
  s_wvsh = *wvsh;
  s_tlr = *tlr;
  s_atm_top = *atm_top;
  s_p_step = *p_step;
  s_p_step_factor = *p_step_factor;
}

extern "C" void atm_2009_atmosp_print( void)
{
  cout << " Atmosphere type           = " << AtmosphereType::name(s_atm_type) << endl;
  cout << " Humidity                  = " << s_humidity << "%" << endl;
  cout << " Water vapor scale height  = " << s_wvsh << "km" << endl;
  cout << " Tropospheric lapse rate   = " << s_tlr << "K/km" << endl;
  cout << " Upper atmosphere boundary = " << s_atm_top << "km" << endl;
  cout << " Primary pressure step     = " << s_p_step << "mb" << endl;
  cout << " Pressure step ratio       = " << s_p_step_factor << endl;
}

extern "C" void atm_2009_atmosp( float *tin, float *pin, float *hin)
{
  try {
    Temperature t( *tin,"K"); // Ground temperature
    Pressure p( *pin,"mb");    // Ground Pressure
    Length h( *hin,"km");      // Altitude of the site
    Atmospheretype atm_type = s_atm_type;
    Humidity humidity( s_humidity,"%");
    Length wvsh( s_wvsh,"km");
    double tlr( s_tlr);
    Length atm_top( s_atm_top,"km");
    Pressure p_step( s_p_step,"mb");
    double p_step_factor(s_p_step_factor);
    if (s_current_atm_profile != NULL)
      delete s_current_atm_profile;
    s_current_atm_profile = new AtmProfile(h,p,t,tlr,humidity,wvsh,p_step,p_step_factor,atm_top,atm_type);
  } catch (...) {
    atm_c_message(seve_e,"ATM_2009_ATMOSP","Error in ATM processing");
  }
}

extern "C" void atm_2009_transm( float *water, float *airmass, float *freq, float *temi, float *tatm, float *taud, float *tauw, float *taut, int *ier)
{
  try {
    Frequency  afreq(*freq,"GHz");
    Length awater( *water, "MM");
    RefractiveIndexProfile rip( afreq, *s_current_atm_profile);
    SkyStatus sky_status( rip, awater, *airmass);
    *taud = sky_status.getDryOpacity().get(); // interpret the old oxygen opacity as the dry opacity
    *tauw = sky_status.getWetOpacity().get(); // interpret the old water opacity as the wet opacity
    *taut = sky_status.getTotalOpacity().get();
    *temi = sky_status.getTebbSky().get();
    *tatm = *temi / (1.-exp( -(*taut) * *airmass));
    *ier = 0;
  } catch (...) {
    atm_c_message(seve_e,"ATM_2009_TRANSM","Error in ATM processing");
    *ier = 1;
  }
}

extern "C" void atm_2009_path( float *water, float *airmass, float *freq, float *path, int *ier)
{
  try {
    Frequency afreq( *freq, "GHz");
    Length awater( *water, "MM");
    RefractiveIndexProfile rip( afreq, *s_current_atm_profile);
    double water_ratio = awater.get() / rip.getGroundWH2O().get();
    double wet_path = rip.getDispersiveWetPathLength().get()
                    + rip.getNonDispersiveWetPathLength().get();
    double dry_path = rip.getNonDispersiveDryPathLength().get()
                    + rip.getO2LinesPathLength().get()
                    + rip.getO3LinesPathLength().get()
                    + rip.getCOLinesPathLength().get()
                    + rip.getN2OLinesPathLength().get();
    *path = (dry_path + water_ratio * wet_path) * (*airmass) * 100.;  /* [cm] */
    *ier = 0;
  } catch (...) {
    atm_c_message(seve_e,"ATM_2009_PATH","Error in ATM processing");
    *ier = 1;
  }
}

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