#include "AcquireNeutronSourceImageInformation.hh"
//////////////////////////////////////////////////////
AcquireNeutronSourceImageInformation::
AcquireNeutronSourceImageInformation()
:AcquireNeutronSourceInformationControlBase( HOST_NAME ){
    DebugFlag = false;
    SetSavePath( "./" );

    if ( DebugFlag ){
        std::cout << std::endl;
        std::cout << "ImageInformation()" << std::endl;
        std::cout << "host_name : " << "(HOST_NAME)" << std::endl;
        std::cout << "DebugFlag : " << DebugFlag << std::endl;
    }
}
//////////////////////////////////////////////////////////////////////
AcquireNeutronSourceImageInformation::
AcquireNeutronSourceImageInformation( std::string host_name, Bool debug_flag )
:AcquireNeutronSourceInformationControlBase( host_name ){
    DebugFlag = debug_flag;
    SetSavePath( "./" );

    if ( DebugFlag ){
        std::cout << std::endl;
        std::cout << "ImageInformation(host_name,debug_flag)" << std::endl;
        std::cout << "host_name : " << host_name << std::endl;
        std::cout << "DebugFlag : " << DebugFlag << std::endl;
    }
}
//////////////////////////////////////////////////////////////////////
AcquireNeutronSourceImageInformation::
AcquireNeutronSourceImageInformation( Bool debug_flag )
:AcquireNeutronSourceInformationControlBase( HOST_NAME ){
    DebugFlag = debug_flag;
    SetSavePath( "./" );

    if ( DebugFlag ){
        std::cout << std::endl;
        std::cout << "ImageInformation(debug_flag)" << std::endl;
        std::cout << "host_name : " << "(HOST_NAME)" << std::endl;
        std::cout << "DebugFlag : " << DebugFlag << std::endl;
    }
}
//////////////////////////////////////////////////////////////////////
AcquireNeutronSourceImageInformation::
~AcquireNeutronSourceImageInformation(){
}
//////////////////////////////////////////////////////////////////////
Int4 AcquireNeutronSourceImageInformation::
SetSavePath( const std::string save_path ){
    std::string path;

    if ( !(save_path.empty()) ){
        if ( save_path.substr(save_path.length()-1,1) != "/" ){
            path = save_path;
        }
        else {
            path = save_path.substr(0,save_path.length()-1);
        }

        DIR *dir;
        //struct dirent *dent;
        /* no directry */
        if ( (dir=opendir(path.c_str())) == NULL ){
            /* making directory */
            if ( mkdir(path.c_str(),
                       S_IRUSR | S_IWUSR | S_IXUSR |         /* rwx */
                       S_IRGRP | S_IWGRP | S_IXGRP |         /* rwx */
                       S_IROTH | S_IXOTH | S_IXOTH) == 0) {  /* rwx */
                FileSavePath = path + "/";
            }
            else {
                std::cout << "Making " << path << " directory failed." << std::endl;
                return -1;
            }
        }
        /* Existing directory */
        else {
            FileSavePath = path + "/";
        }
        //FileSavePath = path + "/";
    }
    if ( DebugFlag ){
        std::cout << "FileSavePath : " << FileSavePath << std::endl;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
void AcquireNeutronSourceImageInformation::
GetImageInformation( const std::string Key ){
//    char *format = "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n";
    std::string recv_data( " " );  /* http recve data (with header) */
    std::string body_data( " " );  /* http body data */

    /* check to information key word */
    if ( Key == BEAM_POWER            || /* Beam Power(image) */
         Key == CT_HISTORY            || /* Beam power history(image) */
         Key == MODERATOR_TEMPERATURE || /* Moderator temperature history(image) */
         Key == JPARC_STATUS          || /* Status of J-PARC(image) */
         Key == SHUTTER_STATUS        || /* Shutter opening-and-closing state(image) */
         Key == CT_3HOUR              || /* Current history(image) */
         Key == CT_1DAY               || /* Current history(image) */
         Key.substr(0,5) == "/MLF/"   ){ /* Other image file */

        SetFilePath( PutImagePath( Key ) );
        std::string file_name = FileSavePath + PutImageFilename( Key );

        /* check to access control */
        if ( AcquireControl( Key ) ){

            /* Initialization of the address structure */
            if ( DebugFlag ) std::cout << "Initialization of an address structure..." << std::endl;
            if ( InitializeSockaddrIn() < 0 ) {
                std::cout << "Initialization of the address structure failed!" << std::endl;
            }
            else {
                /* Create a socket */
                if ( DebugFlag ) std::cout << "Create a socket..." << std::endl;
                if ( CreateSocket() < 0 ) {
                    std::cout << "Create of the socket failed!" << std::endl;
                }
                else {
                    /* Establish a connection to the server. */
                    if ( DebugFlag ) std::cout << "Connecting to the server...." << std::endl;
                    if ( ServerConnect() < 0 ) {
                        std::cout << "Connection to the server failed!" << std::endl;
                    }
                    else {
                        /* Send request */
                        //format << "GET " << FilePath << "HTTP/1.1\r\n"
                        //       << "Host: " << HostName << "\r\n"
                        //       << "Connection: close\r\n"
                        //       << "\r\n";
                        std::string request = "GET "   + FilePath + " HTTP/1.0\r\n"
                                       + "Host: " + HostName + "\r\n"
                                       + "Connection: close\r\n"
                                       + "\r\n";
                                       //+ "User-Agent: " + USER_AGENT + "\r\n"
                        if ( DebugFlag ) {
                            std::cout << "Send to request...." << std::endl;
                            std::cout << request << std::endl;
                        }
                        if ( SendRequest( request ) < 0 ) {
                            std::cout << "Request failed!" << std::endl;
                        }
                        else {
                            /* Replies received */
                            if ( DebugFlag ) std::cout << "Replies received...." << std::endl;
                            if ( RecvReply ( recv_data ) < 0 ) {
                                std::cout << "Receive failed!" << std::endl;
                            }
                            else {
                                if ( SplitBodyData (recv_data, body_data) <= 0 ) {
                                //if ( SplitBodyData ("binary",recv_data, body_data) <= 0 ) {
                                    std::cout << "No image data : " << file_name << std::endl;
                                }
                                else {
                                    /* save image file */
                                    std::ofstream fout;
                                    fout.open(file_name.c_str(),std::ios::out|std::ios::binary);
                                    if ( !fout ) {
                                        std::cout << "file open error! : " << file_name << std::endl;
                                    }
                                    else {
                                        fout << body_data << std::endl;
                                        //fout.write(body_data,size);
                                        fout.close();
                                        //if ( DebugFlag ) std::cout << "save image file : " << file_name << std::endl;
                                        std::cout << "save image file : " << file_name << std::endl;
                                    }
                                }
                            }
                        }
                        //format.str("");                      /* stream buffer clear */
                        //format.clear(std::stringstream::goodbit); /* stream status clear */
                    }
                    /* Close connection */
                    SocketClose();
                }
            }

        }
        else {
            //std::cout << "Under access restrictions!" << std::endl;
        }
    }

    /* Key word Error */
    else {
        std::cout << Key << " is an invalid keyword!" << std::endl;
    }

}
//////////////////////////////////////////////////////////////////////
void AcquireNeutronSourceImageInformation::
GetImageInformation( const std::string Key, const std::string Start ){

    time_t    nowDateTime, endDateTime;
    struct tm *tmNow, *tmEnd;

    /* check to information key word */
    if ( Key == CT_HISTORY            ||   /* Beam power history(image) */
         Key == MODERATOR_TEMPERATURE ){   /* Moderator temperature history(image) */

        /* now date and time */
        time(&nowDateTime);                /* get current time */
        tmNow = gmtime(&nowDateTime);      /* UTC */

        /* UTC -> JST */
        tmNow->tm_hour += 9;
        tmNow->tm_min   = 0;
        tmNow->tm_sec   = 0;
        endDateTime = mktime(tmNow);       /* normalization of time */
        tmEnd = localtime(&endDateTime);

        std::string End = StructTimeToStringTime( tmEnd, "/" );
        if ( DebugFlag ) std::cout << "End : " << End << std::endl;

        GetImageInformation( Key, Start, End );
    }

    /* Key word Error */
    else {
        std::cout << Key << " is an invalid keyword!" << std::endl;
    }
}
//////////////////////////////////////////////////////////////////////
void AcquireNeutronSourceImageInformation::
GetImageInformation( const std::string Key, const std::string Start, const std::string End ){
    std::string recv_data( " " );  /* http recve data (with header) */
    std::string body_data( " " );  /* http body data */

    time_t    nowDateTime, startDateTime, endDateTime;
    struct tm *tmNow;
    struct tm tmStart, tmEnd;

    //char *format = "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n";

    /* check to information key word */
    if ( Key == CT_HISTORY            || /* Beam power history(image) */
         Key == MODERATOR_TEMPERATURE ){ /* Moderator temperature history(image) */

        /* now date and time */
        time(&nowDateTime);                /* get current time */
        tmNow = gmtime(&nowDateTime);      /* UTC current time */
        //tmNow = localtime(&nowDateTime);   /* time_t -> tm struct */
        //std::cout << "UTC            : " << std::endl;
        //std::cout << "tmNow->tm_year : " << tmNow->tm_year + 1900 << std::endl;
        //std::cout << "tmNow->tm_mon  : " << tmNow->tm_mon  + 1 << std::endl;
        //std::cout << "tmNow->tm_mday : " << tmNow->tm_mday << std::endl;
        //std::cout << "tmNow->tm_hour : " << tmNow->tm_hour << std::endl;
        tmNow->tm_hour += 9;               /* UTC -> JST */
        tmNow->tm_min   = 0;
        tmNow->tm_sec   = 0;
        nowDateTime = mktime(tmNow);       /* normalization of time */

        /* start date and time */
        if ( StringTimeToStructTime( Start, "/", &tmStart ) == 0 ){  /* std::string -> tm struct */
            //std::cout << "tmStart.tm_year : " << tmStart.tm_year + 1900 << std::endl;
            //std::cout << "tmStart.tm_mon  : " << tmStart.tm_mon  + 1 << std::endl;
            //std::cout << "tmStart.tm_mday : " << tmStart.tm_mday << std::endl;
            //std::cout << "tmStart.tm_hour : " << tmStart.tm_hour << std::endl;
            tmStart.tm_min = 0;
            tmStart.tm_sec = 0;
            startDateTime = mktime(&tmStart);                        /* tm struct -> time_t */
            if ( nowDateTime < startDateTime ){
                std::cout << "The start date and time is the future now." << std::endl;
                return;
            }
            else {
            }
        }
        else {
            std::cout << "Invalid start date and time!" << std::endl;
            return;
        }

        /* end date and time */
        if ( StringTimeToStructTime( End, "/", &tmEnd ) == 0 ){   /* std::string -> tm struct */
            //std::cout << "tmEnd.tm_year : " << tmEnd.tm_year + 1900 << std::endl;
            //std::cout << "tmEnd.tm_mon  : " << tmEnd.tm_mon  + 1 << std::endl;
            //std::cout << "tmEnd.tm_mday : " << tmEnd.tm_mday << std::endl;
            //std::cout << "tmEnd.tm_hour : " << tmEnd.tm_hour << std::endl;
            tmEnd.tm_min = 0;
            tmEnd.tm_sec = 0;
            endDateTime = mktime(&tmEnd);                         /* tm struct -> time_t */
            if ( nowDateTime < endDateTime ){   /* End day and time is corrected in current day and time. */
                endDateTime= mktime(tmNow);                       /* tm struct -> time_t */
            }
            else {
            }
            //std::cout << "endDateTime : " << endDateTime << std::endl;
        }
        else {
            std::cout << "Invalid end date and time!" << std::endl;
            return;
        }

        UInt4     year, month, day, hour;
        while ( startDateTime <= endDateTime ){
            year  = (UInt4)(tmStart.tm_year + 1900);
            month = (UInt4)(tmStart.tm_mon  + 1);
            day   = (UInt4)(tmStart.tm_mday);
            hour  = (UInt4)(tmStart.tm_hour);
            if ( DebugFlag ) {
                std::cout << "year : " << year << std::endl;
                std::cout << "month: " << month << std::endl;
                std::cout << "day  : " << day << std::endl;
                std::cout << "hour : " << hour << std::endl;
            }

            SetFilePath( PutImagePath(Key, year, month, day, hour) );
            std::string file_name = FileSavePath + PutImageFilename(Key, year, month, day, hour);

            /* check to access control */
            if ( AcquireControl( Key ) ){

                /* Initialization of the address structure */
                if ( DebugFlag ) std::cout << "Initialization of an address structure..." << std::endl;
                if ( InitializeSockaddrIn() < 0 ) {
                    std::cout << "Initialization of the address structure failed!" << std::endl;
                }
                else {
                    /* Create a socket */
                    if ( DebugFlag ) std::cout << "Create a socket..." << std::endl;
                    if ( CreateSocket() < 0 ) {
                        std::cout << "Create of the socket failed!" << std::endl;
                    }
                    else {
                        /* Establish a connection to the server. */
                        if ( DebugFlag ) std::cout << "Connecting to the server...." << std::endl;
                        if ( ServerConnect() < 0 ) {
                            std::cout << "Connection to the server failed!" << std::endl;
                        }
                        else {
                            /* Send request */
                            std::string request = "GET "   + FilePath + " HTTP/1.0\r\n"
                                           + "Host: " + HostName + "\r\n"
                                           + "Connection: close\r\n"
                                           + "\r\n";
                                           //+ "User-Agent: " + USER_AGENT + "\r\n"
                            if ( DebugFlag ) {
                                std::cout << "Send to request...." << std::endl;
                                std::cout << request << std::endl;
                            }
                            if ( SendRequest( request ) < 0 ) {
                                std::cout << "Request failed!" << std::endl;
                            }
                            else {
                                /* Replies received */
                                if ( DebugFlag ) std::cout << "Replies received...." << std::endl;
                                if ( RecvReply ( recv_data ) < 0 ) {
                                    std::cout << "Receive failed!" << std::endl;
                                }
                                else {
                                    if ( SplitBodyData (recv_data, body_data) <= 0 ) {
                                    //if ( SplitBodyData ("binary",recv_data, body_data) <= 0 ) {
                                        std::cout << "No image data : " << file_name << std::endl;
                                    }
                                    else {
                                        /* save image file */
                                        std::ofstream fout;
                                        fout.open(file_name.c_str(),std::ios::out|std::ios::binary);
                                        if ( !fout ) {
                                            std::cout << "file open error! : " << file_name << std::endl;
                                        }
                                        else {
                                            fout << body_data << std::endl;
                                            //fout.write(body_data,size);
                                            fout.close();
                                            //if ( DebugFlag ) std::cout << "save image file : " << file_name << std::endl;
                                            std::cout << "save image file : " << file_name << std::endl;
                                        }
                                    }
                                }
                            }
                            //format.str("");                      /* buffer clear */
                            //format.clear(std::stringstream::goodbit); /* stream clear */
                        }
                        /* Close connection */
                        SocketClose();
                    }
                }

            }
            else {
                //std::cout << "Under access restrictions!" << std::endl;
                return;
            }

            /* next date and time */
            tmStart.tm_hour = ++hour;            /* increment 1 hour */
            startDateTime = mktime(&tmStart);    /* normalization of time */
        }  /* while loop end */
    }

    /* Key word Error */
    else {
        std::cout << Key << " is an invalid keyword!" << std::endl;
    }

    return;
}
//////////////////////////////////////////////////////////////////////
std::string AcquireNeutronSourceImageInformation::
PutImagePath( const std::string Key ){
    std::string PathName;

    PathName = IMAGE_PATH;
    if ( Key == BEAM_POWER ){                  /* Beam Power(image) */
        PathName += BEAM_POWER_FNAME;
    }
    else if ( Key == CT_HISTORY ){             /* Beam power history(image) */
        PathName += CT_01_FNAME;
    }
    else if ( Key == MODERATOR_TEMPERATURE ){  /* Moderator temperature history(image) */
        PathName += MODERATOR_FNAME;
    }
    else if ( Key == JPARC_STATUS ){           /* Status of J-PARC(image) */
        PathName += JPARC_STATUS_FNAME;
    }
    else if ( Key == SHUTTER_STATUS ){         /* Shutter opening-and-closing state(image) */
        PathName += SHUTTER_STATUS_FNAME;
    }
    else if ( Key == CT_3HOUR ){               /* Current history 3 hour(image) */
        PathName += CT_3HOUR_FNAME;
    }
    else if ( Key == CT_1DAY ){                /* Current history 1 day(image) */
        PathName += CT_1DAY_FNAME;
    }
    else if ( Key.substr(0,5) == "/MLF/" ){    /* Other image file  */
        PathName = Key;
    }
    else {                                     /* Error Key word */
        PathName.erase();
    }

    return PathName;
}
//////////////////////////////////////////////////////////////////////
std::string AcquireNeutronSourceImageInformation::
PutImagePath( const std::string Key, const UInt4 year, const UInt4 month, const UInt4 day, const UInt4 hour ){
/* PutImagePath( std::string Key, std::string Date ){ */
    std::string PathName;

    std::ostringstream os;
    os << year << "/" << month << "/" << day << "/"
       << year << "-" << std::setw(2) << std::setfill('0') << month << "-" << std::setw(2) << day
               << "T" << std::setw(2) << hour << "_59" ;

    if ( Key == CT_HISTORY ){                    /* Beam power history(image) */
        PathName = CT_PATH + os.str() + CT_FNAME;
    }
    else if ( Key == MODERATOR_TEMPERATURE ){    /* Moderator temperature history(image) */
        PathName = MODERATOR_TMP_PATH + os.str() + MODERATOR_TMP_FNAME;
    }
    else {                                       /* Error Key word */
        PathName.erase();
    }
    os.str("");                      /* buffer clear */
    os.clear(std::stringstream::goodbit); /* stream clear */

    return PathName;
}
//////////////////////////////////////////////////////////////////////
std::string AcquireNeutronSourceImageInformation::
PutImageFilename( const std::string Key ){
    std::string Filename;

    if ( Key == BEAM_POWER ){                 /* Beam Power(image) */
        Filename = BEAM_POWER_FNAME;
    }
    else if ( Key == CT_HISTORY ){            /* Beam power history(image) */
        Filename = CT_01_FNAME;
    }
    else if ( Key == MODERATOR_TEMPERATURE ){ /* Moderator temperature history(image) */
        Filename = MODERATOR_FNAME;
    }
    else if ( Key == JPARC_STATUS ){          /* Status of J-PARC(image) */
        Filename = JPARC_STATUS_FNAME;
    }
    else if ( Key == SHUTTER_STATUS ){        /* Shutter opening-and-closing state(image) */
        Filename = SHUTTER_STATUS_FNAME;
    }
    else if ( Key == CT_3HOUR ){              /* Current history 3 hour(image) */
        Filename = CT_3HOUR_FNAME;
    }
    else if ( Key == CT_1DAY ){               /* Current history 1 day(image) */
        Filename = CT_1DAY_FNAME;
    }
    else if ( Key.substr(0,5) == "/MLF/" ){   /* Other image file  */
        Filename = Key.substr(5);
    }
    else {                                    /* Error Key word */
        Filename.erase();
    }

    return Filename;
}
//////////////////////////////////////////////////////////////////////
std::string AcquireNeutronSourceImageInformation::
PutImageFilename( const std::string Key, const UInt4 year, const UInt4 month, const UInt4 day, const UInt4 hour ){
    std::string Filename;

    std::ostringstream os;
    os << year << "-" << std::setw(2) << std::setfill('0') << month << "-" << std::setw(2) << day
               << "T" << std::setw(2) << hour << "_59" ;

    if ( Key == CT_HISTORY ){                 /* Beam power history(image) */
        Filename = os.str() + CT_FNAME;
    }
    else if ( Key == MODERATOR_TEMPERATURE ){ /* Moderator temperature history(image) */
        Filename = os.str() + MODERATOR_TMP_FNAME;
    }
    else {                                    /* Error Key word */
        Filename.erase();
    }
    os.str("");                      /* buffer clear */
    os.clear(std::stringstream::goodbit); /* stream clear */

    return Filename;
}
