#ifndef DETECTORINFOEDITORBASE
#define DETECTORINFOEDITORBASE

#include "UtsusemiHeader.hh"
#include "BoostXmlParser.hh"
#include "StringTools.hh"
#include "UtsusemiHeader.hh"
#include <time.h>

class DetectorInfoTagDefineBase
{
public:
    DetectorInfoTagDefineBase();
        //!< Constructor
        /*!<
         */
    ~DetectorInfoTagDefineBase();
        //!< Destructor
        /*!<
         */
    static const std::string DINFO;
    static const std::string DINFO_AT_INST;
    static const std::string DINFO_AT_VER;
    static const std::string DINFO_AT_DATE;

    static const std::string DINFO_INSTRINFO;
    static const std::string DINFO_INSTRINFO_L1;
    static const std::string DINFO_INSTRINFO_SAMPLEPOSI;
    static const std::string DINFO_INSTRINFO_TYPICALL2;
    static const std::string DINFO_INSTRINFO_TYPICALDS;

    static const std::string DINFO_TFP;
    static const std::string DINFO_TFP_PARAM;
    static const std::string DINFO_TFP_PARAM_AT_PIXID;

    static const std::string DINFO_TFPCALCPARAMS;
    static const std::string DINFO_TFPCALCPARAMS_PSD;
    static const std::string DINFO_TFPCALCPARAMS_PSD_REF;
    static const std::string DINFO_TFPCALCPARAMS_PSD_REF_L2;
    static const std::string DINFO_TFPCALCPARAMS_PSD_REF_THETA;

    static const std::string DINFO_POSIINFO;
    static const std::string DINFO_POSIINFO_POSI;
    static const std::string DINFO_POSIINFO_POSI_AT_DETID;
    static const std::string DINFO_POSIINFO_POSI_AT_NUMAXIS;

    static const std::string DINFO_BANKINFO;
    static const std::string DINFO_BANKINFO_BANK;
    static const std::string DINFO_BANKINFO_BANK_AT_ID;
    static const std::string DINFO_BANKINFO_BANK_AT_NAME;

};

class UtsusemiDetectorInfoInstInfo
{
public:
    UtsusemiDetectorInfoInstInfo();
        //!< Constructor
        /*!<
         */
    UtsusemiDetectorInfoInstInfo( const UtsusemiDetectorInfoInstInfo& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiDetectorInfoInstInfo();
        //!< Destructor
        /*!<
         */
    Double L1;                        // [mm]
    std::vector<Double> SamplePosition;    // [mm]
    Double TypicalL2;                 // [mm]
    Double TypicalDS;                 // [mm^2]
};

class UtsusemiDetectorInfoTfp
{
public:
    UtsusemiDetectorInfoTfp();
        //!< Constructor
        /*!<
         */
    UtsusemiDetectorInfoTfp( const UtsusemiDetectorInfoTfp& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiDetectorInfoTfp();
        //!< Destructor
        /*!<
         */
    void ClearList();
    std::vector< std::pair<Double,Double> > TfpList;  /**< List of Detectors */
    void AddTfp( UInt4 pixelId, Double A, Double B );
};

class UtsusemiDetectorInfoTfpCalcParams
{
public:
    UtsusemiDetectorInfoTfpCalcParams();
        //!< Constructor
        /*!<
         */
    UtsusemiDetectorInfoTfpCalcParams( const UtsusemiDetectorInfoTfpCalcParams& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiDetectorInfoTfpCalcParams();
        //!< Destructor
        /*!<
         */

    Double Psd_ref_L2;
    Double Psd_ref_Theta;

};

class UtsusemiDetectorInfoPosiInfo
{
public:
    UtsusemiDetectorInfoPosiInfo();
        //!< Constructor
        /*!<
         */
    UtsusemiDetectorInfoPosiInfo( const UtsusemiDetectorInfoPosiInfo& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiDetectorInfoPosiInfo();
        //!< Destructor
        /*!<
         */
    std::vector< UInt4 > numAxis_list;
    std::vector< std::vector<Double> > position_list;
    void Clear();
    void AddPosi( UInt4 detId, UInt4 numAxis, std::vector<Double> posi );
    bool DelPosi( UInt4 detId, bool isForced );
    UInt4 PutPosiNumAxis( UInt4 detId );
    std::vector<Double> PutPosi( UInt4 detId );
    std::vector<UInt4> PutDetIdList();
};

class UtsusemiDetectorInfoBankInfo
{
public:
    UtsusemiDetectorInfoBankInfo();
        //!< Constructor
        /*!<
         */
    UtsusemiDetectorInfoBankInfo( const UtsusemiDetectorInfoBankInfo& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiDetectorInfoBankInfo();
        //!< Destructor
        /*!<
         */
    std::vector<std::string> bankNameList;
    std::vector<std::string> bankConts;
    void AddBank( UInt4 bankId, std::string name, std::string conts );
    bool DelBank( UInt4 bankId );
    std::vector<std::string> PutBank( UInt4 bankId );
};

//////////////////////////////////
// DetectorInfoEditorBase
/////////////////////////////////

//!
/*!
 *
 */
class DetectorInfoEditorBase
{
private:

