#include "UtsusemiHeader.hh"
////////////////////////////////////////////////
UtsusemiLogger &UtsusemiLogger::getInstance(){
    static UtsusemiLogger instance;
    return instance;
}
////////////////////////////////////////////////
void UtsusemiLogger::CheckLogQuiet(){
    _isQuiet=UtsusemiEnvGetIsQuiet();
}
////////////////////////////////////////////////
void UtsusemiLogger::Initialize(){
    if (_Label.empty()){
        _Label.resize(3);
        _Label[0] = "Message";
        _Label[1] = "Warning";
        _Label[2] = "ERROR";
    }
    _isLogging=false;
    CheckLogQuiet();
}
////////////////////////////////////////////////
std::string UtsusemiLogger::_convT( const time_t *timer ){
    struct tm *t_st = localtime( timer );
    char timec[30];
    strftime( timec, 30, "%Y/%m/%d %H:%M:%S", t_st );
    std::string ret(timec);
    return ret;
}
////////////////////////////////////////////////
void UtsusemiLogger::Add( const Int4 level, const std::string msg, const bool isForce ){
    if (_Label.empty()) Initialize();

    time_t timer;
    time(&timer);
    //_Timer.push_back( ((double)timer/1000.0) );
    bool pre_isQuiet = _isQuiet;
    if (isForce) _isQuiet = false;
    if (_isLogging){
        _Timer.push_back( _convT( &timer ) );
        _Levels.push_back(level);
        _Messages.push_back(msg);
    }
    if (!_isQuiet) std::cout << "["+_convT( &timer )+"] "+_Label[level]+" : "+msg << std::endl;
    _isQuiet = pre_isQuiet;
}
////////////////////////////////////////////////
void UtsusemiLogger::
Add( const std::vector<Int4> levels, const std::vector<std::string> msgs){
    if (_Label.empty()) Initialize();
    if (levels.size()!=msgs.size()) {
        std::cout << "UtsusemiLoggerAdd :: arguments sizes are not same." << std::endl;
        return;
    }
    time_t timer;
    time(&timer);
    //double t = (double)timer/1000.0;
    if (!_isQuiet){
        for (UInt4 i=0; i<msgs.size(); i++)
            std::cout << "["+_convT( &timer )+"]"+ _Label[levels[i]]+" : "+msgs[i] << std::endl;
    }
    if (_isLogging){
        for (UInt4 i=0; i<msgs.size(); i++){
            //_Timer.push_back( t );
            _Timer.push_back( _convT( &timer ) );
            _Levels.push_back( levels[i] );
            _Messages.push_back( msgs[i] );
        }
    }
}
////////////////////////////////////////////////
void UtsusemiLogger::
Add( const std::vector<Int4> levels, const std::vector<std::string> msgs, const std::vector<std::string> timer ){
    if (_Label.empty()) Initialize();
    if ( (levels.size()!=msgs.size()) || (levels.size()!=timer.size()) ){
        std::cout << "UtsusemiLoggerAdd :: arguments sizes are not same." << std::endl;
        return;
    }
    if (!_isQuiet){
        for (UInt4 i=0; i<msgs.size(); i++)
            std::cout << "["+timer[i]+"]"+_Label[levels[i]]+" : "+ msgs[i] << std::endl;
    }
    if (_isLogging){
        for (UInt4 i=0; i<msgs.size(); i++){
            _Timer.push_back( timer[i] );
            _Levels.push_back( levels[i] );
            _Messages.push_back( msgs[i] );
        }
    }
}
////////////////////////////////////////////////
void UtsusemiLogger::
Clear(){
    _Timer.clear();
    _Levels.clear();
    _Messages.clear();
}
//////////////////////////////////////////////////////////
std::vector<std::string> UtsusemiLogger::
PutMessages(const Int4 level){
    if (level<0) return _Messages;
    std::vector<std::string> ret;
    for (UInt4 i=0; i<_Messages.size(); i++)
        if (_Levels[i]==level) ret.push_back( _Messages[i] );

    return ret;
}
////////////////////////////////////////////////
void UtsusemiLogger::Dump( std::string filename ){
    if (_Label.empty()) Initialize();
    if (filename==""){
        for (UInt4 i=0; i<_Messages.size(); i++){
            char aline[256];
            //std::snprintf( aline, sizeof(aline), "[%lf] %s : %s",_Timer[i],_Label[ (UInt4)_Levels[i] ].c_str(), _Messages[i].c_str());
            std::snprintf( aline, sizeof(aline), "[%s] %s : %s",_Timer[i].c_str(),_Label[ (UInt4)_Levels[i] ].c_str(), _Messages[i].c_str());
            std::string aline_s(aline);
            std::cout << aline_s << std::endl;
        }
    }else{
        FILE *fp;
        fp = fopen( filename.c_str(), "w" );
        for (UInt4 i=0; i<_Messages.size(); i++)
            //fstd::printf(fp,"[%lf] %s : %s\n",_Timer[i],_Label[ (UInt4)_Levels[i] ].c_str(), _Messages[i].c_str());
           std::fprintf(fp,"[%s] %s : %s\n",_Timer[i].c_str(),_Label[ (UInt4)_Levels[i] ].c_str(), _Messages[i].c_str());
        fclose(fp);
    }
}

