#include "sthreadworklistsearch.h"

#include "mainwindow.h"

#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>

SThreadWorklistSearch::SThreadWorklistSearch():QSThread()
{
    m_pRD = new WorklistResponseData;
    m_pRD->m_Patient.Init();
}

SThreadWorklistSearch::~SThreadWorklistSearch()
{
    ExitThread();
    SAFE_DELETE(m_pRD);
}

void SThreadWorklistSearch::Init()
{
    m_nCurrentState = 0;

    CommonData* pCommonData = MainWindow::GetCommonData();
    WorklistResponseData rd = pCommonData->GetCurrentWorklistData();
    pCommonData->ReleaseCurrentWorklistData();
    SetWorklistInfo(rd);
}

void SThreadWorklistSearch::InnerRun()
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    if(pCommonData==NULL)
    {
        usleep(1000);
        return;
    }


    if(m_nCurrentState&0x04)
    {
        bool bCheckAlive = false;

        CommonData* pCommon = MainWindow::GetCommonData();
        SDCM_SERVER_INFO* pInfo = NULL;
        QString strIP;
        int port;

        pInfo = pCommon->GetServerWorklistInfo();
        {
            strIP = pInfo->m_strServer_IP;
            port = pInfo->m_nServer_Port;
        }
        pCommon->ReleaseServerWorklistInfo();

        usleep(10*1000);

        int i=0;
        int nRet = 0;

        /*
        for(i=0 ; i<10 && bCheckAlive==false ; i++)
        {
            nRet = CheckAliveWorklist(0);
            if(nRet<0)
            {
                bCheckAlive = false;
            }
            else
            {
                bCheckAlive = true;
                break;
            }
            usleep(300*1000);
        }

        //bCheckAlive = true;
        if(bCheckAlive==false)
        {
            MainWindow* pMainWindow = MainWindow::GetMainWindow();
            if(pMainWindow!=NULL)
            {
                QString strError;
                if(nRet==-1)
                {
                    strError = QString("Error(-1): gethostbyname(%1)").arg(strIP);
                }
                else if(nRet==-2)
                {
                    strError = QString("Error(-2): socket(%1)").arg(strIP);
                }
                else if(nRet==-3)
                {
                    strError = QString("Error(-3): rval");
                }
                else if(nRet==-4)
                {
                    strError = QString("Error(-4): getsockopt");
                }
                else if(nRet==-5)
                {
                    strError = QString("Error(-5): valopt");
                }
                else if(nRet==-6)
                {
                    strError = QString("Error(-6): IP(%1)").arg(strIP);
                }
                else if(nRet==-7)
                {
                    strError = QString("Error(-7): IP(%1)").arg(strIP);
                }
                else if(nRet==-8)
                {
                    strError = QString("Error(-8): F_GETFL(%1)").arg(strIP);
                }

                SetDisplayError(strError);
            }

            //SetWorklistProgress(nRet);
            worklistUpdateComplete();
        }
        else
            */
        {
            SetWorklistProgress(nRet);

            usleep(100*1000);
            SDCMWorklist* pWorklist = pCommonData->GetWorklistClass();
            int nRet = pWorklist->Search();
            if(nRet>=0)
            {
                worklistUpdateComplete();
            }
            else
            {
                worklistError();
            }
        }

        m_nCurrentState = (m_nCurrentState & ~0x04);
    }

    if(m_bStop==true)
    {
        int a=0;
    }
    else
    {
        usleep(100*1000);
    }
}

void SThreadWorklistSearch::SetWorklistInfo(WorklistResponseData& rd)
{
    m_pRD->m_Patient = rd.m_Patient;
    m_pRD->m_Study = rd.m_Study;
    m_pRD->m_Series = rd.m_Series;
    m_pRD->m_Image = rd.m_Image;
    m_pRD->m_ScheduledData = rd.m_ScheduledData;
}



int SThreadWorklistSearch::CheckAliveWorklist(int nType)
{
    int isAlive = 0;

    struct hostent *h;
    struct sockaddr_in servaddr;

    int sd, rval;
    int port = 105;
    //port = 104;

    CommonData* pCommon = MainWindow::GetCommonData();
    SDCM_SERVER_INFO* pInfo = NULL;

    if(nType==0)
    {
        pInfo = pCommon->GetServerWorklistInfo();
    }
    else if(nType==1)
    {
        pInfo = pCommon->GetServerStorageInfo();
    }
    std::string strIP = pInfo->m_strServer_IP.toStdString().c_str();
    port = pInfo->m_nServer_Port;

    if(nType==0)
    {
        pCommon->ReleaseServerWorklistInfo();
    }
    else if(nType==1)
    {
        pCommon->ReleaseServerStorageInfo();
    }


    h=gethostbyname(strIP.c_str());
    if (h == NULL) {
        return -1;
    }
    // std::cout << inet_ntoa(*((struct in_addr *)h->h_addr)) << std::endl;

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd == -1) {
        return -2;
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);


    memcpy(&servaddr.sin_addr, h -> h_addr, h -> h_length);

    int nStatus = fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK);

    nStatus |= O_NONBLOCK;

    nStatus = fcntl(sd, F_SETFL, nStatus);

    //rval = ::bind(sd, (const sockaddr*)&servaddr, sizeof(servaddr));
    rval = ::connect(sd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    fd_set myset;
    struct timeval tv;
    int valopt;
    socklen_t lon;

    if (rval < 0) {
         if (errno == EINPROGRESS) {
            fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
            do {
               tv.tv_sec = 1;
               tv.tv_usec = 0;
               FD_ZERO(&myset);
               FD_SET(sd, &myset);
               rval = select(sd+1, NULL, &myset, NULL, &tv);
               if (rval < 0 && errno != EINTR) {
                  isAlive = -3;
               }
               else if (rval > 0) {
                  // Socket selected for write
                  lon = sizeof(int);
                  int nRet = getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
                  if ( nRet < 0) {
                     isAlive = -4;
                  }
                  // Check the value returned...

                  if (valopt) {
                     isAlive = -5;
                  }
                  break;
               }
               else {
                   isAlive = -6;
                   break;

               }
            } while (isAlive==0);
         }
         else {
            isAlive = -7;
         }
    }

    if(isAlive>=0)
    {
        // Set to blocking mode again...
        nStatus = fcntl(sd, F_GETFL, NULL);
        if( nStatus < 0)
        {
            isAlive = -7;
        }
        else
        {
            nStatus &= (~O_NONBLOCK);

            if( fcntl(sd, F_SETFL, nStatus) < 0)
            {
                isAlive = -8;
            }
            if (rval > 0 && isAlive>=0)
            {
                isAlive = 1;
            }
        }
    }

    if(sd>=0)
    {
        ::close(sd);
    }

    return isAlive;
}


void SThreadWorklistSearch::SearchWorklist()
{
    m_nCurrentState = (m_nCurrentState | 0x04);
    //m_nCurrentState = 3;
}