    std::string _MessageTag;

protected:
    void Initialize();
    UInt4 CheckMultiContInfo( std::string strAttr );
    bool _isReadXml;

public:
    DetectorInfoTagDefineBase TAG;
    UtsusemiDetectorInfoInstInfo* InstInfo;
    UtsusemiDetectorInfoTfp* TfpInfo;
    UtsusemiDetectorInfoTfpCalcParams* TfpCalcParams;
    UtsusemiDetectorInfoPosiInfo* PosiInfo;
    UtsusemiDetectorInfoBankInfo* BankInfo;

    std::string InstCode;                          /**< Instrument Code described  */
    std::string Version;                           /**< version for wiringInfo described  */
    std::string Update;                            /**< update date for wiringInfo described  */

    BoostXmlParser *_parser;                  /**< XML parser  */
    static const std::string KEY_READ_XML;         /**< Key of XML parser to be read from XML file */
    static const std::string KEY_WRITE_XML;        /**< Key of XML parser to be written to XML file */

    static const Int4 DUMP_ALL;
    static const Int4 DUMP_INSTINFO;
    static const Int4 DUMP_TFPINFO;
    static const Int4 DUMP_TFPCALCPARAMS;
    static const Int4 DUMP_POSIINFO;
    static const Int4 DUMP_BANKINFO;

    StringTools* _st;
    bool _Status;
    std::string _detectorFilePath;

    // Required as Reader
    std::vector< std::vector<Double> >* _TimeFocParam;
    std::vector< std::vector<Int4> > _DetIdInBank;
    std::vector<std::string> _BankName;

    DetectorInfoEditorBase();
        //!< Constructor
        /*!<
         */
    DetectorInfoEditorBase( std::string dfile, bool workAsReader=true );
        //!< Constructor
        /*!<
         *   @param dfile (std::string) DetectorInfo file path to be read
         *   @param workAsReader (bool)
         */
    ~DetectorInfoEditorBase();
        //!< Destructor
        /*!<
         */
    void Clear( UInt4 index=0 );
        //!< Clears stored parameters
        /*!<
         *   This deletes information by given index.
         *    index = 0 : all (default)
         *    index = 1 : InstrumentInfo
         *    index = 2 : TfpInfo
         *    index = 3 : TfpCalcParams
         *    index = 4 : PositionInfo
         *    index = 5 : BankInfo
         *
         *   @param index (UInt4)
         *   @return None
         */
    bool Read( std::string arg );
        //!< Reads DetectorInfo.xml and import information
        /*!<
         *   @param arg (std::string) path/to/DetectorInfo.xml or DetectorInfo std::string
         *   @retval true : succeeded
         *   @retval false: failed
         */
    bool Write( std::string filepath );
        //!< Writes DetectorInfo.xml
        /*!<
         *   @param filepath (std::string)
         *   @retval true : succeeded
         *   @retval false: failed
         */
    std::string OutXml( bool withIndent=false );
        //!< Returns DetectorInfo as std::string
        /*!<
         *   @param withIndent(bool) false : output text without an indent format
         *   @return std::string
         */
    void ImportInstInfo();
        //!< Import "instrumentInfo" from DetectorInfo.xml
        /*!<
         *   @param None
         *   @retval None
         */
    void _makeInstInfoXml();
        //!< make "instrumentInfo" xml element
        /*!<
         *   @param None
         *   @retval None
         */
    void ImportTfpInfo();
        //!< Import "tfp" info from DetectorInfo.xml
        /*!<
         *   @param None
         *   @retval None
         */
    void _makeTfpInfoXml();
        //!< make "tfp" xml element
        /*!<
         *   @param None
         *   @retval None
         */
    void ImportTfpCalcParams();
        //!< Import "tfpCalcParams" from DetectorInfo.xml
        /*!<
         *   @param None
         *   @retval None
         */
    void _makeTfpCalcParamsXml();
        //!< make "tfpCalcParams" xml element
        /*!<
         *   @param None
         *   @retval None
         */
    void ImportPosiInfo();
        //!< Import "positionInfo" from DetectorInfo.xml
        /*!<
         *   @param None
         *   @retval None
         */
    void _makePosiInfoXml();
        //!< make "positionInfo" xml element
        /*!<
         *   @param None
         *   @retval None
         */
    void ImportBankInfo();
        //!< Import "bankInfo" from DetectorInfo.xml
        /*!<
         *   @param None
         *   @retval None
         */
    void _makeBankInfoXml();
        //!< make "bankInfo" xml element
        /*!<
         *   @param None
         *   @retval None
         */
    void Dump( Int4 index=DUMP_ALL );
        //!< Shows imported information
        /*!<
         *   @param  index (Int4)
         *   @return None
         */
    bool _makeOutputXml();
        //!< Makes XML format from stored information
        /*!<
         *   @param  None
         *   @retval true    succeded
         *   @retval false   failed
         */