void UtsusemiError( const std::string msg, const bool isForce  ){
    UtsusemiLogger::getInstance().Add( 2, msg, isForce );
}
std::vector<std::string> UtsusemiPutErrorMessages(){
    return UtsusemiLogger::getInstance().PutMessages(2);
}

void UtsusemiWarning( const std::string msg, const bool isForce  ){
    UtsusemiLogger::getInstance().Add( 1, msg, isForce );
}
std::vector<std::string> UtsusemiPutWarningMessages(){
    return UtsusemiLogger::getInstance().PutMessages(1);
}

void UtsusemiMessage( const std::string msg, const bool isForce ){
    UtsusemiLogger::getInstance().Add( 0, msg, isForce );
}
std::vector<std::string> UtsusemiPutMessages(){
    return UtsusemiLogger::getInstance().PutMessages(0);
}
void UtsusemiCheckLogQuiet(){
    UtsusemiLogger::getInstance().CheckLogQuiet();
}
void UtsusemiLoggerDump(const std::string filename){
    UtsusemiLogger::getInstance().Dump(filename);
}
void UtsusemiLoggerOn(){
    UtsusemiLogger::getInstance().SetLoggingOn();
}
void UtsusemiLoggerOff(){
    UtsusemiLogger::getInstance().SetLoggingOff();
}
bool UtsusemiLoggerStatus(){
    return UtsusemiLogger::getInstance().LoggingStatus();
}
void UtsusemiLoggerClear(){
    UtsusemiLogger::getInstance().Clear();
}

////////////////////////////////////////////////
UtsusemiRunDataPathDict &UtsusemiRunDataPathDict::getInstance(){
    static UtsusemiRunDataPathDict instance;
    return instance;
}
////////////////////////////////////////////////
void UtsusemiRunDataPathDict::Initialize(){
    Clear();
}
////////////////////////////////////////////////
void UtsusemiRunDataPathDict::Add( const std::string runNo, const std::vector<std::string> runFolders){
    if (_DictRunDataFolder.Check(runNo)==1){
        UtsusemiWarning( "UtsusemiRunDataPathDict::Add  Already Added this runNo = "+ runNo );
        _DictRunDataFolder.Remove(runNo);
    }
    _DictRunDataFolder.Add(runNo,runFolders);
}
////////////////////////////////////////////////
std::vector<std::string> UtsusemiRunDataPathDict::Put(const std::string runNo){
    std::vector<std::string> empty_vec;
    empty_vec.clear();
    if (_DictRunDataFolder.Check(runNo)==0) return empty_vec;
    else
        return _DictRunDataFolder.Put(runNo);
}
////////////////////////////////////////////////
void UtsusemiRunDataPathDict::Dump(){
    _DictRunDataFolder.Dump();
}
////////////////////////////////////////////////
void UtsusemiRunDataPathDict::Clear(){
    _DictRunDataFolder.Clear();
}

