#include "HttpFileDownload.h"
#include "SyFile.h"

#ifdef WIN32

    //////////////////////////////////////////////////////////////////////////
    // Windows version
    //////////////////////////////////////////////////////////////////////////

HttpFileDownload::HttpFileDownload()
{
}

HttpFileDownload::~HttpFileDownload()
{
}

int HttpFileDownload::DownloadStart(const char *url, const char *destFile)
{
    return(-1);
}

int HttpFileDownload::DownloadStatus(uint64 *pTotalReceived, uint64 *pTotalSize)
{
    return(-1);
}


#else

    //////////////////////////////////////////////////////////////////////////
    // PS3 version
    //////////////////////////////////////////////////////////////////////////

    // NOTE: this is largely copied from the sample-code provided by the SDK - JEFFP

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "netex/net.h"
#include "netex/errno.h"

#include "cell/http.h"

class HttpFileDownloadInternal
{
    public:
        CellHttpClientId m_clientId;
        CellHttpTransId m_transId;
        SyFile m_outFile;
        uint64_t m_length;
        uint64_t m_totalRecv;
        char *m_buffer;
};

#define LOCAL_HTTP_BUFFER_SIZE 8192
static void * httpBuffer = NULL;

HttpFileDownload::HttpFileDownload()
{
    m_data = new HttpFileDownloadInternal;
    m_data->m_clientId = 0;
    m_data->m_transId = 0;
    m_data->m_length = 0;
    m_data->m_totalRecv = 0;
    m_data->m_buffer = new char[256 * 1024];

    int32_t ret = sys_net_initialize_network();
    if (ret != 0) 
    {
        printf("initialize_network() failed\n");
    }
    if (httpBuffer == NULL)
    {
      httpBuffer = malloc(LOCAL_HTTP_BUFFER_SIZE); //alloc's once and never lets go - might want to do this differently.
    }
    ret = cellHttpInit(httpBuffer, LOCAL_HTTP_BUFFER_SIZE);
    if (0 > ret) 
    {
        printf("unable to start libhttp... (0x%x)\n", ret);
    }

    ret = cellHttpCreateClient(&m_data->m_clientId);
    if (0 > ret) 
    {
        printf("unable to create http client... (0x%x)\n", ret);
    }
}

HttpFileDownload::~HttpFileDownload()
{
    m_data->m_outFile.Close();      // may or may not be open at this point, but just in case

    if (m_data->m_transId)
    {
        cellHttpDestroyTransaction(m_data->m_transId);
        m_data->m_transId = 0;
    }

    if (m_data->m_clientId) 
    {
        cellHttpDestroyClient(m_data->m_clientId);
        m_data->m_clientId = 0;
    }

    cellHttpEnd();
    sys_net_finalize_network();

    delete[] m_data->m_buffer;
    delete m_data;
}

int HttpFileDownload::DownloadStart(const char *url, const char *destFile)
{
    int ret = 0;

    char uriPool[8192];
    CellHttpUri uri;
    ret = cellHttpUtilParseUri(&uri, url, uriPool, sizeof(uriPool), NULL);
    if (0 > ret) 
    {
        printf("error parsing URI... (0x%x)\n\n", ret);
        return(-1);
    }

    ret = cellHttpCreateTransaction(&m_data->m_transId, m_data->m_clientId, CELL_HTTP_METHOD_GET, &uri);
    if (0 > ret) 
    {
        printf("failed to create http transaction... (0x%x)\n\n", ret);
        return(-1);
    }

    ret = cellHttpSendRequest(m_data->m_transId, NULL, (size_t)0, NULL);
    if (0 > ret) 
    {
        printf("failed to complete http transaction... (0x%x)\n\n", ret);
    }

    int code = 0;
    ret = cellHttpResponseGetStatusCode(m_data->m_transId, &code);
    if (0 > ret) 
    {
        printf("failed to receive http response... (0x%x)\n\n", ret);
        return(-1);
    }

    ret = cellHttpResponseGetContentLength(m_data->m_transId, &m_data->m_length);
    if (0 > ret) 
    {
        if (ret == CELL_HTTP_ERROR_NO_CONTENT_LENGTH) 
        {
            m_data->m_length = 0;
        } 
        else 
        {
            printf("error in receiving content length... (0x%x)\n\n", ret);
            return(-1);
        }
    }

    m_data->m_outFile.Open(destFile, SYFILE_CREATE | SYFILE_BINARY | SYFILE_WONLY);
    return(0);
}

int HttpFileDownload::DownloadStatus(uint64 *pTotalReceived, uint64 *pTotalSize)
{
    *pTotalReceived = m_data->m_totalRecv;
    *pTotalSize = m_data->m_length;

    if ((m_data->m_length > 0) && (m_data->m_totalRecv >= m_data->m_length))
    {
        return(1);
    }

    size_t recv = 0;
    int ret = cellHttpRecvResponse(m_data->m_transId, m_data->m_buffer, 256 * 1024, &recv);
    if (0 > ret) 
    {
        printf("error receiving body... (0x%x)\n\n", ret);
        return(-1);
    } 
    else if (recv == 0) 
    {
        m_data->m_length = m_data->m_totalRecv;
        return(1);
    }

    m_data->m_outFile.Write(m_data->m_buffer, recv);
    m_data->m_totalRecv += recv;

    *pTotalReceived = m_data->m_totalRecv;
    *pTotalSize = m_data->m_length;

    if ((m_data->m_length > 0) && (m_data->m_totalRecv >= m_data->m_length))
    {
        m_data->m_outFile.Close();
        return(1);
    }
    return(0);
}




#endif