    bool SetInstInfoL1( Double _L1 );
        //!< Set L1 in InstrumentInfo
        /*!<
         *   @param  L1 (Double) [mm]
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetInstInfoSamplePosition( Double _px, Double _py, Double _pz );
        //!< Set SamplePosition in InstrumentInfo
        /*!<
         *   @param  _px (Double) [mm]
         *   @param  _py (Double) [mm]
         *   @param  _pz (Double) [mm]
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetInstInfoTypicalL2( Double _L2 );
        //!< Set the typical L2 in InstrumentInfo
        /*!< which is used for the solid-angle correction
         *
         *   @param  _L2 (Double) [mm]
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetInstInfoTypicalDS( Double _dS );
        //!< Set the typical dS (the area of one pixel) in InstrumentInfo
        /*!< which is used for the solid-angle correction
         *
         *   @param  _dS (Double) [mm]
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetTfpInfo( UInt4 pixId, Double A, Double B );
        //!< Set Time-focusing parameters (for ENG )
        /*!<
         *   @param  pixId (UInt4) pixel-Id
         *   @param  A (Double) param A
         *   @param  B (Double) param B
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetTfpInfo( std::vector<UInt4> pixIdList, std::vector<Double> AList, std::vector<Double> BList );
        //!< Set Time-focusing parameters (for ENG )
        /*!<
         *   @param  pixIdList (std::vector<UInt4>)  list of pixId
         *   @param  AList (std::vector<Double>)     list of A
         *   @param  BList (std::vector<Double>)     list of B
         *   @retval true    succeded
         *   @retval false   failed
         */
    std::vector<Double> PutTfpInfo( UInt4 pixId );
        //!< Put Tfp parameters of given pixId
        /*!<
         *   @param  pixId (UInt4) pixel-Id
         *   @return std::vector<Double> returned A and B
         */
    bool DeleteTfpInfo( UInt4 pixId, bool isForced=false );
        //!< Delete Tfp parameters of given pixId
        /*!<
         *   @param  pixId (UInt4) pixel-Id
         *   @param isForced (bool) execute without warning message
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeleteTfpInfo( std::vector<UInt4> pixIdList, bool isForced=false );
        //!< Delete Tfp parameters of given pixId
        /*!<
         *   @param  pixIdList (std::vector<UInt4>) list of pixel-Id
         *   @param isForced (bool) execute without warning message
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetTfpCalcParamsPsdRef( Double psd_ref_l2, Double psd_ref_theta );
        //!< Set Time-focusing Calculation Parameters
        /*!<
         *   @param  psd_ref_l2 (Double) Reference L2
         *   @param  psd_ref_theta (Double) Reference Theta
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetPositionInfo( UInt4 detId, UInt4 numAxis, std::vector<Double> params );
        //!< Set Position info parameters
        /*!<
         *   @param  detId (UInt4) detector ID
         *   @param  numAxis (UInt4)  the number of axes
         *   @param  params (std::vector<Double>)
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeletePositionInfo( UInt4 detId, bool isForced=false );
        //!< Delete Position info parameters of given detectorId
        /*!<
         *   @param  detId (UInt4) detector ID
         *   @param  isForced (bool) execute without warning message
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeletePositionInfo( std::vector<UInt4> detIdList, bool isForced=false );
        //!< Delete Position info parameters of given detectorId
        /*!<
         *   @param  detIdList (std::vector<UInt4>) list of detId
         *   @param  isForced (bool) execute without warning message
         *   @retval true    succeded
         *   @retval false   failed
         */
    UInt4 PutPositionInfoNumAxis( UInt4 detId );
        //!< Put NumAxis in Position info parameters of given detectorId
        /*!<
         *   @param  detId (UInt4) detector ID
         *   @return UInt4 NumAxis
         */
    std::vector<Double> PutPositionInfoParams( UInt4 detId );
        //!< Put parameters in Position info of given detectorId
        /*!<
         *   @param  detId (UInt4) detector ID
         *   @return std::vector<Double> parameters
         */
    std::vector<UInt4> PutPositionInfoDetIdList();
        //!< Put list of detId stored as Position Inof
        /*!<
         *   @param  None
         *   @return std::vector<UInt4> list of detId
         */
    bool SetBankInfo( UInt4 bankId, std::string bankName, std::string conts );
        //!< Set BankInfo
        /*!<
         *   @param  bankId (UInt4) Bank ID
         *   @param  bankName (std::string) Bank Name
         *   @param  conts (std::string)
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeleteBankInfo( UInt4 bankId );
        //!< Delete BankInfo of given bankId
        /*!<
         *   @param  bankId (UInt4) Bank ID
         *   @retval true    succeded
         *   @retval false   failed
         */
    std::vector<std::string> PutBankInfo( UInt4 bankId );
        //!< Put BankInfo of given bankId
        /*!<
         *   @param  bankId (UInt4) Bank ID
         *   @return std::vector<std::string>  <BankName>,<Conts1,Conts2,...>
         */