std::vector<std::string> UtsusemiPutRunDataPathFromDict(const std::string runNo){
    return UtsusemiRunDataPathDict::getInstance().Put( runNo );
}
void UtsusemiAddRunDataPathToDict(const std::string runNo, const std::vector<std::string> runFolders){
    UtsusemiRunDataPathDict::getInstance().Add( runNo, runFolders );
}
void UtsusemiDumpRunDataPathDict(){
    UtsusemiRunDataPathDict::getInstance().Dump();
}
void UtsusemiClearRunDataPathDict(){
    UtsusemiRunDataPathDict::getInstance().Clear();
}

////////////////////////////////////////////////
// for VC++ only
#ifdef _MSC_VER

#if _MSC_VER<1900
    double round(double x) {
        return (x > 0.0) ? floor(x + 0.5) : ceil(x - 0.5);
    }
#endif
//
//    #include <Windows.h>
//    void usleep(int usec){
//        Sleep(usec / 1000); // Sleep takes a value in "msec"
//    }
#endif


////////////////////////////////////////////////
UInt4 UtsusemiGetNumOfMulTh(){
    const char *multh_c = getenv(UTSUSEMI_DEFINE_MULTH);
    UInt4 multh = 0;
    if (multh_c!=NULL){
        std::string multh_s(multh_c);
        if (multh_s!=""){
            StringTools st;
            multh = st.StringToUInt4( multh_s );
        }
    }
#ifdef MULTH
    if (multh == 0) multh = MULTH;
    multh = std::min((UInt4)MULTH, multh);
    return std::min(multh, (UInt4)omp_get_num_procs());
#else
    return 1;
#endif
}
////////////////////////////////////////////////
UInt4 UtsusemiEnvGetNumOfMulTh(){
    return UtsusemiGetNumOfMulTh();
}

