#ifndef WIRINGINFOEDITORBASE
#define WIRINGINFOEDITORBASE

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

//////////////////////////////////
// WiringInfoEditorBase
/////////////////////////////////

//! Codes to treat WiringInfo
/*!
 *  - Reads WiringInfo to be read from histogram creation methods
 *  - Reads WiringInfo to change its contents
 *  - Saves changed WiringInfo
 *
 *
 */
class WiringInfoEditorBase
{
private:


    WiringInfoConversionDictionary* _WCD;
    std::string _MessageTag;
    void Initialize();

protected:
    UInt4 CheckMultiContInfo( std::string strAttr );
    bool _isReadXml;
    void _AllocatePixelInfo( UInt4 daqid, UInt4 modno );
    void _MakePixelInfoStore();
    bool _CheckAlivePixelInfo();
    bool _makeOutputXml();
        //!< Makes XML format from stored information
        /*!<
         *   @param  None
         *   @retval true    succeded
         *   @retval false   failed
         */
    WiringInfoTagDefineBase TAG;

public:

    std::vector< UtsusemiDaqInfo* >* PixelInfo;    /**< PixelInfo->at(daqId)->ModList[modNo]->DetList[detNo]  */
    std::vector< std::vector<UInt4>* > DetInfoList;     /**< [detId]( std::vector of <daqId, modNo, detNo> )   */

    std::vector< UtsusemiTofBinPattern* > TofBinPtnInfo; /**< TOF bin std::vector [paternId]( params )*/
    std::vector< UtsusemiTofMaskPattern* > TofMaskPtnInfo; /**< TOF mask std::vector [paternId]( params )*/
    std::vector< UtsusemiTofBinInfo* > TofBinInfo; /**< TOF bin info [patern_id] or NULL */

    //std::pair<UInt4,Double> FrameBoundaryInfo;     /** first=frameNo, second=Boundary */
    UtsusemiFrameBoundaryInfo FrameBoundaryInfo;     /** obj.frameNo, obj.boundaryValue, obj.boundaryType */
    UtsusemiTimeDependBackGround TimeDependBackGroundRegion; /** UtsusemiTimeDependBackGround **/ //[inamura 160809]

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

    // Required as Reader
    UInt4 MaxPixelId;                         /**< max of pixel id (required WiringInforeader) */
    UInt4 MaxDetId;                           /**< max of detector id (required WiringInforeader) */
    UInt4 NumOfInnerDet;                      /**< the number of inner detId */
    UInt4 NumOfInnerPixel;                    /**< the number of inner pixel No */
    std::vector< std::vector< std::vector< std::vector<Int4>* >* >* >* PixelInfoStore; /**< Pixel info of WiringInfo  */
    std::vector< std::vector<Int4>* >* DetIdConvTable;  /**< conversion table between inner detector No and outer detId */
    std::vector< std::vector<Int4>* >* PixelConvTable;  /**< conversion table between inner pixel No and outer pixelId */
    std::vector<Int4> PixelIdToInnerId;            /**< conversion table from PixelId to inner pixel No */

    std::vector< std::vector<Int4>* >* TrigInfoStore;  /**<  TrigNET info [index][type,daqId,moduleNo] */
    std::vector< std::vector<Double>* > TofBinInfoList;   /**< Replace original TofBinInfo  */
    //std::vector< std::vector<Double>* > TofBinPtnVec;   /**< Replace by TofBinPtnInfo */
    //std::vector< Int4 > TofBinPtnTypeVec;          /**< Replace by TofBinPtnInfo */

    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 std::string KEY_USE_DEF_MASK;

    static const Int4 DUMP_ALL;
    static const Int4 DUMP_PIXELINFO;
    static const Int4 DUMP_TOFBINPAT;
    static const Int4 DUMP_TOFBININFO;
    static const Int4 DUMP_FRAMEINFO;

    StringTools* _st;
    bool _Status;
    std::string _wiringFilePath;
    std::string _maskXmlFilePath;
    std::string _detType;
    std::vector<std::string> _ignoreModuleType; //[inamura 170117]
    bool _isFixedHeadPixelId; //[inamura 191216]