    bool SetInfoAsReader();
        //!< Converts WiringInfo into the format to be read from histogram creation methods
        /*!<
         *   @param  None
         *   @retval true    succeded
         *   @retval false   failed
         */
    void ClearReader( UInt4 index=0 );
        //!< Clears the WiringInfo data to be read from histogram creation methods
        /*!<
         *   @param  index (UInt4)   index of variables to be cleared.
         *   @retval None
         */
    Double PutInstL1();
        //!< Put L1
        /*!<
         *   @param  None
         *   @return Double L1[mm]
         */
    std::vector<Double> PutInstSamplePosition();
        //!< Put Sample Position
        /*!<
         *   @param  None
         *   @return std::vector<Double> [px,py,pz] [mm]
         */
    Double PutInstTypicalL2();
        //!< Put the typical L2 stored.
        /*!<
         *   @param  None
         *   @return Double L2 [mm]
         */
    Double PutInstTypicalDS();
        //!< Put the typical dS (the area of one pixel) stored.
        /*!<
         *   @param  None
         *   @return Double dS [mm*mm]
         */
    std::vector<Int4> PutBankIdList();
        //!< Puts List of Bank ID
        /*!<
         *
         *   @param None
         *   @return  List of BankId (std::vector<Int4>).
         */
    std::vector<Int4> PutDetIdInBank( UInt4 bankId );
        //!< Puts range of DetId in Bank ID given by an argument.
        /*!<
         *
         *   @param bankId(UInt4)  bank ID
p         *   @return  range of detId (std::vector<Int4>).
         */
    std::vector<Int4> PutDetIdInBank( std::string bankName );
        //!< Puts range of DetId in Bank ID given by an argument.
        /*!<
         *
         *   @param bankName (String) bank Name
         *   @return  range of detId (std::vector<Int4>).
         */
    std::vector<std::string> PutBankName();
        //!< Puts List of Banks name
        /*!<  attribute "name" in bank tag
         *
         *   @param None
         *   @return  list of banks name (std::vector<std::string>).
         */
    std::vector< std::vector<Double> >* PutTfp();
        //!< Put Time focusing parameters loaded from DetectorInfo file
        /*!<
         *   @param None
         *   @return timeFocParam
         */
};
#endif