////////////////////////////////////////////////
std::string UtsusemiEnvGetDataDir(){
    const char *data_c = getenv(UTSUSEMI_DEFINE_DATA_DIR);
    if (data_c!=NULL){
        std::string data_s(data_c);
        return data_s;
    }else{
        UtsusemiError( "UtsusemiEnvGetDataDir : Not set UTSUSEMI_DATA_DIR ");
        return "";
    }
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetBaseDir(){
    const char *data_c = getenv("UTSUSEMI_BASE_DIR");
    if (data_c!=NULL){
        std::string data_s(data_c);
        return data_s;
    }else{
        UtsusemiError( "UtsusemiEnvGetDataDir : Not set UTSUSEMI_BASE_DIR ");
        return "";
    }
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetInstCode(){
    const char *inst_c = getenv(UTSUSEMI_DEFINE_INST_CODE);
    if (inst_c!=NULL){
        std::string inst_s(inst_c);
        return inst_s;
    }else{
        const char *inst_c2 = getenv("UTSUSEMI_SYS_NAME");
        if (inst_c2!=NULL){
            UtsusemiWarning( "UtsusemiEnvGetInstCode : Please use UTSUSEMI_INST_CODE insteed of UTSUSEMI_SYS_NAME");
            std::string inst_s2(inst_c2);
            return inst_s2;
        }
        UtsusemiError( "UtsusemiEnvGetInstCode : Not set UTSUSEMI_INST_CODE ");
        return "";
    }
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetInstDataDir(){
    std::string data_dir  = UtsusemiEnvGetDataDir();
    std::string inst_code = UtsusemiEnvGetInstCode();
    if ((data_dir!="")&&(inst_code!=""))
        return data_dir+"/"+inst_code;
    else
        return "";
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetInstDir(){
    std::string base_dir = UtsusemiEnvGetBaseDir();
    std::string inst_code= UtsusemiEnvGetInstCode();
    if ((base_dir!="")&&(inst_code!=""))
        return base_dir+"/"+inst_code;
    else
        return "";
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetUserDir(){
    const char *c = getenv(UTSUSEMI_DEFINE_USR_DIR);
    if (c!=NULL){
        std::string s(c);
        return s;
    }else{
        const char *c2 = getenv("HOME");
        if (c2!=NULL){
            UtsusemiWarning("UtsusemiEnvGetUserCode : Not set UTSUSEMI_USR_DIR, use HOME ");
            std::string s2(c2);
            return s2;
        }
        UtsusemiError( "UtsusemiEnvGetUserCode : Not set UTSUSEMI_USR_DIR ");
        return "";
    }
}
////////////////////////////////////////////////
std::string UtsusemiEnvGetWorkDir(){
    const char *c = getenv(UTSUSEMI_DEFINE_WORK_DIR);
    if (c!=NULL){
        std::string s(c);
        return s;
    }else{
        /*
        const char *c2 = getenv(UTSUSEMI_DEFINE_USR_DIR);
        if (c2!=NULL){
            std::string s(c2);
            return s;
        }
        */
        return "";
    }
}
////////////////////////////////////////////////
bool UtsusemiEnvGetDebugMode(){
    const char *c = getenv(UTSUSEMI_DEFINE_DEBUGMODE);
    if (c!=NULL){
        std::string s(c);
        if ((s=="y")||(s=="Y"))
            return true;
        else if ((s=="n")||(s=="N"))
            return false;
        else
            UtsusemiWarning("UtsusemiEnvGetDebugMode : UTSUSEMI_DEBUGMODE must be y,Y,n and N");
    }
    return false;
}
////////////////////////////////////////////////
bool UtsusemiEnvGetIsQuiet(){
    const char *c = getenv(UTSUSEMI_DEFINE_LOG_QUIET);
    if (c!=NULL){
        std::string s(c);
        if ((s=="y")||(s=="Y"))
            return true;
        else if ((s=="n")||(s=="N"))
            return false;
        else
            UtsusemiWarning("UtsusemiEnvGetDebugMode : UTSUSEMI_IGNORE_EMPTYFILE must be y,Y,n and N");
    }
    return false;
}
///////////////////////////////////////////////
bool UtsusemiEnvGetIgnoreEmptyFile(){
    const char *c = getenv(UTSUSEMI_DEFINE_IGNORE_EMPTYFILE);
    if (c!=NULL){
        std::string s(c);
        if ((s=="y")||(s=="Y"))
            return true;
        else if ((s=="n")||(s=="N"))
            return false;
        else
            UtsusemiWarning("UtsusemiEnvGetDebugMode : UTSUSEMI_IGNORE_EMPTYFILE must be y,Y,n and N");
    }
    return false;
}
//////////////////////////////////////////////////////////
std::string FindParamFilePath(std::string target, std::string additionalPath ){
    return _FindFilePath( target, UTSUSEMIUSERPRIVXMLFILEPATH, additionalPath, true );
}
//////////////////////////////////////////////////////////
std::string FindTempFilePath(std::string target, std::string additionalPath ){
    return _FindFilePath( target, UTSUSEMIUSERPRIVTEMPORALFILEPATH, additionalPath, false );
}
//////////////////////////////////////////////////////////
std::string _FindFilePath( std::string target, std::string interPath, std::string additionalPath, bool isParam ){
    std::string empty_ret = "";
    bool isFound = false;

    char target_path_c[400];
    if (additionalPath!=""){

        if (target!="")
            std::snprintf( target_path_c, sizeof(target_path_c), "%s/%s", additionalPath.c_str(),target.c_str() );
        else
            std::snprintf( target_path_c, sizeof(target_path_c), "%s", additionalPath.c_str() );

        const boost::filesystem::path fullpath( target_path_c );
        if (boost::filesystem::exists( fullpath )) isFound = true;
    }

    if (isFound){
    }else{
        // Search in current dir
        if (target!=""){
            const boost::filesystem::path fullpath( target.c_str() );
            if (boost::filesystem::exists( fullpath )) return target;
        }
        // Search in /opt/mlfsoft/python-utsusemi/XXX/ana/xml
        std::string utsusemi_usr_path = UtsusemiEnvGetInstDir();
        if (utsusemi_usr_path==""){
            UtsusemiError("FindParamFilePath >> Not found Environment Variable UTSUSEMI_BASE_DIR or UTSUSEMI_INST_CODE");
            return empty_ret;
        }
        if (target!="")
            std::snprintf( target_path_c, sizeof(target_path_c), "%s/%s/%s", utsusemi_usr_path.c_str(), interPath.c_str(), target.c_str() );
        else
            std::snprintf( target_path_c, sizeof(target_path_c), "%s/%s", utsusemi_usr_path.c_str(), interPath.c_str() );

        const boost::filesystem::path fullpath2( target_path_c );
        if ((isParam)&&(boost::filesystem::exists( fullpath2 ))) isFound = true;
        else{
            // Search in ~/ana/xml or ~/ana/tmp
            std::string utsusemi_priv_path = UtsusemiEnvGetUserDir();
            if (utsusemi_priv_path==""){
                UtsusemiError("FindParamFilePath >> Not found Environment Variable UTSUSEMI_USR_DIR");
                return empty_ret;
            }
            if (target!="")
                std::snprintf( target_path_c, sizeof(target_path_c), "%s/%s/%s", utsusemi_priv_path.c_str(), interPath.c_str(), target.c_str() );
            else
                std::snprintf( target_path_c, sizeof(target_path_c), "%s/%s", utsusemi_priv_path.c_str(), interPath.c_str() );

            const boost::filesystem::path fullpath( target_path_c );
            if (boost::filesystem::exists( fullpath )) isFound = true;
            else{
                // Search in /tmp
                if (target!="")
                    std::snprintf( target_path_c, sizeof(target_path_c), "/tmp/%s", target.c_str() );
                else
                    std::snprintf( target_path_c, sizeof(target_path_c), "/tmp" );
                const boost::filesystem::path fullpath( target_path_c );
                if (boost::filesystem::exists( fullpath )) isFound = true;
            }
        }
    }

    if (isFound){
        std::string ret( target_path_c );
        return ret;
    }else
        return empty_ret;

}
//////////////////////////////////////////////////////////
std::string FindRootDataFolder(std::string _dataDir){
    std::string empty_ret="";
    if (_dataDir==""){
        std::string dataPath_s = UtsusemiEnvGetDataDir();
        if (dataPath_s==""){
            UtsusemiError( "FindRootDataFolder : UTSUSEMI_DATA_DIR is empty. ");
            return empty_ret;
        }
        _dataDir = dataPath_s;
    }
    const boost::filesystem::path dpath(_dataDir.c_str());
    if ((boost::filesystem::exists(dpath)) && (boost::filesystem::is_directory(dpath))){
        return _dataDir;
    }else{
        UtsusemiError( "FindRootDataFolder : not found dataPath= "+_dataDir);
        return empty_ret;
    }
    /*
    DIR *dpath;
    if ((dpath=opendir(_dataDir.c_str()))==NULL){
        UtsusemiError( "FindRootDataFolder : not found dataPath= "+_dataDir);
        return empty_ret;
    }
    closedir(dpath);

    return _dataDir;
    */
}
//////////////////////////////////////////////////////////
std::vector<std::string> FindInstDataFolders(std::string _instCode, std::string _rootDir){
    std::vector<std::string> empty_ret;
    _rootDir = FindRootDataFolder(_rootDir);
    if (_rootDir=="") return empty_ret;

    std::vector<std::string> pathToDataInstVect(1,"");

    const boost::filesystem::path dpath(_rootDir.c_str());
    if ((boost::filesystem::exists(dpath)) && (boost::filesystem::is_directory(dpath))){
    }else{
        UtsusemiError( "FindInstDataFolder : not found root dir= "+_rootDir);
        return empty_ret;
    }
    BOOST_FOREACH( const boost::filesystem::path& dp,
                   std::make_pair( boost::filesystem::directory_iterator( dpath ),
                   boost::filesystem::directory_iterator())){
        std::string tmp = dp.filename().string();
        std::string::size_type ind = tmp.find(_instCode);
        if (ind != std::string::npos){
            std::string path_tmp(_rootDir);
            _addPath( &path_tmp, &tmp );
            const boost::filesystem::path dir_tmp(path_tmp.c_str());
            if ((boost::filesystem::exists(dir_tmp)) && (boost::filesystem::is_directory(dir_tmp))){
            }else{
                continue;
            }
            if (tmp.size() == 3){ // dir name = "XXX"
                pathToDataInstVect[0] = path_tmp;
            }else if (tmp.size() == 5){ // dir name = "XXXNN" SIK01
                unsigned char t10 = (unsigned char)(*(tmp.substr(3,1).c_str()));
                unsigned char t01 = (unsigned char)(*(tmp.substr(4,1).c_str()));
                if ( (t10<'0')||(t10>'9')||(t01<'0')||(t01>'9') ){
                    continue;
                }else{
                    UInt4 n = ( (UInt4)(t10-'0') )*10 + (UInt4)(t01-'0') + 1;
                    if (n<pathToDataInstVect.size() ){
                        pathToDataInstVect[n] = path_tmp;
                    }else{
                        pathToDataInstVect.resize( n+1, "" );
                        pathToDataInstVect[n] = path_tmp;
                    }
                }
            }
        }
    }
    return pathToDataInstVect;
}
//////////////////////////////////////////////////////////
std::vector<std::string> FindRunDataFolders( std::string _instCode,  UInt4 _runNo, std::vector<std::string> _instDataFolders ){
    if (_runNo==0){
        std::vector<std::string> empty_ret;
        return empty_ret;
    }
    char runcodec[10];
    std::snprintf( runcodec, sizeof(runcodec), "%3s%06d",_instCode.c_str(), _runNo );
    std::string runCode( runcodec );

    std::vector<std::string> paths = UtsusemiPutRunDataPathFromDict(runCode);
    if (!paths.empty()) return paths;

    // make list of existing data files for each run nubmer
    //DIR* dir;
    //struct dirent *dp;
    std::vector<std::string> ret;
    for (UInt4 i=0; i<_instDataFolders.size(); i++){
        if (_instDataFolders[i]!=""){
            const boost::filesystem::path dir(_instDataFolders[i].c_str());
            if ((boost::filesystem::exists(dir)) && (boost::filesystem::is_directory(dir))){
            }else{
                UtsusemiWarning( "FindRunDataFolders : Cannot open path such as "+_instDataFolders[i]);
            }
            BOOST_FOREACH( const boost::filesystem::path& dp,
                           std::make_pair( boost::filesystem::directory_iterator(dir),
                           boost::filesystem::directory_iterator())){
                std::string aFolder = dp.filename().string();
                std::string::size_type ind = aFolder.find(runCode);
                if ((ind==0)&&(aFolder.size()==18)){ // is XXX123456_YYYYMMDD ?
                    std::string runFolderPath( _instDataFolders[i] );
                    _addPath( &runFolderPath, &aFolder ); // runFolderPath = /data/XXXnn/XXX123456_YYYYMMDD
                    if ((boost::filesystem::exists(runFolderPath)) && (boost::filesystem::is_directory(runFolderPath)))
                        ret.push_back(runFolderPath);
                }
            }
        }
    }

    // Sort folders by date; sorted_dir[0] is latest one.
    std::vector<std::string> sorted_dir;
    for (UInt4 i=0; i<ret.size(); i++){
        std::string last_date = "00000000";
        UInt4 max_j = 0;
        for (UInt4 j=0; j<ret.size(); j++){
            //std::cout << "#[inamura 181105] ret[j]="+ret[j] << std::endl;
            if (ret[j]!="00000000"){
                std::string cur_date=ret[j].substr( ret[j].size()-1-6, 6 );
                if (cur_date>last_date){
                    last_date=cur_date;
                    max_j = j;
                }
            }
        }
        sorted_dir.push_back( ret[max_j] );
        ret[max_j]="00000000";
    }
    UtsusemiAddRunDataPathToDict(runCode,sorted_dir);

    return sorted_dir;
}
//////////////////////////////////////////////////////////
std::vector<std::string> FindRunDataFolders( std::string _instCode,  UInt4 _runNo ){
    return FindRunDataFolders( _instCode, _runNo, FindInstDataFolders(_instCode) );
}
//////////////////////////////////////////////////////////
std::vector<std::string> FindRunDataFolders( UInt4 _runNo ){
    std::string _instCode = UtsusemiEnvGetInstCode();
    if (_instCode==""){
        UtsusemiError("FindRunDataFolder : InstCode is not defined.");
        std::vector<std::string> empty_ret;
        return empty_ret;
    }
    return FindRunDataFolders( _instCode, _runNo, FindInstDataFolders(_instCode) );
}
//////////////////////////////////////////////////////////
UInt4 PutLatestRunNoFromDataFolder( std::string _instCode, UInt4 _runNoUpperLimit ){
    if (_instCode=="") _instCode = UtsusemiEnvGetInstCode();
    if (_instCode==""){
        UtsusemiError("FindLatestRunDataFolder : InstCode is not defined.");
        return 0;
    }
    std::vector<std::string> found_rundata_paths;
    std::vector<std::string> inst_data_path_v=FindInstDataFolders(_instCode, "");
    for (std::vector<std::string>::iterator it=inst_data_path_v.begin(); it!=inst_data_path_v.end(); ++it){
        const boost::filesystem::path dpath( (*it).c_str() );
        if ((boost::filesystem::exists( dpath ))&&(boost::filesystem::is_directory( dpath ))){
            BOOST_FOREACH( const boost::filesystem::path& p,
                           std::make_pair( boost::filesystem::directory_iterator( dpath ),
                                           boost::filesystem::directory_iterator())){
                if (boost::filesystem::is_directory(p)){
                    std::string fname = p.filename().string();
                    if (fname.size() == 18){
                        if (fname.substr(0,3) == _instCode){
                            UInt4 runNo = (UInt4)(atoi( fname.substr(3,6).c_str()) );
                            if (runNo<=_runNoUpperLimit) found_rundata_paths.push_back(fname);
                        }
                    }
                }
            }
        }
    }
    sort( found_rundata_paths.begin(), found_rundata_paths.end() );
    //for (std::vector<std::string>::iterator it=found_rundata_paths.begin(); it!=found_rundata_paths.end(); ++it)
    //    std::cout << (*it) << std::endl;
    return (UInt4)(atoi(found_rundata_paths.back().substr(3,6).c_str())); // return runNo(nnnnnn) from XXXnnnnnn_YYMMDD
}
//////////////////////////////////////////////////////////
std::string FindEnvironFolderInRunData( std::string _instCode,  UInt4 _runNo, std::vector<std::string> _instDataFolders ){
    std::vector<std::string> found_dirs = FindRunDataFolders(_instCode, _runNo, _instDataFolders);
    if (found_dirs.empty()) return "";

    StringTools st;
    std::vector<std::string> keys = st.SplitString(UTSUSEMIENVIRONPATHINRUNFOLDER,"/");
    std::string utsusemi_path="";
    const boost::filesystem::path dpath( found_dirs.front().c_str() ); // search latest data folder
    if ((boost::filesystem::exists( dpath ))&&(boost::filesystem::is_directory( dpath ))){
        BOOST_FOREACH( const boost::filesystem::path& p,
                       std::make_pair( boost::filesystem::directory_iterator( dpath ),
                                       boost::filesystem::directory_iterator())){
            if (boost::filesystem::is_directory(p)){
                //std::cout << " found directory p.string()="<<p.string()<<std::endl;
                if (p.filename()==keys[0]){ // "params"
                    BOOST_FOREACH( const boost::filesystem::path& p2,
                                   std::make_pair( boost::filesystem::directory_iterator( p ),
                                                   boost::filesystem::directory_iterator())){
                        if (boost::filesystem::is_directory(p2)){
                            //std::cout << "found directory p2.string()="<<p2.string()<<std::endl;
                            if (p2.filename()==keys[1]){ // "Utsusemi"
                                utsusemi_path = p2.string();
                            }
                        }
                    }
                }
            }
        }
    }
    return utsusemi_path;
}
//////////////////////////////////////////////////////////
std::string FindEnvironFolderInRunData( std::string _instCode,  UInt4 _runNo ){
    return FindEnvironFolderInRunData( _instCode, _runNo, FindInstDataFolders(_instCode) );
}
//////////////////////////////////////////////////////////
std::string FindEnvironFolderInRunData( UInt4 _runNo ){
    std::string _instCode = UtsusemiEnvGetInstCode();
    if (_instCode==""){
        UtsusemiError("FindEnvironFolderInRunData : InstCode is not defined.");
        return "";
    }
    return FindEnvironFolderInRunData( _instCode, _runNo, FindInstDataFolders(_instCode) );
}
//////////////////////////////////////////////////////////
void _addPath( std::string *orgPath, std::string *addPath ){

    std::string::size_type ind = orgPath->find_last_of("/");
    if (ind==(orgPath->size()-1)){
        *orgPath = *orgPath+*addPath;
    }else{
        *orgPath = *orgPath+"/"+*addPath;
    }

}
