#include "SASDetectorInfoEditorRPMT.hh"
//////////////////////////////////////////////////////////
DetectorInfoTagDefineSAS::
DetectorInfoTagDefineSAS(){
}
//////////////////////////////////////////////////////////
DetectorInfoTagDefineSAS::
~DetectorInfoTagDefineSAS(){
}
//////////////////////////////////////////////////////////
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT="sas/rpmt";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_NUMLINES="numOfLines";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_BINWIDTH="binWidth";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_SIZEXCH="sizeXch";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_SIZEYCH="sizeYch";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_XCHSHIFT="XchShift";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_YCHSHIFT="YchShift";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_PHRANGEX="PHeightXRange";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_PHRANGEY="PHeightYRange";
const std::string DetectorInfoTagDefineSAS::DINFO_INSTRINFO_SASRPMT_IGRAVITYPARAM="incidentGravityParam";

//////////////////////////////////////////////////////////
SASDetectorInfoInstRPMT::
SASDetectorInfoInstRPMT(){
    numOfLines = 1024;
    binWidth = 2;
    sizeXch = 304;
    sizeYch = 304;
    XchShift = 0;
    YchShift = 0;
    PHRangeX.first = 128;
    PHRangeX.second = 1024;
    PHRangeY.first = 128;
    PHRangeY.second = 1024;
    incidentGravityParam = 0.0;
}
//////////////////////////////////////////////////////////
SASDetectorInfoInstRPMT::
SASDetectorInfoInstRPMT( const SASDetectorInfoInstRPMT& obj ){
    L1 = obj.L1;
    SamplePosition.resize(3,0.0);
    copy( obj.SamplePosition.begin(),obj.SamplePosition.end(),SamplePosition.begin() );
    TypicalL2 = obj.TypicalL2;
    TypicalDS = obj.TypicalDS;

    numOfLines = obj.numOfLines;
    binWidth = obj.binWidth;
    sizeXch = obj.sizeXch;
    sizeYch = obj.sizeYch;
    XchShift = obj.XchShift;
    YchShift = obj.YchShift;
    PHRangeX.first = obj.PHRangeX.first;
    PHRangeX.second = obj.PHRangeX.second;
    PHRangeY.first = obj.PHRangeY.first;
    PHRangeY.second = obj.PHRangeY.second;
    incidentGravityParam = obj.incidentGravityParam;
}
//////////////////////////////////////////////////////////
SASDetectorInfoInstRPMT::
~SASDetectorInfoInstRPMT(){
}
//////////////////////////////////////////////////////////
void SASDetectorInfoInstRPMT::
Dump(){
    std::cout << "numOfLines = " << numOfLines << std::endl;
    std::cout << "binWidth = " << binWidth << std::endl;
    std::cout << "sizeXch = " << sizeXch << std::endl;
    std::cout << "sizeYch = " << sizeYch << std::endl;
    std::cout << "XchShift = " << XchShift << std::endl;
    std::cout << "YchShift = " << YchShift << std::endl;
    std::cout << "PulseHeight Range for X = " << PHRangeX.first << " - " << PHRangeX.second << std::endl;
    std::cout << "PulseHeight Range for Y = " << PHRangeY.first << " - " << PHRangeY.second << std::endl;
    std::cout << "incidentGravityParam = " << incidentGravityParam << std::endl;
}

//////////////////////////////////////////////////////////
SASDetectorInfoEditorRPMT::
SASDetectorInfoEditorRPMT()
{
    _instRPMT = NULL;
    Initialize();
}
//////////////////////////////////////////////////////////
SASDetectorInfoEditorRPMT::
SASDetectorInfoEditorRPMT( std::string dfile, bool workAsReader):UtsusemiDetectorInfoEditorNeunet(dfile, workAsReader){
    _instRPMT = NULL;
    Initialize();
    if ( Read(dfile) ){
        if (workAsReader)
            this->_DE->SetInfoAsReader();
        this->_DE->_Status=true;
    }else{
        this->_DE->_Status=false;
    }
}
//////////////////////////////////////////////////////////
SASDetectorInfoEditorRPMT::
~SASDetectorInfoEditorRPMT()
{
    Clear(0);
    //DetectorInfoEditorNeunet::ClearReader(0);
    this->_DE->ClearReader(0);
    delete _st;
}