    WiringInfoEditorBase();
        //!< Constructor
        /*!<
         */
    WiringInfoEditorBase(std::string _wFile, bool workAsReader=true);
        //!< Constructor
        /*!<
         *   @param _wFile (std::string)
         *   @param workAsReader (bool)
         */
    ~WiringInfoEditorBase();
        //!< Destructor
        /*!<
         */
    void Clear( UInt4 index=0 );
        //!< Clears stored parameters
        /*!<
         *   This deletes information by given index.
         *    index = 0 : all (default)
         *    index = 1 : PixelInfo ( and DetInfoList )
         *    index = 2 : TofBinPtnInfo
         *    index = 3 : TofBinInfo
         *    index = 4 : FrameBoundaryInfo
         *
         *   @param index (UInt4)
         *   @return None
         */
    bool Read( std::string arg );
        //!< Reads WiringInfo.xml and import information
        /*!<
         *   @param arg (std::string) path/to/DetectorInfo.xml or DetectorInfo as std::string
         *   @retval true : succeeded
         *   @retval false: failed
         */
    bool Write( std::string filepath );
        //!< Writes WiringInfo.xml
        /*!<
         *   @param filepath (std::string)
         *   @retval true : succeeded
         *   @retval false: failed
         */
    std::string OutXml( bool withIndent=false );
        //!< Returns WiringInfo as std::string
        /*!<
         *   @param withIndent(bool) false : output xml without an indent format
         *   @return std::string
         */
    void ImportPixelInfo();
        //!< Analyzes xml descriptions for PixelInfo
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void ImportTofBinPattern();
        //!< Analyzes xml descriptions for TOF bin patterns
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void ImportTofMaskPattern();
        //!< Analyzes xml descriptions for TOF mask pattern
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void ImportTofBinInfo();
        //!< Analyzes xml descriptions for TOF bin info
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void ImportFrameInfo();
        //!< Analyzes xml descriptions for frame info
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void Dump( Int4 index=DUMP_ALL );
        //!< Shows imported information
        /*!<
         *   @param  index (Int4)
         *   @return None
         */
    void ResetHeadPixelId(Int4 first_detId=0, Int4 last_detId=-1, Int4 headPixelId=0 );
        //!< Re-calculates each headPixelId by numPixel
        /*!<
         *   ResetHeadPixelId(Int4 first_detId=0, Int4 last_detId=-1, Int4 headPixelId=0 )
         *   @param first_detId   range of detId to apply
         *   @param last_detId    range of detId to apply
         *   @param headPixelId   if set, headPixelId starts from this value
         *   @return None
         */
    bool SetInstInfo( std::string instCode="", std::string update="", std::string ver="" );
        //!< Set InstCode and other information
        /*!<
         *   SetInstInfo( std::string instCode, std::string ver="1.5", std::string update="" );
         *   @param instCode   instrument code
         *   @param update     date format "YYYYMMDDhhmmss"
         *   @param ver        version
         *   @retval true  : success
         *   @retval false : false
         */
    bool SetPixelInfo( UInt4 daqId, UInt4 modNo, UInt4 detId, Int4 headPixelId, UInt4 numPixel, std::string type, UInt4 numAxis=1 );
    bool SetPixelInfo( UInt4 daqId, UInt4 modNo );
    bool SetPixelInfo( UInt4 daqId);
        //!< Sets Pixel info
        /*!< This changes or makes pixel information by given parameters
         *
         *   SetPixelInfo( UInt4 daqId, UInt4 modNo, UInt4 detId, UInt4 headPixelId, UInt4 numPixel, std::string type, UInt4 axis=0 )
         *   SetPixelInfo( UInt4 daqId, UInt4 modNo )
         *   SetPixelInfo( UInt4 daqId )
         *   @param daqId
         *   @param modNo
         *   @param detId
         *   @param headPixelid
         *   @param numPixel
         *   @param type
         *   @param numAxis
         *
         *   @retval true  : success
         *   @retval false : false
         */
    bool SetAllPixelInfo( UInt4 numPixel, std::string type=UTSUSEMI_KEY_HEAD_DETTYPE_PSD, UInt4 numAxis=1, Int4 daqId=-1, Int4 modNo=-1);
        //!< Sets Pixel info for all or given range
        /*!< This changes or makes pixel information by given parameters
         *   After changed parameter all, this executes ReSetHeadPixelId
         *
         *   SetAllPixelInfo( UInt4 numPixel, std::string type="PSD", UInt4 axis=0, Int4 daqId=-1, Int4 modNo=-1);
         *
         *   @param numPixel
         *   @param type
         *   @param numAxis
         *   @param daqId
         *   @param modNo
         *
         *   @retval true  : success
         *   @retval false : false
         */

