#ifndef WIRINGINFOEDITORNEUNET
#define WIRINGINFOEDITORNEUNET

#include "WiringInfoEditorBase.hh"
#include <algorithm>

class WiringInfoDefineNeunet:
    public WiringInfoTagDefineBase
{
public:
    WiringInfoDefineNeunet();
    ~WiringInfoDefineNeunet();

    static const std::string WINFO_PSDPARAM;
    static const std::string WINFO_PSDPARAM_PARAM;
    static const std::string WINFO_PSDPARAM_PARAM_AT_ID;

    static const std::string WINFO_PSDBININFO;
    static const std::string WINFO_PSDBININFO_AT_SETID;
    static const std::string WINFO_PSDBININFO_BIN;
    static const std::string WINFO_PSDBININFO_BIN_AT_NUM;
    static const std::string WINFO_PSDBININFO_BIN_AT_DELTA;
    static const std::string WINFO_PSDBININFO_BIN_AT_OFFSET;

};

class UtsusemiPsdParam
{
public:
    UtsusemiPsdParam();
    UtsusemiPsdParam( const UtsusemiPsdParam& obj );
    ~UtsusemiPsdParam();

    UInt4 detId;
    Double valA;
    Double valB;
    Double valC;
    Double upperPH;
    Double lowerPH;

};
class UtsusemiPsdBinInfo
{
public:
    UtsusemiPsdBinInfo();
        //!< Constructor
        /*!<
         */
    UtsusemiPsdBinInfo( const UtsusemiPsdBinInfo& obj );
        //!< Copy Constructor
        /*!<
         */
    ~UtsusemiPsdBinInfo();
        //!< Destructor
        /*!<
         */
    bool SetConts( std::string conts );
        //!< Destructor
        /*!<
         */
    bool SetNewNumOfPixel( UInt4 num_of_pixel );
    std::string PutContsAsString();
    UInt4 numPixel;   /**< num of pixels  */
    //UInt4 deltaX;     /**< width value  */
    //Int4  offsetX;    /**< offset value  */
    //std::string conts;     /**< parameters descriptions as text */
    Double deltaX;
    Double offsetX;
    std::vector< std::pair<UInt4,UInt4> > conts;
};

