#include "CaseInfoReaderBase.hh"

////////////////////////////////////////
CaseInfoReaderBase::
CaseInfoReaderBase(){
    Initialize();
}
////////////////////////////////////////
CaseInfoReaderBase::
CaseInfoReaderBase(std::string filename){
    Initialize();
    ReadFile(filename);
}

////////////////////////////////////////
CaseInfoReaderBase::
~CaseInfoReaderBase(){
    delete mxReader;
    delete stools;
}
////////////////////////////////////////
void CaseInfoReaderBase::
Initialize(){
    hasInfo = false;
    mxReader = NULL;
    MessageTag = "CaseInfoReaderBase > ";
    _TimeSlicing = NULL;
    stools = new StringTools();
}
////////////////////////////////////////
bool CaseInfoReaderBase::
ReadFile(std::string filename){
    if (mxReader != NULL) delete mxReader;
    mxReader = new BoostXmlParser( "CaseInfo", filename );
    mxReader->SetQuiet( !(UtsusemiEnvGetDebugMode()) );
    UtsusemiMessage( MessageTag+"Read :"+filename );
    if (mxReader->hasPath("CaseInfo", "caseInfo")){
        hasInfo = true;
    }else{
        UtsusemiError( MessageTag+"Invalid file" );
        hasInfo = false;
    }
    return hasInfo;
}
////////////////////////////////////////
void CaseInfoReaderBase::
Clear(){
    if (_TimeSlicing!=NULL) {
        for (UInt4 i=0;i<_TimeSlicing->size();i++)
            if (_TimeSlicing->at(i)!=NULL) delete _TimeSlicing->at(i);
        delete _TimeSlicing;
        _TimeSlicing=NULL;
    }
}
////////////////////////////////////////
bool CaseInfoReaderBase::
ImportCaseInfo(std::string filename){
    if (mxReader==NULL)
        if ((filename=="")||(!ReadFile(filename))) return false;

    std::string xmlpath_root = "caseInfo";
    std::string xmlpath_base = xmlpath_root+"/timeSlicing";
    if (_TimeSlicing!=NULL) Clear();
    if (mxReader->hasPath( "CaseInfo", xmlpath_base )){
        std::string cond_type = mxReader->putTextContent( "CaseInfo", xmlpath_base, "type" );
        if ((cond_type=="")||(cond_type=="1")){ // Contents includes many <time> tags
            std::vector<std::string> case_list_sv = mxReader->PutAttValList("CaseInfo",xmlpath_base+"/time","caseId");
            std::vector<UInt4> case_list_v(case_list_sv.size(),0);
            for (UInt4 i=0; i<case_list_v.size(); i++)
                case_list_v[i] = stools->StringToUInt4( case_list_sv[i] );
            if (case_list_v.empty()){
                std::string reserved = mxReader->PutContent("CaseInfo",xmlpath_base,"reserved");
                if (reserved!=""){
                    UInt4 num_reserved = stools->StringToUInt4( reserved );
                    if (_TimeSlicing==NULL) _TimeSlicing = new std::vector< std::pair<double,double>* >( num_reserved+1, NULL);
                    for (UInt4 i=0; i<num_reserved+1; i++) _TimeSlicing->at(i) = new std::pair<double,double>;
                    return true;
                }
                return false;
            }
            sort( case_list_v.begin(), case_list_v.end() );
            UInt4 max_caseId = case_list_v.back();
            if (_TimeSlicing==NULL) _TimeSlicing = new std::vector< std::pair<double,double>* >( max_caseId+1, NULL);
            if (max_caseId>=(_TimeSlicing->size())) _TimeSlicing->resize( max_caseId+1, NULL );

            for (std::vector<UInt4>::iterator it=case_list_v.begin(); it!=case_list_v.end(); ++it){
                std::string xmlpath_time = xmlpath_base+"/time,caseId="+stools->UInt4ToString( *it );
                std::string conts = mxReader->PutContent("CaseInfo",xmlpath_time,"");
                std::vector<std::string> cont_list = stools->SplitString( conts, "," );
                if (cont_list.size()<2) continue;
                if (_TimeSlicing->at( *it )==NULL) _TimeSlicing->at(*it)=new std::pair<double,double>;
                _TimeSlicing->at(*it)->first = stools->StringToDouble( cont_list[0] );
                _TimeSlicing->at(*it)->second= stools->StringToDouble( cont_list[1] );
            }
        }else if (cond_type=="2"){
            std::string conts = mxReader->PutContent("CaseInfo",xmlpath_base+"/time","");
            std::vector<std::string> cont_list = stools->SplitString( conts, "," );
            if (cont_list.size()>2){
                Double st = stools->StringToDouble( cont_list[0] );
                Double et = stools->StringToDouble( cont_list[1] );
                Double dt = stools->StringToDouble( cont_list[2] );
                UInt4 caseId = 1;
                Double ct = st;
                if (_TimeSlicing==NULL) _TimeSlicing = new std::vector< std::pair<double,double>* >();

                while( ct<=et ){
                    if (caseId>=(_TimeSlicing->size())) _TimeSlicing->resize( caseId+1, NULL );
                    if (_TimeSlicing->at(caseId)==NULL) _TimeSlicing->at(caseId) = new std::pair<double,double>;
                    _TimeSlicing->at(caseId)->first  = ct;
                    _TimeSlicing->at(caseId)->second = ct+dt;
                    ct += dt;
                    caseId++;
                }
            }
        }else{
            UtsusemiError("CaseInfoReaderBase::ImportCaseInfo TimeSlicing/time type is invalid.");
        }
    }else
        return false;

    return true;
}
////////////////////////////////////////
void CaseInfoReaderBase::
SetTimeSlicing( std::vector<Double> tmp ){

    UInt4 max_caseId = int(tmp.size()/2);
    if (_TimeSlicing==NULL) _TimeSlicing = new std::vector< std::pair<double,double>* >(max_caseId+1, NULL);
    if (max_caseId>=_TimeSlicing->size()) _TimeSlicing->resize( max_caseId+1, NULL );

    for (UInt4 caseId=1; caseId<(max_caseId+1); caseId++){
        if (_TimeSlicing->at(caseId)==NULL)
            _TimeSlicing->at(caseId) = new std::pair<double,double>;
        Double p1 = tmp[ (caseId-1)*2 ];
        Double p2 = tmp[ (caseId-1)*2 +1];
        if ((p1<0.)&&(p2<0.)){
            delete _TimeSlicing->at(caseId);
            _TimeSlicing->at(caseId)=NULL;
        }else{
            _TimeSlicing->at(caseId)->first  = p1;
            _TimeSlicing->at(caseId)->second = p2;
        }
    }
}