    bool DeleteDetector( UInt4 detId );
        //!< Deletes detector element in Pixel info
        /*!< This delete detector information
         *
         *   RemoveDetector( UInt4 detId )
         *   @param daqId
         *
         *   @retval true  : success
         *   @retval false : false
         */
    bool DeleteModule( UInt4 daqId, UInt4 modNo );
        //!< Deletes module element in Pixel info
        /*!< This delete module element ( also deletes included detectors )
         *
         *   DeleteModule( UInt4 daqId, UInt4 modNo )
         *   @param daqId
         *   @param modNo
         *
         *   @retval true  : success
         *   @retval false : false
         */
    bool DeleteDaq( UInt4 daqId );
        //!< Deletes daq elements in Pixel info
        /*!< This deletes daq element ( also deletes included modules and detectors )
         *
         *   DeleteDaq( UInt4 daqId )
         *   @param daqId
         *
         *   @retval true  : success
         *   @retval false : false
         */
    void SetDaqAlive( bool isAlive, UInt4 first_daqId, UInt4 last_daqId=999999999 );
        //!< Sets DAQ components status use or not
        /*!< isAlive info is used when output to xml.
         *
         *   SetDaqAlive( bool isAlive, UInt4 first_daqId, UInt4 last_daqId=999999999 );
         *   @param  isAlive (bool) true: use, false: not use
         *   @param  first_daqId (UInt4) first daqId to be set
         *   @param  last_daqId  (UInt4) last daqId to be set, if not set, only first_daqId is set.
         *   @return None
         */
    void SetModAlive( bool isAlive, UInt4 daqId, UInt4 first_modNo, UInt4 last_modNo=999999999 );
        //!< Sets Module components status use or not
        /*!< isAlive info is used when output to xml.
         *
         *   SetModAlive( bool isAlive, UInt4 daqId, UInt4 first_modNo, UInt4 last_modNo=999999999 )
         *   @param  isAlive (bool) true: use, false: not use
         *   @param  daqId (UInt4) DAQ ID including target modules
         *   @param  first_modNo (UInt4) first module No to be set
         *   @param  last_modNo  (UInt4) last module No to be set, if not set, only first_modNo is set.
         *   @return None
         */
    void SetDetAlive( bool isAlive, UInt4 first_detId, UInt4 last_detId=999999999 );
        //!< Sets detector components status use or not
        /*!< isAlive info is used when output to xml.
         *
         *   SetDetAlive( bool isAlive, UInt4 first_detId, UInt4 last_detId=999999999 )
         *   @param  isAlive (bool) true: use, false: not use
         *   @param  first_detId (UInt4) first detId to be set
         *   @param  last_detId  (UInt4) last detId to be set, if not set, only first_detId is set.
         *   @return None
         */
    bool SetTofBinPattern( UInt4 patternId, UInt4 type, std::vector<Double> params );
        //!< Sets Tof binning pattern
        /*!<
         *   SetTofBinPattern( UInt4 patternId, UInt4 type, std::vector<Double> params )
         *   @param  patternId   (UInt4) patternId, if already patternId exists, overwrites
         *   @param  type        (UInt4) TofBin type
         *   @param  params      (std::vector<Double>) parameters for TofBin type)
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeleteTofBinPattern( UInt4 patternId );
        //!< Deletes Tof binning pattern
        /*!<
         *   DeleteTofBinPattern( UInt4 patternId )
         *   @param  patternId   (UInt4) patternId, if already patternId exists, overwrites
         *   @retval true    succeded
         *   @retval false   failed
         */
    void DeleteAllTofBinPattern();
        //!< Deletes all Tof binning pattern
        /*!<
         *   @param  None
         *   @return None
         */