class WiringInfoEditorNeunet:
    public WiringInfoEditorBase
{
private:
    WiringInfoDefineNeunet TAG;
    std::string _MessageTag;
protected:
    bool _makeOutputXmlNeunet();

public:
    bool _withPH;
    std::vector< UtsusemiPsdParam* > PsdParams;
    std::vector< UtsusemiPsdBinInfo* > PsdBinInfo;

    // Required as Reader
    std::vector< std::vector<Double>* > PsdBinInfoList;   /**< Replaced original PsdBinInfo  */
    std::vector< std::vector<Double>* >* PsdParamsList;       /**< Replaced original PsdParams */
    //std::vector< std::vector<Double>* > PsdBinInfo;       /**< Replaced by PsdBinInfoList */

    static const std::string PSD_A;
    static const std::string PSD_B;
    static const std::string PSD_C;
    static const std::string PSD_LLD;
    static const std::string PSD_HLD;

    static const Int4 DUMP_PSDPARAMS;
    static const Int4 DUMP_PSDBININFO;

    WiringInfoEditorNeunet();
        //!< Constructor
        /*!<
         */
    WiringInfoEditorNeunet( std::string wfile, bool workAsReader=true );
        //!< Constructor
        /*!<
         *   @params wfile (std::string) wiring file path
         *   @param workAsReader (bool)
         */
    ~WiringInfoEditorNeunet();
        //!< 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
         *    index = 5 : TrigInfoStore
         *    index = 6 : TofMaskPtn
         *    index = 7 : PsdParams
         *    index = 8 : PsdBinInfo
         *
         *   @param index (UInt4)
         *   @return None
         */
    void ClearReader( UInt4 index=0 );
    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 ImportPsdParams();
        //!< Analyzes xml descriptions for psd params (A,B,C,LDD)
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    void ImportPsdInfo();
        //!< Analyzes xml descriptions for PsdBinInfo
        /*!< This analyzes read xml descriptions
         *   @param  None
         *   @return None
         */
    std::vector<Double> PutPsdParams( UInt4 detId );
        //!< Puts PSD parameters for given detector ID
        /*!<
         *   PutPsdParams( UInt4 detId )
         *
         *   @param detId    (UInt4) detId
         *   @retval std::vector<Double> with size=0 : no PSD info
         *   @retval std::vector<Double> with size=5 : [<A val>, <B val>, <C val>, <Lower limit PH>, <Upper limit PH>]
         */
    bool SetPsdParams( UInt4 detId, Double Aval, Double Bval, Double Cval, Double PHlow, Double PHup );
    bool SetPsdParams( UInt4 detId, std::string tag, Double val );
        //!< Sets PSD parameters for each detector
        /*!<
         *   SetPsdParams( UInt4 detId, Double Aval, Double Bval, Double Cval, Double PHlow, Double PHup )
         *   SetPsdParams( UInt4 detId, std::string tag, Double val )
         *
         *   @param detId    (UInt4) detId
         *   @param Aval     (Double) A value of PSD
         *   @param Bval     (Double) B value of PSD
         *   @param Cval     (Double) C value of PSD
         *   @param PHlow    (Double) lower limit of pulse height value of PSD
         *   @param PHup     (Double) upper limit of pulse heignt value of PSD
         *   @param tag      (std::string) Key of parameters which must be "A","B","C","LLD","HLD"
         *   @param val      (Double) value for given Key
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool SetAllPsdParams( std::string tag, Double val );
        //!< Sets PSD parameters to all
        /*!<
         *   SetAllPsdParams( std::string tag, Double val )
         *
         *   @param tag      (std::string) Key of parameters which must be "A","B","C","LLD","HLD"
         *   @param val      (Double) value for given Key
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeletePsdParams( UInt4 start_detId=0, UInt4 end_detId=0 );
        //!< Deletes PSD parameters
        /*!<
         *   DeletePsdParams( UInt4 start_detId=0, UInt4 end_detId=0 )
         *
         *   @param start_detId  (UInt4) range of detId
         *   @param end_detId    (UInt4) range of detId
         *   @retval true    succeded
         *   @retval false   failed
         */
    void MakePsdInfo( UInt4 numPixel, Double deltaX, Double offsetX );
        //!< Makes PSD bin Info
        /*!< This collects detId which has same numPixel as given numPixel and makes PsdInfo
         *   MakePsdInfo( UInt4 numPixel, UInt4 deltaX, UInt4 offsetX )
         *
         *   @param numPixel  (UInt4) number of pixels in a PSD
         *   @param deltaX    (Double) width on X axis for each pixel
         *   @param offsetX   (Double) offset value on X axis
         *   @return None
         */
    bool SetPsdInfo( UInt4 numPixel, Double deltaX, Double offsetX, std::string conts );
    bool SetPsdInfo( Double deltaX, Double offsetX, UInt4 start_detId=0, UInt4 end_detId=0 );
        //!< Sets PSD bin Info
        /*!< This makes PSD info tag by given parameters without checking.
         *   SetPsdInfo( UInt4 numPixel, Double deltaX, Double offsetX, std::string conts )
         *   SetPsdInfo( Double deltaX, Double offsetX, UInt4 start_detId=0, UInt4 end_detId=0 )
         *
         *   @param numPixel  (UInt4) number of pixels in a PSD
         *   @param deltaX    (Double) width on X axis for each pixel
         *   @param offsetX   (Double) offset value on X axis
         *   @param conts     (std::string) contents of this tag
         *   @param start_detId (UInt4) range of detId
         *   @param end_detId   (UInt4) range of detId
         *   @retval true    succeded
         *   @retval false   failed
         */
    bool DeletePsdInfo( UInt4 index=999999999 );
        //!< Deletes Psd bin info
        /*!<
         *   DeletePsdInfo( UInt4 index=999999999 )
         *
         *   @param index  (UInt4) index for PsdBinInfo to be deleted
         *   @retval true    succeded
         *   @retval false   failed
         */
    void Dump( Int4 index=DUMP_ALL );
    bool SetNumPixelOfPsdBin( UInt4 num_of_pixel, Int4 start_id=-1, Int4 end_id=-1 );
    bool SetDetectorRange( std::vector<UInt4> list_of_num_pixels, std::vector< std::pair< Int4,Int4 > > list_of_det_range, std::string det_type );

    bool SetDetParam( std::string params="psd" );

    bool SetInfoAsReader();

};
#endif
