#ifndef MLFHEADER
#define MLFHEADER

#include "Header.hh"
#include "ElementContainerMatrix.hh"
#include "MlfPhysicalConstants.hh"
#include "DoubleBinArrange.hh"
#include "StringTools.hh"
#include "CppToPython.hh"

//#include <math.h>
#include <cfloat>
#ifdef MULTH
    #include <omp.h>
#endif
#define MLF_ENV_PROTONSERV_HOSTNAME "MLF_PROTONSERV_HOSTNAME"
#define MLF_ENV_LOG_QUIET "MLF_LOG_QUIET"
#define MLF_ENV_T0PIDCHECK_IGNORED "MLF_T0PIDCHECK_IGNORED"

//////////////////////////////////
// MlfHeader
/////////////////////////////////

//!  Header of MLF
/*!
 */

UInt4 MlfGetNumOfMulTh();

extern const Double MLF_NEUNET_CLOCK_MICROSEC;  // 1clock = 0.025 [microsec]
extern const Double MLF_NEUNET_CLOCK_SEC;       // 1clock = 2.5e-08 [sec]
extern const Double MLF_TARGET_FRAME_MICROSEC;  // 1frame = 40000.0 [microsec]
extern const Double MLF_TARGET_FRAME_MILLISEC;  // 1frame = 40.0 [millisec]

static const std::string MLF_KEY_HEAD_XAXIS = "Xaxis";   // X-axis on ElementContaienr's header
static const std::string MLF_KEY_HEAD_XUNIT = "Xunit";   // X-axis unit on ElementContaienr's header
static const std::string MLF_KEY_HEAD_XRANGE = "XRANGE"; // X-axis bins on ElementContaienr's header
static const std::string MLF_KEY_HEAD_ZAXIS = "Zaxis";   // Z-axis on ElementContaienrArray's header
static const std::string MLF_KEY_HEAD_ZUNIT = "Zunit";   // Z-axis unit on ElementContaienrArray's header
static const std::string MLF_KEY_HEAD_ZRANGE = "ZRANGE"; // Z-axis bins on ElementContaienrArray's header
static const std::string MLF_KEY_HEAD_UNIT_PRE = "_UNIT_"; // Prefix of unit on ElementContaienrArray's header

std::vector<UInt4> DivMultiContUInt4( std::string conts );
        //!< Divides std::string into list of Uint4
        /*   This analyzes std::string format to make UInt4 std::vector.
         *   Format : "x-y" or "x:y" -> x, x+1, x+2, ... ,y-1, y
         *   Format : "x-y,z:w" -> x, x+1, ..., y-1, y, z, z+1, ..., w-1, w
         *
         *   @param conts (std::string)
         *   @return std::vector<UInt4>
         */
std::vector<Double> DivMultiContDouble( std::string conts );
        //!< make range from given std::string
        /*   This analyzes std::string format to make Double std::vector.
         *   Format : "x:y, z:w" -> [x,y,z,w]
         *
         *   @param conts  (std::string)
         *   @return std::vector<Double>
         */
std::vector<Double> CalcRangeAsBinCenterZero( Double v_min, Double v_max, Double v_step, bool isZeroCenter=true );
        //!< Calculates range as 0 is bin center
        /*!< The origin of axis becomes the center position of binning width on its axis.
         *   @param v_min (Double) minimum value of given range
         *   @param v_max (Double) maximum value of given range
         *   @param v_step (Double) step value of given range
         *   @param isZeroCenter (bool) When v_min> 0, true: zero point is center of bin, false: v_min is center of bin
         *   @return returned std::vector has three value:[0]=new minimum value, [1]=new maximum value, [2]=the number of steps
         */
std::vector<Double> PutVectorAsBinCenterZero( Double v_min, Double v_max, Double v_step );
        //!< Calculates std::vector as 0 is bin center
        /*!< The origin of axis becomes the center position of binning width on its axis.
         *   @param v_min (Double) minimum value of given range
         *   @param v_max (Double) maximum value of given range
         *   @param v_step (Double) step value of given range
         *   @return returned std::vector between v_min to v_max with the step of v_step
         */
std::string MlfEnvGetProtonServerHostName();
bool MlfEnvGetIsQuiet();
bool MlfEnvGetT0PidCheckIgnored();

#endif
