#ifndef _CLUSTER_HS2_CAL_HH
# define _CLUSTER_HS2_CAL_HH

# include "HydroscatIF.h"

/** @brief A functor class that compute calibrated values from HS2 raw data 
 */
class HS2Cal {
public:
  /** @brief Constructor
   *
   * Create a new instance and load the $AUV_CONFIG_DIR/hs2Calibration.dat to extratc
   * the calibration partameters.
   *
   * @sa void HS2Cal::loadCfg(char const *filename);
   */
  HS2Cal();
  /** @brief Destructor
   */
  ~HS2Cal() {}

  /** @brief output type.
   *
   * The data structure used to store the calibrated values.
   *
   * Right now it is just providing bb470, bb676, and chlorophyll fluorescence.
   * May be worthwhile to add the temperature and depth if needed.
   */
  struct Output {
    bool ready;
    double bb470;
    double bb676;
    double fl676_uncorr;
  }; // HS2Cal::Output

  /** @brief Compute calibarted data
   *
   * @param data A raw data structure taken from HS2
   * @return the claibrated data computed from data
   */
  Output calibrate(HydroscatIF::Data &data) const;

  /** @brief Function call operator.
   *
   * This operator overload allows to use this class like
   * it was a pointer to a function (or functor). It calls
   * calibrate method
   *
   */
  Output operator()(HydroscatIF::Data &data) const {
    return calibrate(data);
  }

private:
  /** @brief a bug patch on raw data in Hydroscat
   *
   * @param value The value to patch.
   *
   * It appears that the snormx values provided by Hydroscat are buggy.
   * This function allow to have their correct value.
   */
  static void patchShort(short &value);

  /** @brief typ_absorption computation
   *
   * A copy/past from matlab scripts... I don't really know what it is computing but
   * it is needed. I suspect that it could be computed a priori (ie during constructor)
   * avoiding to recompute them at each call. Indeed we need to compute it only for 470 and 676 and
   * it just interpolate a value based on a_star table and the freq value (which is 470 or 676). 
   */
  static double typ_absorption(double freq);

  /** @brief Load hs2Calibration.dat
   *
   * This method make a very dirty parsing of hs2Calibration.dat to extract information.
   * @todo right now the parsing is very badly done and rely on the fact that
   * parameters are always at the same line it can be improved by a lex/yacc parsing
   */
  static void loadCfg(char const *filename);

  /** @brief Compute uncorrelated calibrated data.
   * used by calc_uncorr and calibrate
   */
  static double calc_uncorr(short channel, short snorm, short gainStatus, double temp);
  /** @brief Compute correlated calibrated data.
   * used by calibrate 
   */
  static double calc_bb(short channel, short snorm, short gainStatus, double temp, short freq);

  /* 
   * Following is large bunch of constants needed to compute calibrated values
   */ 
  static double const C;
  static double const gamma_y;
  static double const a_d_400;
  static double const gamma_d;
  static double const a_star[];

  static double const beta_w_ref;
  static double const b_bw_ref;
  static double const lambda_ref;
  static double const gamma;

  static double const b_b_tilde;
  static double const k_1;
  
  /*
   * Data extracted from hs2Calibration.dat
   */
  static double s_calTemp;
  
  static double s_gain[];
  static double s_mu[];
  static double s_tempCoeff[];
  static double s_Rnominal[];
  static double s_beta2bb[];
  static double s_sigmaExp[];

}; // HS2Cal 

#endif // _CLUSTER_HS2_CAL_HH