    bool SetTofBinInfo( UInt4 patternId, Double offsetBin=0.0, Int4 maskPtnId=-1 );
    bool SetTofBinInfo( UInt4 start_detId, UInt4 end_detId, UInt4 patternId, Double offsetBin=0.0, Int4 maskPtnId=-1 );
    bool SetTofBinInfo( std::vector<UInt4> range, UInt4 patternId, Double offsetBin=0.0, Int4 maskPtnId=-1 );
        //!< Sets Tof binning info
        /*!<
         *   SetTofBinInfo( UInt4 patternId, UInt4 offsetBin=0 )
         *      this applys all detectors.
         *   SetTofBinInfo( UInt4 start_detId, UInt4 end_detId, UInt4 patternId, UInt4 offsetBin=0 );
         *      this applys detectors between start_detid and end_detId
         *   SetTofBinInfo( std::vector<UInt4> range, UInt4 patternId, UInt4 offsetBin=0 );
         *      this applys individual, example [0,12,15,16,20,0,25,29] => 0-12,15-16,20,25-29
         *   @param  start_detId (UInt4) detId range
         *   @param  end_detId   (UInt4) detId range
         *   @param  range       (std::vector<UInt4>)
         *   @param  patternId   (UInt4) patternId
         *   @param  offsetBin   (Double) offset value
         *   @param  maskPtnId   (Int4) mask pattern Id
         *   @retval true    succeded
         *   @retval false   failed
         */
    void DeleteAllTofBinInfo();
        //!< Deletes all Tof binning info
        /*!<
         *   @param  None
         *   @return None
         */
    bool SetFrameInfo( UInt4 frameNo, Double boundary, std::string type="tof" );
        //!< Sets Tof frame boundary parameters
        /*!<
         *   SetFrameInfo( UInt4 frameNo, Double boundary )
         *   @param frameNo    (UInt4) Frame Number
         *   @param boundary   (Double) TOF boundary
         *   @param type       (std::string)
         *   @retval true    succeded
         *   @retval false   failed
         */


    bool SetUseDetectorType( std::string _detType );
        //!< Makes detectors alive by given detector type
        /*!<
         *   @param  _detType (std::string) <detType1>[,<detType2>,...]
         *   @retval true    succeded
         *   @retval false   failed
         */


    bool SetTofMaskPattern( UInt4 patternId, std::vector<Double> params );
        //!< Sets Tof mask Pattern with pattern Id
        /*!<
         *   @param  patterinId (UInt4) pattern Id for given params
         *   @param  params     (std::vector<Double>) tof ranges list to be masked, [m1,m2,m3,m4,...,] means region of [m1:m2], [m3:m4] ... are masked.
         *   @retval true    succeded
         *   @retval false   failed
         */

    virtual bool SetDetectorRange( std::vector<UInt4> list_of_num_pixels, std::vector< std::pair< Int4,Int4 > > list_of_det_range, std::string det_type );
        //!< Makes the staus of given detectors alive or not
        /*!<
         *   @param list_of_num_pixels   (std::vector<UInt4>) the number of pixels of each detector ranges
         *   @param list_of_det_range    (std::vector< std::pair<Int4,Int4> >) detector ranges
         *   @param det_type             (std::string) type of all given detectors
         *   @retval true    succeded
         *   @retval false   failed
         */

