/*******************************************************************************
 * This file is part of SWIFT.
 * Copyright (c) 2012 Matthieu Schaller (matthieu.schaller@durham.ac.uk).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 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 Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/
#ifndef SWIFT_UNITS_H
#define SWIFT_UNITS_H

/* Config parameters. */
#include "../config.h"

/* Local includes. */
#include "parser.h"

/**
 * @brief The unit system used internally.
 *
 * This structure contains the conversion factors to the 7 cgs base units to the
 *internal units.
 * It is used everytime a conversion is performed or an i/o function is called.
 *
 **/
struct UnitSystem {
  double UnitMass_in_cgs; /*< Conversion factor from grams to internal mass
                             units */

  double UnitLength_in_cgs; /*< Conversion factor from centimeters to internal
                               length units. */

  double UnitTime_in_cgs; /*< Conversion factor from seconds to internal time
                             units. */

  double UnitCurrent_in_cgs; /*< Conversion factor from Ampere to internal
                                current units. */

  double UnitTemperature_in_cgs; /*< Conversion factor from Kelvins to internal
                                    temperature units. */
};

/**
 * @brief The base units used in the cgs (and internal) system. All units are
 * derived from those.
 */
enum BaseUnits {
  UNIT_MASS = 0,
  UNIT_LENGTH = 1,
  UNIT_TIME = 2,
  UNIT_CURRENT = 3,
  UNIT_TEMPERATURE = 4
};

/**
 * @brief  The different conversion factors supported by default
 */
enum UnitConversionFactor {
  UNIT_CONV_NO_UNITS,
  UNIT_CONV_MASS,
  UNIT_CONV_LENGTH,
  UNIT_CONV_TIME,
  UNIT_CONV_DENSITY,
  UNIT_CONV_SPEED,
  UNIT_CONV_ACCELERATION,
  UNIT_CONV_FORCE,
  UNIT_CONV_ENERGY,
  UNIT_CONV_ENERGY_PER_UNIT_MASS,
  UNIT_CONV_ENTROPY,
  UNIT_CONV_ENTROPY_PER_UNIT_MASS,
  UNIT_CONV_POWER,
  UNIT_CONV_PRESSURE,
  UNIT_CONV_FREQUENCY,
  UNIT_CONV_ELECTRIC_CHARGE,
  UNIT_CONV_ELECTRIC_VOLTAGE,
  UNIT_CONV_ELECTRIC_CAPACITANCE,
  UNIT_CONV_ELECTRIC_RESISTANCE,
  UNIT_CONV_ELECTRIC_CONDUCTANCE,
  UNIT_CONV_MAGNETIC_FLUX,
  UNIT_CONV_MAGNETIC_FIELD,
  UNIT_CONV_MAGNETIC_INDUCTANCE,
  UNIT_CONV_TEMPERATURE
};

void units_init(struct UnitSystem*, const struct swift_params*);
double units_get_base_unit(const struct UnitSystem*, enum BaseUnits);
const char* units_get_base_unit_symbol(enum BaseUnits);
const char* units_get_base_unit_CGS_symbol(enum BaseUnits);
double units_general_conversion_factor(const struct UnitSystem* us,
                                       const float baseUnitsExponants[5]);
double units_conversion_factor(const struct UnitSystem* us,
                               enum UnitConversionFactor unit);
float units_general_h_factor(const struct UnitSystem* us,
                             const float baseUnitsExponants[5]);
float units_h_factor(const struct UnitSystem* us,
                     enum UnitConversionFactor unit);
float units_general_a_factor(const struct UnitSystem* us,
                             const float baseUnitsExponants[5]);
float units_a_factor(const struct UnitSystem* us,
                     enum UnitConversionFactor unit);
void units_general_conversion_string(char* buffer, const struct UnitSystem* us,
                                     const float baseUnitsExponants[5]);
void units_conversion_string(char* buffer, const struct UnitSystem* us,
                             enum UnitConversionFactor unit);

#endif /* SWIFT_UNITS_H */