//////////////////////////////////////////////////////////
void SASDetectorInfoEditorRPMT::
Initialize(){
    _MessageTag = "SASDetectorInfoEditorRPMT::";
    _st = new StringTools();
    //DetectorInfoEditorNeunet::Initialize();
    if (_instRPMT != NULL) delete _instRPMT;
    _instRPMT = NULL;

    _bcX = 0.0;
    _bcY = 0.0;
    _rotAng = 0.0;
    _unitPixelSizeX = 0.205;
    _unitPixelSizeY = 0.207;

    _KEY_WRITE_XML = this->_DE->KEY_WRITE_XML;
    _KEY_READ_XML = this->_DE->KEY_READ_XML;
}
//////////////////////////////////////////////////////////
void SASDetectorInfoEditorRPMT::
Clear( UInt4 index ){
    if (_instRPMT!=NULL){
        delete _instRPMT;
    }
    _instRPMT = NULL;

    //DetectorInfoEditorNeunet::Clear(index);
    this->_DE->Clear(index);
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::
Read( std::string arg ){
    //if (DetectorInfoEditorNeunet::Read(arg)){
    if (this->_DE->Read(arg)){
        // required only for SAS/RPMT
        ImportInstSASRPMTInfo();
        this->_DE->_Status = true;
    }
    return this->_DE->_Status;
}
//////////////////////////////////////////////////////////
void SASDetectorInfoEditorRPMT::
ImportInstSASRPMTInfo(){
    if (_instRPMT == NULL) _instRPMT = new SASDetectorInfoInstRPMT();
    std::string sas_rpmt_path = TAGSAS.DINFO + "/" + TAGSAS.DINFO_INSTRINFO + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT;
    if (this->_DE->_parser->hasPath( _KEY_READ_XML, sas_rpmt_path )){
        std::string path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_NUMLINES;
        std::string tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->numOfLines = _st->StringToUInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_BINWIDTH;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->binWidth = _st->StringToUInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_SIZEXCH;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->sizeXch = _st->StringToUInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_SIZEYCH;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->sizeYch = _st->StringToUInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_XCHSHIFT;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->XchShift = _st->StringToInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_YCHSHIFT;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->YchShift = _st->StringToInt4( tmp );
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_PHRANGEX;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            std::vector<std::string> tmp_v = _st->SplitString( tmp, "," );
            if (tmp_v.size()==2){
                _instRPMT->PHRangeX.first = _st->StringToUInt4(tmp_v[0]);
                _instRPMT->PHRangeX.second = _st->StringToUInt4(tmp_v[1]);
            }
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_PHRANGEY;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            std::vector<std::string> tmp_v = _st->SplitString( tmp, "," );
            if (tmp_v.size()==2){
                _instRPMT->PHRangeY.first = _st->StringToUInt4(tmp_v[0]);
                _instRPMT->PHRangeY.second = _st->StringToUInt4(tmp_v[1]);
            }
        }
        path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_IGRAVITYPARAM;
        tmp = this->_DE->_parser->PutContent( _KEY_READ_XML, path, "" );
        if (!tmp.empty()){
            _instRPMT->incidentGravityParam = _st->StringToDouble(tmp);
        }
    }
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::
Write( std::string filepath ){
    if (_makeOutputXmlSASRPMTInfo()){
        this->_DE->_parser->Save( _KEY_WRITE_XML, filepath );
    }else{
        UtsusemiError( _MessageTag+"Write : false to make output XML from given information. " );
        return false;
    }
    return true;
}
//////////////////////////////////////////////////////////
std::string SASDetectorInfoEditorRPMT::
OutXml( bool withIndent ){
    if (_makeOutputXmlSASRPMTInfo()){
        return this->_DE->_parser->OutToString( _KEY_WRITE_XML, "", withIndent );
    }else{
        UtsusemiError( _MessageTag+"OutXml : false to make output XML from given information. " );
        return "";
    }
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::
_makeOutputXmlSASRPMTInfo(){
    if (_convPositionInfo()){
    }else{
        return false;
    }
    //if (DetectorInfoEditorNeunet::_makeOutputXmlNeunet()){
    if (this->_DE->_makeOutputXmlNeunet()){
        if (_instRPMT!=NULL){
            std::string sas_rpmt_path = TAGSAS.DINFO + "/" + TAGSAS.DINFO_INSTRINFO + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT;
            std::string path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_NUMLINES;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->UInt4ToString( _instRPMT->numOfLines ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_BINWIDTH;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->UInt4ToString( _instRPMT->binWidth ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_SIZEXCH;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->UInt4ToString( _instRPMT->sizeXch ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_SIZEYCH;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->UInt4ToString( _instRPMT->sizeYch ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_XCHSHIFT;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->Int4ToString( _instRPMT->XchShift ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_YCHSHIFT;
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->Int4ToString( _instRPMT->YchShift ));
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_PHRANGEX;
            std::string range_st = _st->UInt4ToString( _instRPMT->PHRangeX.first ) + ",";
            range_st += _st->UInt4ToString( _instRPMT->PHRangeX.second );
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, range_st );
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_PHRANGEY;
            range_st = _st->UInt4ToString( _instRPMT->PHRangeY.first ) + ",";
            range_st += _st->UInt4ToString( _instRPMT->PHRangeY.second );
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, range_st );
            path = sas_rpmt_path + "/" + TAGSAS.DINFO_INSTRINFO_SASRPMT_IGRAVITYPARAM;
            Char gp[24];
            std::snprintf( gp, sizeof(gp), "%.10f", _instRPMT->incidentGravityParam );
            std::string igp = std::string( gp );
            this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, igp);
            //this->_DE->_parser->AddElement( _KEY_WRITE_XML, path, _st->DoubleToString( _instRPMT->incidentGravityParam ));
        }
        return true;
    }
    return false;
}
//////////////////////////////////////////////////////////
void SASDetectorInfoEditorRPMT::Dump(){
    //DetectorInfoEditorBase::Dump();
    this->_DE->Dump();
    if (_instRPMT!=NULL) _instRPMT->Dump();
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::SetChannelShift( Int4 x, Int4 y){
    if (_instRPMT == NULL) return false;
    _instRPMT->XchShift = x;
    _instRPMT->YchShift = y;
    return true;
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::SetBeamCenterPixel( Double x, Double y ){
    if ((x<0.0)||(y<0.0)) return false;
    _bcX = x;
    _bcY = y;
    return true;
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::SetRotateAngle( Double ang ){
    _rotAng = ang;
    return true;
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::SetIncidentGravityParam( Double b ){
    if (_instRPMT!=NULL){
        _instRPMT->incidentGravityParam = b;
        return true;
    }else
        return false;
}
//////////////////////////////////////////////////////////
bool SASDetectorInfoEditorRPMT::_convPositionInfo(){
    std::vector<UInt4> detId_list = this->_DE->PutPositionInfoDetIdList();
    if (detId_list.empty()) return true;

    if ((_bcX == 0.0)&&(_bcY == 0.0)&&(_rotAng == 0.0)) return true;

    //Shift
    Double spX = (_bcX - _instRPMT->sizeXch/2.0) * _unitPixelSizeX;
    Double spY = (_bcY - _instRPMT->sizeYch/2.0) * _unitPixelSizeY;
    //std::cout << "#[inamura 221231] spX, spY = "<<spX<<" , "<<spY<<std::endl;

    std::vector<Double> pms0 = this->_DE->PutPositionInfoParams(detId_list[0]);
    std::vector<Double> pms1 = this->_DE->PutPositionInfoParams(detId_list.back());

    //Shift both terminal points of the center line
    Double p0_x0 = pms0[0] - spX;
    Double p0_y0 = pms0[1] - spY;
    Double p0_x1 = pms1[0] - spX;
    Double p0_y1 = pms1[1] - spY;
    //std::cout << "#[inamura 221231] P0 = "<<p0_x0<<" , "<<p0_y0<<std::endl;
    //std::cout << "#[inamura 221231] P1 = "<<p0_x1<<" , "<<p0_y1<<std::endl;

    //Rotate both terminal points of the center line
    Double ang_rad = _rotAng / 180.0 * M_PI;
    Double p1_x0 = p0_x0 * cos(ang_rad) - p0_y0 * sin(ang_rad) + spX;
    Double p1_y0 = p0_x0 * sin(ang_rad) + p0_y0 * cos(ang_rad) + spY;
    Double p1_x1 = p0_x1 * cos(ang_rad) - p0_y1 * sin(ang_rad) + spX;
    Double p1_y1 = p0_x1 * sin(ang_rad) + p0_y1 * cos(ang_rad) + spY;
    //std::cout << "#[inamura 221231] P0 = "<<p1_x0<<" , "<<p1_y0<<std::endl;
    //std::cout << "#[inamura 221231] P1 = "<<p1_x1<<" , "<<p1_y1<<std::endl;

    //difference between pixels on the center line
    Double dx = (p1_x1 - p1_x0) / (_instRPMT->sizeXch - 1);
    Double dy = (p1_y1 - p1_y0) / (_instRPMT->sizeYch - 1);
    //std::cout << "#[inamura 221231] dX, dY = "<<dx<<" , "<<dy<<std::endl;

    //Rotation of detector std::vector
    Double pl_x0 = pms0[3];
    Double pl_y0 = pms0[4];
    Double pl_x1 = pl_x0 * cos(ang_rad) - pl_y0 * sin(ang_rad);
    Double pl_y1 = pl_x0 * sin(ang_rad) + pl_y0 * cos(ang_rad);

    //Change position information
    for (UInt4 i=0; i<detId_list.size(); i++){
        UInt4 detId = detId_list[i];
        std::vector<Double> pn = this->_DE->PutPositionInfoParams(detId);

        Double pn_x = p1_x0 + (dx * (Double)i);
        Double pn_y = p1_y0 + (dy * (Double)i);

        pn[0] = pn_x;
        pn[1] = pn_y;
        pn[3] = pl_x1;
        pn[4] = pl_y1;

        this->_DE->SetPositionInfo(detId, 1, pn);
    }
    return true;
}
//////////////////////////////////////////////////////////
UInt4 SASDetectorInfoEditorRPMT::PutNumOfLines(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->numOfLines;
}
//////////////////////////////////////////////////////////
UInt4 SASDetectorInfoEditorRPMT::PutBinWidth(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->binWidth;
}
//////////////////////////////////////////////////////////
UInt4 SASDetectorInfoEditorRPMT::PutSizeXch(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->sizeXch;
}
//////////////////////////////////////////////////////////
UInt4 SASDetectorInfoEditorRPMT::PutSizeYch(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->sizeYch;
}
//////////////////////////////////////////////////////////
Int4 SASDetectorInfoEditorRPMT::PutXchShift(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->XchShift;
}
//////////////////////////////////////////////////////////
Int4 SASDetectorInfoEditorRPMT::PutYchShift(){
  if (_instRPMT == NULL) return 0;
  return _instRPMT->YchShift;
}
//////////////////////////////////////////////////////////
std::pair<UInt4,UInt4> SASDetectorInfoEditorRPMT::PutPHRangeX(){
  if (_instRPMT == NULL){
    std::pair<UInt4,UInt4> empty;
    return empty;
  }
  return _instRPMT->PHRangeX;
}
//////////////////////////////////////////////////////////
std::pair<UInt4,UInt4> SASDetectorInfoEditorRPMT::PutPHRangeY(){
  if (_instRPMT == NULL){
    std::pair<UInt4,UInt4> empty;
    return empty;
  }
  return _instRPMT->PHRangeY;
}
//////////////////////////////////////////////////////////
Double SASDetectorInfoEditorRPMT::PutIncidentGravityParam(){
  if (_instRPMT == NULL) return 0.0;
  return _instRPMT->incidentGravityParam;
}
//////////////////////////////////////////////////////////
Double SASDetectorInfoEditorRPMT::PutL2(){
  if (_instRPMT == NULL) return 0.0;
  return this->PutInstTypicalL2();
}