    bool SetConversionParameter( std::string params, UInt4 _ptnId=0 );
        //!< Sets conversion parameters for histogram creation from event data
        /*!< This params are checked by WiringConversionDictionary class and used to calculate tof_bin_pattern.
         *
         *   @param params  (std::string) parameters to create histogram in string format
         *   @param _ptnId  (UInt4)  given pattern id for this parameter ( normally 1 )
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetDetParam( std::string params );
        //!< Sets detector parameters
        /*!< This method will be overrided by WiringInfoEditorNeunet to treat Pulse Height.
         *   In this class, this methods set only detector type in ["PSD","uPSD","MON","SCIN1D","RPMT","MWPC","WLSF32"]
         *
         *   @param params  (std::string) detector type
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetDetRange( std::string params );
        //!< Sets detector ranges to be used for histogram creation
        /*!< This params can include "All", range of detector ID, the number of pixels in a detector.
         *   ["All", <detId>-<detId>, <detId>-<detId>:num,...]
         *
         *   @param params  (std::string) detector range parameter(s)
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetFrameInfo( std::string params );
        //!< Sets tof frame treating information
        /*!< This params can include frame number and boundary tof.
         *   ["None" or <frameNo>,<boundaryTof> or "<type>:<boundary>" where type in ("tof","lambda","energy","ei") ]
         *
         *   @param params  (std::string) frame info parameter
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetMaskInfo( std::string params, UInt4 _ptnId );
        //!< sets MASK histogram creations
        /*!<     bool SetMaskInfo( std::string params="NoFile", UInt4 _ptnId=0 )
         *       Format of params
         *        "<Mask.xml>[,<TOF-Mask from>-< to > [,<TOF-Mask from>-<to>] ]"
         *            - Mask.xml = "NoFile" if no mask.
         *
         *   @param params   (std::string) detector parameters for histogram ceration
         *   @param _ptnId   (UInt4)  ID of this parameters in WiringInfo
         *   @retval true    : succeeded
         *   @retval false   : failed
         */
    //[inamura 160809]-->
    bool SetTimeDependBackGroundInfo( std::string params );
        //!< sets Tof region to be used for TimeDependBackground correction
        /*!<     bool SetTimeDependBackGroundInfo( std::string params="None" )
         *       Format of params
         *        "None" : not used this background correction
         *        "tof0-tof1" : tof0 is start tof of region, tof1 is last of region
         *
         *   @param params   (std::string) TimeDepend BackGroundRegion
         *   @retval true    : succeeded
         *   @retval false   : failed
         */
    void ImportTimeDependBackGroundInfo();
    std::vector< std::vector<Double>* >* PutTimeDependBackGroundList(){ return _WCD->TimeDependBackGroundRegion;}
    //<--[inamura 160809]
    void ClearReader( UInt4 index=0 );
    bool SetInfoAsReader();
    WiringInfoConversionDictionary* PutConversionDictionary(){ return _WCD;}
    void SetIgnoreModuleType( std::string tmp ){ _ignoreModuleType.push_back(tmp); }     //[inamura 170117]
    std::vector<UInt4> PutDaqList();
        //!< Returns list of DAQ ID described in WiringInfo
        /*!<
         *
         *   @retval std::vector<UInt4>
         */
    std::vector<UInt4> PutModuleList( UInt4 daqId );
        //!< Returns list of module No in given daqId described in WiringInfo
        /*!<
         *
         *   @param daqId (UInt4) DAQ Id
         *   @retval std::vector<UInt4>
         */
    std::vector<UInt4> PutDetectorList( UInt4 daqId, UInt4 modNo );
        //!< Returns list of detId in given daqId and module No described in WiringInfo
        /*!<
         *
         *   @param daqId (UInt4) DAQ Id
         *   @param modNo (UInt4) module No
         *   @retval std::vector<UInt4>
         */
    UtsusemiDetInfo* PutDetInfo( UInt4 daqId, UInt4 modNo, UInt4 detId );
    UInt4 PutNumOfPixelForDet(UInt4 _detId=0);
    std::vector<Int4> PutPixelInfoStore( UInt4 daqId, UInt4 modeNo, UInt4 detNo );
    void IgnoredXml( bool isIgnoredXml=true ){ _isReadXml=isIgnoredXml; }
    void FixHeadPixelId( bool isFixed=true ){ _isFixedHeadPixelId=isFixed; }
};
#endif
