/* ------------------------------------------------------------------
 * Copyright (C) 2008 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
#include "pvmf_protocol_engine_node.h"
#include "pvmf_protocol_engine_node_download_common.h"
#include "pvmf_protocolengine_node_tunables.h"

#include "pvlogger.h"
/**
//Macros for calling PVLogger
*/
#define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
#define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFO(m) LOGINFOMED(m)
#define LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m);
#define LOGERRORDATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m);
#define LOGINFOCLOCK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iClockLogger,PVLOGMSG_INFO,m);
#define PVMF_PROTOCOL_ENGINE_LOGBIN(iPortLogger, m) PVLOGGER_LOGBIN(PVLOGMSG_INST_LLDBG, iPortLogger, PVLOGMSG_ERR, m);
#define	NODEDATAPATHLOGGER_TAG "datapath.sourcenode.protocolenginenode"

#ifdef ANDROID
#define LOG_NDEBUG 0
#include <utils/Log.h>
#undef LOG_TAG
#define LOG_TAG "ProtocolEngine"
#endif

////////////////////////////////////////////////////////////////////////////////////
//////	DownloadContainer implementation
////////////////////////////////////////////////////////////////////////////////////

// constructor
DownloadContainer::DownloadContainer(PVMFProtocolEngineNode *aNode) : ProtocolContainer(aNode)
{
    ;
}

void DownloadContainer::deleteProtocolObjects()
{
    if (iNode->iCfgFileContainer)
    {
        iNode->iCfgFileContainer->saveConfig();
        OSCL_DELETE(iNode->iCfgFileContainer);
        iNode->iCfgFileContainer = NULL;
    }

    if (iNode->iDownloadSource) OSCL_DELETE(iNode->iDownloadSource);
    iNode->iDownloadSource = NULL;
    ProtocolContainer::deleteProtocolObjects();
}

int32 DownloadContainer::doPreStart()
{
    // check the case: resume download after download is complete
    OsclSharedPtr<PVDlCfgFile> aCfgFile = iNode->iCfgFileContainer->getCfgFile();
    LOGINFODATAPATH((0, "DownloadContainer::doPreStart(), currFileSizeFromCfgFile=%d, totalFileSizeFromCfgFile=%d, aResumeDownload=%d, rangeStartTime=%d",
                     aCfgFile->GetCurrentFileSize(), aCfgFile->GetOverallFileSize(), (uint32)(!aCfgFile->IsNewSession()), aCfgFile->GetRangeStartTime()));

    if (!aCfgFile->IsNewSession() && aCfgFile->GetCurrentFileSize() >= aCfgFile->GetOverallFileSize())
    {
        iNode->iInterfacingObjectContainer.setFileSize(aCfgFile->GetOverallFileSize());
        iNode->SetState(EPVMFNodeStarted);
        iNode->iEventReport->startRealDataflow();
        iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE);
        iNode->iDownloadControl->checkResumeNotification();
        return PROCESS_SUCCESS_END_OF_MESSAGE;
    }
    return PROCESS_SUCCESS;
}

bool DownloadContainer::doPause()
{
    if (iNode->iCfgFileContainer) iNode->iCfgFileContainer->saveConfig();
    return true;
}

void DownloadContainer::doClear(const bool aNeedDelete)
{
    // save config
    if (iNode->iCfgFileContainer) iNode->iCfgFileContainer->saveConfig();
    ProtocolContainer::doClear(aNeedDelete);
}

void DownloadContainer::doCancelClear()
{
    // save config
    if (iNode->iCfgFileContainer) iNode->iCfgFileContainer->saveConfig();
    ProtocolContainer::doCancelClear();
}

bool DownloadContainer::addSourceData(OsclAny* aSourceData)
{
    if (!aSourceData) return false;
    if (!iNode->iDownloadSource->addSource(aSourceData)) return false;
    iNode->iCfgFileContainer->setDataSource(iNode->iDownloadSource);
    return true;
}

bool DownloadContainer::createCfgFile(OSCL_String& aUri)
{
    // create and set iCfgFile
    if (!iNode->iCfgFileContainer) return false;
    return (iNode->iCfgFileContainer->createCfgFile(aUri) == PVMFSuccess);
}

bool DownloadContainer::getProxy(OSCL_String& aProxyName, uint32 &aProxyPort)
{
    // download proxy
    // try proxy name/port from the context data at first, and then config file
    // normally proxy name/port in the context data is stored in iCfgFileContainer,
    // for resume download, the proxy name/port in iCfgFileContainer will be updated
    // by the information from the actual config file (i.e., LoadConfig())
    if (iNode->iDownloadSource->iProxyName.get_size() > 0 && iNode->iDownloadSource->iProxyPort > 0)
    {
        aProxyName = iNode->iDownloadSource->iProxyName;
        aProxyPort = iNode->iDownloadSource->iProxyPort;
    }
    else
    {
        OsclSharedPtr<PVDlCfgFile> aCfgFile = iNode->iCfgFileContainer->getCfgFile();
        if (aCfgFile->GetProxyName().get_size() == 0 || aCfgFile->GetProxyPort() == 0) return false;
        aProxyName = aCfgFile->GetProxyName();
        aProxyPort = aCfgFile->GetProxyPort();
    }
    return true;
}

void DownloadContainer::setHttpVersion(const uint32 aHttpVersion)
{
    if (!iNode->iCfgFileContainer->isEmpty())
    {
        iNode->iCfgFileContainer->getCfgFile()->setHttpVersion(aHttpVersion);
    }
}

void DownloadContainer::setHttpExtensionHeaderField(OSCL_String &aFieldKey,
        OSCL_String &aFieldValue,
        const HttpMethod aMethod,
        const bool aPurgeOnRedirect)
{
    iNode->iCfgFileContainer->getCfgFile()->SetExtensionHeaderKey(aFieldKey);
    iNode->iCfgFileContainer->getCfgFile()->SetExtensionHeaderValue(aFieldValue);
    iNode->iCfgFileContainer->getCfgFile()->SetHTTPMethodMaskForExtensionHeader(getBitMaskForHTTPMethod(aMethod));
    iNode->iCfgFileContainer->getCfgFile()->SetExtensionHeaderPurgeOnRediect(aPurgeOnRedirect);
}

bool DownloadContainer::handleContentRangeUnmatch()
{
    // re-issue GET request with range from zero -- meaning starting download from beginning
    OsclSharedPtr<PVDlCfgFile> aCfgFile = iNode->iCfgFileContainer->getCfgFile();
    aCfgFile->SetCurrentFileSize(0);
    aCfgFile->SetOverallFileSize(aCfgFile->GetMaxAllowedFileSize());
    aCfgFile->SetNewSession();
    iNode->iProtocol->stop();

    DownloadOutputConfig config;
    config.isNeedOpenDataStream = true;
    config.isRangeSupport		= false;
    config.isResumeDownload		= true;
    if (iNode->iNodeOutput->initialize((OsclAny*)(&config)) != PVMFSuccess) return false;
    iNode->iNodeOutput->discardData(true); // true means closing and reopening the data stream object
    iNode->StartDataFlowByCommand();
    iNode->iEventReport->startRealDataflow();
    return true;
}

bool DownloadContainer::downloadUpdateForHttpHeaderAvailable()
{
    if (!iNode->iCfgFileContainer->getCfgFile()->IsNewSession())
    {
        // for resume download session, open data stream with append mode
        DownloadOutputConfig config;
        config.isNeedOpenDataStream = true;
        config.isRangeSupport		= true;
        config.isResumeDownload		= true;
        iNode->iNodeOutput->setCurrentOutputSize(iNode->iProtocol->getDownloadSize());
        iNode->iDownloadControl->setPrevDownloadSize(iNode->iProtocol->getDownloadSize());
        if (iNode->iNodeOutput->initialize((OsclAny*)(&config)) != PVMFSuccess) return false;
    }
    return true;
}

bool DownloadContainer::isStreamingPlayback()
{
    return (iNode->iDownloadSource->iPlaybackControl ==
            (uint32)PVMFSourceContextDataDownloadHTTP::ENoSaveToFile);
}

int32 DownloadContainer::initNodeOutput()
{
    // pass objects to node output object
    iNode->iNodeOutput->setOutputObject((OsclAny*)iNode->iPortInForData);
    iNode->iNodeOutput->setOutputObject((OsclAny*)iInterfacingObjectContainer->getDataStreamFactory(), NodeOutputType_DataStreamFactory);
    iNode->iInterfacingObjectContainer.setOutputPortConnect();  // for sending disconnect after download complete

    OsclSharedPtr<PVDlCfgFile> aCfgFile = iNode->iCfgFileContainer->getCfgFile();
    DownloadOutputConfig config;
    config.isResumeDownload     = !aCfgFile->IsNewSession();
    // for resume download, initially no need to open data stream, because we don't know open mode determined by one of several factors: range support (not available)
    // at this point, will call initialize again once we know if range is supported or not
    config.isNeedOpenDataStream = !config.isResumeDownload;
    if (config.isResumeDownload && (aCfgFile->GetCurrentFileSize() >= aCfgFile->GetOverallFileSize()))
    {
        config.isNeedOpenDataStream = true;
    }

    return iNode->iNodeOutput->initialize((OsclAny*)(&config));
}

bool DownloadContainer::initProtocol_SetConfigInfo()
{
    OsclSharedPtr<PVDlCfgFile> aCfgFile = iNode->iCfgFileContainer->getCfgFile();
    if (iNode->iUserAgentField)
    {
        OSCL_FastString aUserAgent;
        if (!iNode->iUserAgentField->getUserAgent(aUserAgent)) return false;
        aCfgFile->SetUserAgent(aUserAgent);
    }
    iNode->iProtocol->setConfigInfo((OsclAny*)(&aCfgFile));
    return true;
}

void DownloadContainer::initDownloadControl()
{
    iNode->iDownloadControl->setSupportObject((OsclAny*)iNode->iProtocol, DownloadControlSupportObjectType_ProtocolEngine);
    iNode->iDownloadControl->setSupportObject((OsclAny*)iNode->iDownloadProgess, DownloadControlSupportObjectType_DownloadProgress);
    iNode->iDownloadControl->setSupportObject((OsclAny*)iNode->iNodeOutput, DownloadControlSupportObjectType_OutputObject);

    iNode->iDownloadProgess->setSupportObject((OsclAny*)iNode->iProtocol, DownloadControlSupportObjectType_ProtocolEngine);
    iNode->iDownloadProgess->setSupportObject((OsclAny*)iNode->iCfgFileContainer, DownloadControlSupportObjectType_ConfigFileContainer);
    iNode->iDownloadProgess->setSupportObject((OsclAny*)iNode->iNodeOutput, DownloadControlSupportObjectType_OutputObject);
}

bool DownloadContainer::doInfoUpdate(uint32 downloadStatus)
{
    if (downloadStatus == PROCESS_SUCCESS_GOT_EOS ||
            downloadStatus == PROCESS_WAIT_FOR_INCOMING_DATA) return true;

    if (iNode->iInterfaceState == EPVMFNodeStarted)
    {
        updateDownloadControl(isDownloadComplete(downloadStatus));
    }

    // centralize sending info events for download
    return iNode->iEventReport->checkReportEvent(downloadStatus);
}

void DownloadContainer::updateDownloadControl(const bool isDownloadComplete)
{
    // check resume notification
    if (iNode->iDownloadControl->checkResumeNotification(isDownloadComplete) == 1)
    {
        // report data ready event
        iNode->iEventReport->sendDataReadyEvent();
    }

    // update download progress
    iNode->iDownloadProgess->update(isDownloadComplete);
}

bool DownloadContainer::handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler)
{
    iNode->iNodeTimer->clear();
    return ProtocolContainer::handleProtocolStateComplete(aEvent, aEventHandler);
}

////////////////////////////////////////////////////////////////////////////////////
//////	pvHttpDownloadOutput implementation
////////////////////////////////////////////////////////////////////////////////////

// constructor
pvHttpDownloadOutput::pvHttpDownloadOutput(PVMFProtocolEngineNodeOutputObserver *aObserver) :
        PVMFProtocolEngineNodeOutput(aObserver),
        iDataStreamFactory(NULL),
        iDataStream(NULL),
        iSessionID(0),
        isOpenDataStream(false),
        iCounter(0)
{
    ;
}

// destructor
pvHttpDownloadOutput::~pvHttpDownloadOutput()
{
    reset();
}

void pvHttpDownloadOutput::reset()
{
    PVMFProtocolEngineNodeOutput::reset();

    // delete data stream object
    if (iDataStreamFactory && iDataStream)
    {
        iDataStream->CloseSession(iSessionID);
        PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
        iDataStreamFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iDataStream);
        iDataStream = NULL;
        iDataStreamFactory = NULL;
    }
}

void pvHttpDownloadOutput::setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType)
{
    if (aObjectType == NodeOutputType_DataStreamFactory && aOutputObject) iDataStreamFactory = (PVMFDataStreamFactory *)aOutputObject;
    PVMFProtocolEngineNodeOutput::setOutputObject(aOutputObject, aObjectType);
}

uint32 pvHttpDownloadOutput::writeToDataStream(OUTPUT_DATA_QUEUE &aOutputQueue)
{
    uint32 totalFragSize = 0, i;
    for (i = 0; i < aOutputQueue.size();i++)
    {
        uint32 fragSize = aOutputQueue[i].getMemFragSize();
        if (!writeToDataStream((uint8*)(aOutputQueue[i].getMemFragPtr()), fragSize)) return ~0;
        totalFragSize += fragSize;
    }

    LOGINFODATAPATH((0, "pvHttpDownloadOutput::writeToDataStream() SIZE= %d , SEQNUM=%d", totalFragSize, iCounter++));
    iCurrTotalOutputSize += totalFragSize;
    return totalFragSize;
}

bool pvHttpDownloadOutput::writeToDataStream(uint8 *aBuffer, uint32 aBufferLen)
{
    if (iDataStream->Write(iSessionID, aBuffer, sizeof(uint8), aBufferLen) != PVDS_SUCCESS) return false;
    return true;
}

int32 pvHttpDownloadOutput::flushData(const uint32 aOutputType)
{
    int32 status = PVMFProtocolEngineNodeOutput::flushData(aOutputType);
    if (status != PROCESS_SUCCESS) return status;

    while (!iOutputFramesQueue.empty())
    {
        if (writeToDataStream(iOutputFramesQueue[0]) == 0xffffffff) return PROCESS_OUTPUT_TO_DATA_STREAM_FAILURE;
        iOutputFramesQueue.erase(iOutputFramesQueue.begin());
    }
    return PROCESS_SUCCESS;
}

int32 pvHttpDownloadOutput::initialize(OsclAny* aInitInfo)
{
    // open data stream object
    if (!iDataStreamFactory || !iPortIn) return PVMFFailure;
    if (!iDataStream)
    {
        PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
        iDataStream = (PVMIDataStreamSyncInterface*)iDataStreamFactory->CreatePVMFCPMPluginAccessInterface(uuid);
        if (!iDataStream) return PVMFFailure;

        // create memory pool
        int32 status = createMemPool();
        if (status != PVMFSuccess) return status;
    }

    // open data stream object if needed
    return openDataStream(aInitInfo);
}

int32 pvHttpDownloadOutput::openDataStream(OsclAny* aInitInfo)
{
    DownloadOutputConfig* config = (DownloadOutputConfig*)aInitInfo;
    if (config->isNeedOpenDataStream && !isOpenDataStream)
    {
        PvmiDataStreamMode aMode = PVDS_WRITE_ONLY;
        if (config->isResumeDownload && config->isRangeSupport) aMode = PVDS_APPEND;

        if (iDataStream->OpenSession(iSessionID, aMode) != PVDS_SUCCESS) return PROCESS_DATA_STREAM_OPEN_FAILURE;
        isOpenDataStream = true;
    }
    return PVMFSuccess;
}

void pvHttpDownloadOutput::discardData(const bool aNeedReopen)
{
    discardDataBody(aNeedReopen);
}

void pvHttpDownloadOutput::discardDataBody(const bool aNeedReopen, const uint32 aSeekOffset)
{
    // discard the existing data inside the data stream object
    if (iDataStream && isOpenDataStream)
    {
        if (aNeedReopen)
        {
            iDataStream->CloseSession(iSessionID);
            iDataStream->OpenSession(iSessionID, PVDS_REWRITE);
        }
        else
        {
            // for progressive playback, the file offset may not be 0 after reconnect
            iDataStream->Seek(iSessionID, aSeekOffset, PVDS_SEEK_SET);
        }
    }
    PVMFProtocolEngineNodeOutput::discardData();
}

uint32 pvHttpDownloadOutput::getAvailableOutputSize()
{
    uint32 writeCapacity = 0xFFFFFFFF;
    if (iDataStream)
    {
        iDataStream->QueryWriteCapacity(iSessionID, writeCapacity);
    }
    return writeCapacity;
}

////////////////////////////////////////////////////////////////////////////////////
//////	pvDownloadControl implementation
////////////////////////////////////////////////////////////////////////////////////

pvDownloadControl::pvDownloadControl() :
        iCurrentPlaybackClock(NULL),
        iProgDownloadSI(NULL),
        iNodeOutput(NULL)
{
    clear();
    createDownloadClock(); // may leave
    iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
}

void pvDownloadControl::clear()
{
    // check whether there is still pending resume request
    if (iProgDownloadSI) sendResumeNotification(true);
    iProgDownloadSI = NULL;

    iPlaybackUnderflow			= true;
    iDownloadComplete			= false;
    iRequestResumeNotification	= false;
    iCurrentNPTReadPosition		= 0;
    iClipDurationMsec			= 0;
    iPlaybackByteRate			= 0;
    iClipByterate				= 0;
    iPrevDownloadSize			= 0;
    iDlAlgoPreConditionMet		= false;
    iSetFileSize				= false;
    iSendDownloadCompleteNotification = false;
}

// requst resume notification, implementation of PVMFDownloadProgressInterface API
void pvDownloadControl::requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete, bool& aNeedSendUnderflowEvent)
{
    LOGINFODATAPATH((0, "pvDownloadControl::requestResumeNotification(), iPlaybackUnderflow=%d, iRequestResumeNotification=%d, iDownloadComplete=%d",
                     iPlaybackUnderflow, iRequestResumeNotification, iDownloadComplete));

    aNeedSendUnderflowEvent = !iRequestResumeNotification;

    if (!(aDownloadComplete = iDownloadComplete))
    {
        iPlaybackUnderflow = true;
        iCurrentNPTReadPosition = currentNPTReadPosition;
        iDownloadComplete = false;
    }

    iRequestResumeNotification = true;

    // save the download size at the underflow point
    iPrevDownloadSize = iNodeOutput->getCurrentOutputSize();

    // estimate playback rate and save the download size at the underflow point
    if (currentNPTReadPosition > 0 && currentNPTReadPosition < 0xFFFFFFFF)
    {
        // estimate playback rate
        iPlaybackByteRate = divisionInMilliSec(iProtocol->getDownloadSize(), currentNPTReadPosition);

        LOGINFODATAPATH((0, "pvDownloadControl::requestResumeNotification(), currentNPTReadPosition=%d, playbackRate=%dbps, prevDownloadSize=%d",
                         currentNPTReadPosition, (iPlaybackByteRate << 3), iPrevDownloadSize));
    }
}

void pvDownloadControl::setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType)
{
    switch (aType)
    {
        case DownloadControlSupportObjectType_SupportInterface:
            iProgDownloadSI = (PVMFFormatProgDownloadSupportInterface*)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_ProgressInterface:
        {
            PVMFDownloadProgressInterface *aProgDownload = (PVMFDownloadProgressInterface *)aDLSupportObject;
            if (iProgDownloadSI) iProgDownloadSI->setDownloadProgressInterface(aProgDownload);
            break;
        }
        case DownloadControlSupportObjectType_EnginePlaybackClock:
            iCurrentPlaybackClock = (OsclClock *)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_ProtocolEngine:
            iProtocol = (HttpBasedProtocol *)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_DownloadProgress:
            iDownloadProgress = (DownloadProgressInterface *)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_OutputObject:
            iNodeOutput = (PVMFProtocolEngineNodeOutput *)aDLSupportObject;
            break;

        default:
            break;
    }
}

// check whether to make resume notification; if needed, then make resume notification
// Return value: 1 means making resume notification normally (underflow->auto resume),
//				 2 means making resume notification for download complete
//				 0 means anything else
int32 pvDownloadControl::checkResumeNotification(const bool aDownloadComplete)
{
    LOGINFODATAPATH((0, "pvDownloadControl::checkResumeNotification() IN, iPlaybackUnderflow=%d, iRequestResumeNotification=%d, aDownloadComplete=%d",
                     (uint32)iPlaybackUnderflow, (uint32)iRequestResumeNotification, (uint32)aDownloadComplete));

    // short-cut: download complete
    if (!checkDownloadCompleteForResumeNotification(aDownloadComplete)) return 0;

    // real work that causes some PDL and PS differences
    if (!iPlaybackUnderflow && iRequestResumeNotification)
    {
        sendResumeNotification(iDownloadComplete);
        return 2;
    }


    // check if need to resume playback
    if (iPlaybackUnderflow &&
            isResumePlayback(iProtocol->getDownloadRate(),
                             iNodeOutput->getCurrentOutputSize(),
                             iProtocol->getContentLength()))
    {
#ifdef ANDROID
        LOGV("DownloadRate %d bytes per sec. Downloaded Bytes %d/%d", iProtocol->getDownloadRate(), iNodeOutput->getCurrentOutputSize(), iProtocol->getContentLength());
#endif
        iPlaybackUnderflow = false;
        sendResumeNotification(iDownloadComplete);
        return 1;
    }

    return 0;
}

bool pvDownloadControl::checkDownloadCompleteForResumeNotification(const bool aDownloadComplete)
{
    if (aDownloadComplete)
    {
        LOGINFODATAPATH((0, "pvDownloadControl::checkDownloadCompleteForResumeNotification()  Download is complete, final download rate = %dbps", (iProtocol->getDownloadRate() << 3)));
    }

    iDownloadComplete = aDownloadComplete;
    if (!pvDownloadControl::isInfoReady()) return false;

    // set file size to parser node
    setFileSize(iProtocol->getContentLength());

    // send download complete notification to parser node
    if (aDownloadComplete) sendDownloadCompleteNotification();

    // update download clock
    if (!iDownloadComplete) updateDownloadClock();
    return true;
}

void pvDownloadControl::setFileSize(const uint32 aFileSize)
{
    if (iSetFileSize) return;
    if (aFileSize == 0 || !iProgDownloadSI) return;

    iProgDownloadSI->setFileSize(aFileSize);
    iSetFileSize = true;
}

void pvDownloadControl::sendResumeNotification(bool aDownloadComplete)
{
    if (iRequestResumeNotification)
    {
        iProgDownloadSI->playResumeNotification(aDownloadComplete);
        iRequestResumeNotification = false;
        if (aDownloadComplete) iPlaybackUnderflow = false;

        // sync up with actual download complete
        if (aDownloadComplete && !iDownloadComplete) iDownloadComplete = aDownloadComplete;
    }
}

void pvDownloadControl::sendDownloadCompleteNotification()
{
    if (!iProgDownloadSI || iSendDownloadCompleteNotification) return;

    // send download complete notification
    LOGINFODATAPATH((0, "pvDownloadControl::sendDownloadCompleteNotification() - Notify download complete"));
    iProgDownloadSI->notifyDownloadComplete();
    iSendDownloadCompleteNotification = true;
}

// create iDlProgressClock, will leave when memory allocation fails
void pvDownloadControl::createDownloadClock()
{
    // create shared OsclClock
    PVDlSharedPtrAlloc<OsclClock> alloc;
    OsclClock* myClock = alloc.allocate();
    OsclRefCounterSA< PVDlSharedPtrAlloc<OsclClock> > *refcnt = new OsclRefCounterSA< PVDlSharedPtrAlloc<OsclClock> >(myClock);
    OsclSharedPtr<OsclClock> myHandle(myClock, refcnt);
    iDlProgressClock = myHandle;

    // set the clock base
    iDlProgressClock->SetClockTimebase(iEstimatedServerClockTimeBase);
    uint32 startTime = 0; // for type conversion
    iDlProgressClock->SetStartTime32(startTime, OSCLCLOCK_SEC);
}


// auto-resume playback decision
bool pvDownloadControl::isResumePlayback(const uint32 aDownloadRate,
        const uint32 aCurrDownloadSize,
        const uint32 aFileSize)
{
    // check download complete, for download complete, no need to run the following algorithm
    if (iDownloadComplete || isOutputBufferOverflow())
    {
        if (!iDownloadComplete)
        {
            LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback(), output buffer (MBDS is full) overflows!! Then auto-resume kicks off!!"));
        }
        return true;
    }

    // check playback clock, if not available, then switch to the old algorithm
    if (!iCurrentPlaybackClock) return isResumePlaybackWithOldAlg(aDownloadRate, aFileSize - aCurrDownloadSize);

    // check the pre-conditins including initial download time/size for download rate estimation purpose
    if (!isDlAlgoPreConditionMet(aDownloadRate, iClipDurationMsec, aCurrDownloadSize, aFileSize)) return false;

    // get the playback clock time
    if (iClipDurationMsec > 0 && aFileSize > 0)
    {
        return checkAutoResumeAlgoWithConstraint(aDownloadRate, aFileSize - aCurrDownloadSize, iClipDurationMsec, aFileSize);
    }

    return checkAutoResumeAlgoNoConstraint(aCurrDownloadSize, aFileSize, iClipDurationMsec);
}


bool pvDownloadControl::isDlAlgoPreConditionMet(const uint32 aDownloadRate,
        const uint32 aDurationMsec,
        const uint32 aCurrDownloadSize,
        const uint32 aFileSize)
{
    if (iDlAlgoPreConditionMet) return iDlAlgoPreConditionMet;

    LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback()->isDlAlgoPreConditionMet(), download rate = %d , clip duration = %dms, download size = %d",
                     aDownloadRate, aDurationMsec, aCurrDownloadSize));
    OSCL_UNUSED_ARG(aDurationMsec);
    if (aDownloadRate == 0) return false;

    // check initial download time for download rate estimation
    uint32 downloadTimeMsec = iProtocol->getDownloadTimeForEstimation();
    LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback()->isDlAlgoPreConditionMet(), check dl_time(%dms) > 1sec, OR download size(%d) >= 10 percent of file size(%d)=%d",
                     downloadTimeMsec, aCurrDownloadSize, aFileSize, aFileSize / PVPROTOCOLENGINE_INIT_DOWNLOAD_SIZE_PERCENTAGE_THRESHOLD));
    iDlAlgoPreConditionMet = (downloadTimeMsec >= PVPROTOCOLENGINE_INIT_DOWNLOAD_TIME_THRESHOLD);
    if (iDlAlgoPreConditionMet) return true;

    // check initial download size for download rate estimation
    uint32 initDownloadThreshold = (aFileSize > 0 ? aFileSize / PVPROTOCOLENGINE_INIT_DOWNLOAD_SIZE_PERCENTAGE_THRESHOLD : PVPROTOCOLENGINE_INIT_DOWNLOAD_SIZE_THRESHOLD);
    iDlAlgoPreConditionMet = (aCurrDownloadSize >= initDownloadThreshold);
    return iDlAlgoPreConditionMet;
}

// with contraint: file size and clip duration are both available
bool pvDownloadControl::checkAutoResumeAlgoWithConstraint(const uint32 aDownloadRate,
        const uint32 aRemainingDownloadSize,
        const uint32 aDurationMsec,
        const uint32 aFileSize)
{
    // get the playback clock time
    uint32 playbackTimeMec32 = 0;
    if (!getPlaybackTimeFromEngineClock(playbackTimeMec32)) return false;

    LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback()->checkAutoResumeAlgowithConstraint(), algorithm: RemainingDownloadSize < 0.0009 * dl_rate * remaining_playback_time: remaining_dl_size= %d, dl_rate=%dByte/s,  playback_remaining_time=%dms",
                     aRemainingDownloadSize, aDownloadRate, aDurationMsec - playbackTimeMec32));
    // the basic algorithm is, remaining download time (remaining download size/download rate) <
    //						   remaining playback time (duration - current playback time) * 0.9

    uint32 newDurationMsec = aDurationMsec;
    if (!checkNewDuration(aDurationMsec, newDurationMsec)) return false;
    uint32 playbackRemainingTimeMsec = newDurationMsec - playbackTimeMec32;
    // 4sec buffering time
    if (approveAutoResumeDecisionShortCut(aFileSize - aRemainingDownloadSize, newDurationMsec, playbackTimeMec32, playbackRemainingTimeMsec))
    {
        LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback()->checkAutoResumeAlgowithConstraint(), 4sec extra buffering time"));
        return true;
    }

    if (approveAutoResumeDecision(aRemainingDownloadSize, aDownloadRate, playbackRemainingTimeMsec))
    {
        LOGINFODATAPATH((0, "pvDownloadControl::isResumePlayback()->checkAutoResumeAlgowithConstraint(), BytesLeft = %d, dl_rate = %dbps, duration = %d(orig_duration=%d), playback_time=%d",
                         aRemainingDownloadSize, (aDownloadRate << 3), newDurationMsec, aDurationMsec, playbackTimeMec32));
        return true;
    }

    return false;
}


bool pvDownloadControl::getPlaybackTimeFromEngineClock(uint32 &aPlaybackTime)
{
    aPlaybackTime = 0;
    bool isPbOverflow = false;
    iCurrentPlaybackClock->GetCurrentTime32(aPlaybackTime, isPbOverflow, OSCLCLOCK_MSEC);
    if (isPbOverflow)
    {
        LOGERRORDATAPATH((0, "pvDownloadControl::getPlaybackTimeFromEngineClock(), Playback clock overflow %d", isPbOverflow));
        return false;
    }
    return true;
}

// use fixed-point calculation to replace the float-point calculation: aRemainingDLSize<0.0009*aDownloadRate*aRemainingPlaybackTime
bool pvDownloadControl::approveAutoResumeDecision(const uint32 aRemainingDLSize,
        const uint32 aDownloadRate,
        const uint32 aRemainingPlaybackTime)
{
    // fixed-point calculation
    // 0.0009 = 1/1111 ~= 1/1024 = 1/2^10 = right shift 10 bits
    // aRemainingDLSize<(aDownloadRate*aRemainingPlaybackTime>>10)

    uint32 max = OSCL_MAX(aDownloadRate, aRemainingPlaybackTime);
    if ((max >> PVPROTOCOLENGINE_AUTO_RESUME_FIXED_CALCULATION_MAX_LIMIT_RIGHT_SHIFT_FACTOR) == 0)   // right shift 16 bits, 2^16= 65536
    {
        return (aRemainingDLSize < (aDownloadRate*aRemainingPlaybackTime >>
                                    PVPROTOCOLENGINE_AUTO_RESUME_FIXED_CALCULATION_RIGHT_SHIFT)); // right shift 10 bits
    }
    else
    {
        uint32 min = OSCL_MIN(aDownloadRate, aRemainingPlaybackTime);
        uint32 maxRightShift10 = max >> PVPROTOCOLENGINE_AUTO_RESUME_FIXED_CALCULATION_RIGHT_SHIFT; // right shift 10 bits
        return (aRemainingDLSize / maxRightShift10 < min);
    }
}

// result = x*1000/y
uint32 pvDownloadControl::divisionInMilliSec(const uint32 x, const uint32 y)
{
    // result = x*1000/y
    // handle overflow issue
    uint32 result = 0;
    if (x >> PVPROTOCOLENGINE_DOWNLOAD_DURATION_CALCULATION_LIMIT_RIGHT_SHIFT_FACTOR)
    {
        result = (x >> PVPROTOCOLENGINE_DOWNLOAD_DURATION_CALCULATION_RIGHTSHIFT_FACTOR) * 1000 /
                 (y >> PVPROTOCOLENGINE_DOWNLOAD_DURATION_CALCULATION_RIGHTSHIFT_FACTOR);
    }
    else
    {
        result = x * 1000 / y;
    }
    return result;
}

bool pvDownloadControl::isResumePlaybackWithOldAlg(const uint32 aDownloadRate, const uint32 aRemainingDownloadSize)
{
    // get the download progress clock time
    uint64 download_time;
    iDlProgressClock->GetCurrentTime64(download_time, OSCLCLOCK_MSEC);
    uint32 currentNPTDownloadPosition = Oscl_Int64_Utils::get_uint64_lower32(download_time);

    LOGINFODATAPATH((0, "pvDownloadControl::isResumePlaybackWithOldAlg(), download_time=%dms, download_complete=%d\n", download_time, iDownloadComplete));

    if (iCurrentNPTReadPosition < currentNPTDownloadPosition)
    {
        // bytes_remaining < (0.9 * (received data rate * file duration ))

        uint32 BytesTobeDownloadedForAutoResume = (uint32)((currentNPTDownloadPosition - iCurrentNPTReadPosition) *
                aDownloadRate * 0.0009);

        LOGINFODATAPATH((0, "pvDownloadControl::isResumePlaybackWithOldAlg(), currentDLPosition=%dms, iCurrentReadPosition=%dms, downloadRate=%d, remainingSize %d\n", \
                         currentNPTDownloadPosition, iCurrentNPTReadPosition, aDownloadRate, aRemainingDownloadSize));

        if (BytesTobeDownloadedForAutoResume > aRemainingDownloadSize)
        {
            return true;
        }
    }

    return false;
}

void pvDownloadControl::cancelResumeNotification()
{
    // Just reset the boolean iRequestResumeNotification, so that download control sends no resume notification.
    iRequestResumeNotification = false;
}


////////////////////////////////////////////////////////////////////////////////////
//////	DownloadProgress implementation
////////////////////////////////////////////////////////////////////////////////////
// constructor
DownloadProgress::DownloadProgress() :
        iProtocol(NULL),
        iProgDownloadSI(NULL),
        iNodeOutput(NULL)
{
    reset();
}

void DownloadProgress::reset()
{
    //for progress reports
    iCurrProgressPercent  = 0;
    iPrevProgressPercent  = 0;
    iDownloadNPTTime	  = 0;
    iDurationMsec		  = 0;
}

void DownloadProgress::setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType)
{
    switch (aType)
    {
        case DownloadControlSupportObjectType_SupportInterface:
            iProgDownloadSI = (PVMFFormatProgDownloadSupportInterface*)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_ProtocolEngine:
            iProtocol = (HttpBasedProtocol *)aDLSupportObject;
            break;

        case DownloadControlSupportObjectType_OutputObject:
            iNodeOutput = (PVMFProtocolEngineNodeOutput *)aDLSupportObject;
            break;

        default:
            break;
    }
}

bool DownloadProgress::update(const bool aDownloadComplete)
{
    if (!aDownloadComplete) updateDownloadClock();

    // update download progress
    uint32 newProgressPercent = 0;
    if (!calculateDownloadPercent(newProgressPercent)) return false;

    //Report 0... 100 percent complete.
    // In progressive streaming, repositioning is allowed during download
    // so the download percentage does not always increase
    if (newProgressPercent != iCurrProgressPercent)
    {
        //avoid sending the same percentage update
        iCurrProgressPercent = newProgressPercent;
        return true;
    }
    return false;
}

bool DownloadProgress::getNewProgressPercent(uint32 &aProgressPercent)
{
    aProgressPercent = iCurrProgressPercent;
    // in progressive streaming, after repositioning esp rewind, the current download percentage
    // may be smaller than the previous percentage and current percentage may not be 0 unless rewind back to
    // // beginning of clip
    if (((iCurrProgressPercent < iPrevProgressPercent) && iPrevProgressPercent > 0) ||
            iCurrProgressPercent > iPrevProgressPercent)
    {
        iPrevProgressPercent = iCurrProgressPercent;
        return true;
    }
    return false;
}

bool DownloadProgress::calculateDownloadPercent(uint32 &aDownloadProgressPercent)
{
    // clip duration
    uint32 clipDuration = getClipDuration();
    if (clipDuration == 0) return false;

    // download progress, convert to percent complete.
    aDownloadProgressPercent = iDownloadNPTTime * 100 / clipDuration;
    if (aDownloadProgressPercent > 100) aDownloadProgressPercent = 100;
    return true;
}

uint32 DownloadProgress::getClipDuration()
{
    return iDurationMsec;
}

////////////////////////////////////////////////////////////////////////////////////
//////	PVMFDownloadDataSourceContainer implementation
////////////////////////////////////////////////////////////////////////////////////
PVMFDownloadDataSourceContainer::PVMFDownloadDataSourceContainer(OsclAny* aSourceData)
{
    addSource(aSourceData);
}

bool PVMFDownloadDataSourceContainer::addSource(OsclAny* aSourceData)
{
    PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, aSourceData);

    PVInterface* aDownloadSourceInterface = NULL;
    PVUuid downloadHTTPDataUuid(PVMF_DOWNLOAD_DATASOURCE_HTTP_UUID);
    if (pvInterface->queryInterface(downloadHTTPDataUuid, aDownloadSourceInterface))
    {
        PVMFDownloadDataSourceHTTP* aInterface = OSCL_STATIC_CAST(PVMFDownloadDataSourceHTTP*, aDownloadSourceInterface);
        copy(*aInterface);
        return true;
    }

    PVUuid downloadPVXDataUuid(PVMF_DOWNLOAD_DATASOURCE_PVX_UUID);
    if (pvInterface->queryInterface(downloadPVXDataUuid, aDownloadSourceInterface))
    {
        PVMFDownloadDataSourcePVX* aInterface = OSCL_STATIC_CAST(PVMFDownloadDataSourcePVX*, aDownloadSourceInterface);
        copy(*aInterface);
        return true;
    }

    PVInterface* sourceDataContext = NULL;
    PVUuid sourceContextUuid(PVMF_SOURCE_CONTEXT_DATA_UUID);
    if (pvInterface->queryInterface(sourceContextUuid, sourceDataContext))
    {

        PVUuid dlHTTPContextUuid(PVMF_SOURCE_CONTEXT_DATA_DOWNLOAD_HTTP_UUID);
        if (sourceDataContext->queryInterface(dlHTTPContextUuid, aDownloadSourceInterface))
        {
            PVMFSourceContextDataDownloadHTTP* aInterface = OSCL_STATIC_CAST(PVMFSourceContextDataDownloadHTTP*, aDownloadSourceInterface);
            copy(*aInterface);
            return true;
        }

        PVUuid dlPVXContextUuid(PVMF_SOURCE_CONTEXT_DATA_DOWNLOAD_PVX_UUID);
        if (sourceDataContext->queryInterface(dlPVXContextUuid, aDownloadSourceInterface))
        {
            PVMFSourceContextDataDownloadPVX* aInterface = OSCL_STATIC_CAST(PVMFSourceContextDataDownloadPVX*, aDownloadSourceInterface);
            copy(*aInterface);
            return true;
        }
    }
    return false;
}

void PVMFDownloadDataSourceContainer::copy(const PVMFDownloadDataSourceHTTP& aSourceData)
{
    iHasDataSource	  = true;
    iIsNewSession	  = aSourceData.bIsNewSession;
    iMaxFileSize	  = aSourceData.iMaxFileSize;
    iPlaybackControl  = (uint32)convert(aSourceData.iPlaybackControl);
    if (aSourceData.iPlaybackControl == PVMFDownloadDataSourceHTTP::ENoSaveToFile) iIsNewSession = true; // always use new download session for progressive streaming
    iConfigFileName   = aSourceData.iConfigFileName;
    iDownloadFileName = aSourceData.iDownloadFileName;
    iProxyName		  = aSourceData.iProxyName;
    iProxyPort		  = aSourceData.iProxyPort;
    iPvxInfo		  = NULL;
}

void PVMFDownloadDataSourceContainer::copy(const PVMFDownloadDataSourcePVX& aSourceData)
{
    iHasDataSource	  = true;
    iIsNewSession	  = aSourceData.bIsNewSession;
    iMaxFileSize	  = aSourceData.iMaxFileSize;
    iPlaybackControl  = 0;
    iConfigFileName   = aSourceData.iConfigFileName;
    iDownloadFileName = aSourceData.iDownloadFileName;
    iProxyName		  = aSourceData.iProxyName;
    iProxyPort		  = aSourceData.iProxyPort;
    iPvxInfo		  = &aSourceData.iPvxInfo;
}

void PVMFDownloadDataSourceContainer::copy(const PVMFSourceContextDataDownloadHTTP& aSourceData)
{
    iHasDataSource	  = true;
    iIsNewSession	  = aSourceData.bIsNewSession;
    iMaxFileSize	  = aSourceData.iMaxFileSize;
    iPlaybackControl  = (uint32)aSourceData.iPlaybackControl;
    if (aSourceData.iPlaybackControl == PVMFSourceContextDataDownloadHTTP::ENoSaveToFile) iIsNewSession = true; // always use new download session for progressive streaming
    iConfigFileName   = aSourceData.iConfigFileName;
    iDownloadFileName = aSourceData.iDownloadFileName;
    iProxyName		  = aSourceData.iProxyName;
    iProxyPort		  = aSourceData.iProxyPort;
    iUserID			  = aSourceData.iUserID;
    iUserPasswd		  = aSourceData.iUserPasswd;
    iPvxInfo		  = NULL;
}

void PVMFDownloadDataSourceContainer::copy(const PVMFSourceContextDataDownloadPVX& aSourceData)
{
    iHasDataSource	  = true;
    iIsNewSession	  = aSourceData.bIsNewSession;
    iMaxFileSize	  = aSourceData.iMaxFileSize;
    iPlaybackControl  = 0;
    iConfigFileName   = aSourceData.iConfigFileName;
    iDownloadFileName = aSourceData.iDownloadFileName;
    iProxyName		  = aSourceData.iProxyName;
    iProxyPort		  = aSourceData.iProxyPort;
    iPvxInfo		  = aSourceData.iPvxInfo;
}

PVMFSourceContextDataDownloadHTTP::TPVPlaybackControl PVMFDownloadDataSourceContainer::convert(const PVMFDownloadDataSourceHTTP::TPVPlaybackControl aPlaybackControl)
{
    switch (aPlaybackControl)
    {
        case PVMFDownloadDataSourceHTTP::ENoPlayback:
            return PVMFSourceContextDataDownloadHTTP::ENoPlayback;
        case PVMFDownloadDataSourceHTTP::EAfterDownload:
            return PVMFSourceContextDataDownloadHTTP::EAfterDownload;
        case PVMFDownloadDataSourceHTTP::EAsap:
            return PVMFSourceContextDataDownloadHTTP::EAsap;
        case PVMFDownloadDataSourceHTTP::ENoSaveToFile:
            return PVMFSourceContextDataDownloadHTTP::ENoSaveToFile;
        case PVMFDownloadDataSourceHTTP::EReserve:
            return PVMFSourceContextDataDownloadHTTP::EReserve;
        default:
            break;
    };
    return PVMFSourceContextDataDownloadHTTP::EAsap;
}


////////////////////////////////////////////////////////////////////////////////////
//////	PVDlCfgFileContainer implementation
////////////////////////////////////////////////////////////////////////////////////
PVMFStatus PVDlCfgFileContainer::createCfgFile(OSCL_String &aUrl)
{
    // iDataSource should be ready at this point
    if (!iDataSource) return PVMFFailure;

    // create iCfgFileObj
    PVDlSharedPtrAlloc<PVDlCfgFile> alloc;
    PVDlCfgFile* myCfg = alloc.allocate();
    OsclRefCounterSA< PVDlSharedPtrAlloc<PVDlCfgFile> > *refcnt = new OsclRefCounterSA< PVDlSharedPtrAlloc<PVDlCfgFile> >(myCfg);
    OsclSharedPtr<PVDlCfgFile> myHandle(myCfg, refcnt);
    iCfgFileObj = myHandle;

    // set common stuff for progressive download and fasttrack
    OSCL_FastString player_version(_STRLIT_CHAR("4.0"));
    iCfgFileObj->SetPlayerVersion(player_version);

    OSCL_FastString user_network(_STRLIT_CHAR("UNKNOWN"));
    iCfgFileObj->SetUserNetwork(user_network);

    OSCL_FastString deviceInfo(_STRLIT_CHAR("MANUF=UNKNOWN;PROC=WINS EMULATOR;MEM=UNKNOWN;OS=EPOC;DISPLAY=TRUECOLOR16"));
    iCfgFileObj->SetDeviceInfo(deviceInfo);

    iCfgFileObj->SetNetworkTimeouts(30000, 30000, -1);

    iCfgFileObj->SetRangeStartTime(0);

    return configCfgFile(aUrl);
}

PVMFStatus PVDlCfgFileContainer::loadOldConfig()
{
    int32 status = iCfgFileObj->LoadConfig();
    LOGINFODATAPATH((0, "PVDlCfgFileContainer::loadOldConfig() status=%d(-1 critical, -2 non-critical), currFileSize=%d, totalFileSize=%d, rangeStartTime=%d",
                     status, iCfgFileObj->GetCurrentFileSize(), iCfgFileObj->GetOverallFileSize(), iCfgFileObj->GetRangeStartTime()));

    if (status == PVDlCfgFile::LoadConfigStatus_CriticalError) return PVMFFailure;
    if (status == PVDlCfgFile::LoadConfigStatus_NonCriticalError)
    {
        // set up a new download session
        iCfgFileObj->SetCurrentFileSize(0);
        iCfgFileObj->SetOverallFileSize(iCfgFileObj->GetMaxAllowedFileSize());
        iCfgFileObj->SetNewSession();
    }

    PVDlCfgFile::TPVDLPlaybackMode tmpPlaybackMode = iCfgFileObj->GetPlaybackMode();
    if (tmpPlaybackMode == PVDlCfgFile::EPVDL_ASAP)
    {
        iPlaybackMode = PVMFDownloadDataSourceHTTP::EAsap;;
    }
    else if (tmpPlaybackMode == PVDlCfgFile::EPVDL_PLAYBACK_AFTER_DOWNLOAD)
    {
        iPlaybackMode = PVMFDownloadDataSourceHTTP::EAfterDownload;
    }
    else if (tmpPlaybackMode == PVDlCfgFile::EPVDL_DOWNLOAD_ONLY)
    {
        iPlaybackMode = PVMFDownloadDataSourceHTTP::ENoPlayback;
    }
    else //if(tmpPlaybackMode == PVDlCfgFile::EReserve )
    {
        //iPlaybackMode = PVMFDownloadDataSourceHTTP::EReserve;
        return PVMFFailure;
    }
    return PVMFSuccess;
}

PVMFStatus PVDlCfgFileContainer::configCfgFile(OSCL_String &aUrl)
{
    if (iDataSource->isEmpty()) return PVMFFailure;
    if (iDataSource->iMaxFileSize <= 0) return PVMFFailure;
    iCfgFileObj->SetOverallFileSize(iDataSource->iMaxFileSize);
    iCfgFileObj->SetMaxAllowedFileSize(iDataSource->iMaxFileSize);

    iCfgFileObj->SetConfigFileName(iDataSource->iConfigFileName);
    iCfgFileObj->SetDownloadFileName(iDataSource->iDownloadFileName);

    // save URL
    iCfgFileObj->SetUrl(aUrl);

    // for old session, load the config file
    if (!iDataSource->iIsNewSession) return loadOldConfig();
    return PVMFSuccess;
}



////////////////////////////////////////////////////////////////////////////////////
//////	downloadEventReporter implementation
////////////////////////////////////////////////////////////////////////////////////
downloadEventReporter::downloadEventReporter(PVMFProtocolEngineNode *aNode) : EventReporter(aNode)
{
    clear();
}

void downloadEventReporter::clear()
{
    iSendBufferStartInfoEvent		= false;
    iSendBufferCompleteInfoEvent	= false;
    iSendMovieAtomCompleteInfoEvent = false;
    iSendInitialDataReadyEvent		= false;
    iSendContentLengthEvent			= false;
    iSendContentTruncateEvent		= false;
    iSendContentTypeEvent			= false;
    iSendUnexpectedDataEvent		= false;
    iSendServerDisconnectEvent		= false;

    EventReporter::clear();
}

void downloadEventReporter::sendDataReadyEvent()
{
    iNode->ReportInfoEvent(PVMFInfoDataReady, (OsclAny*)iNode->iProtocol->getDownloadRate());
    iSendInitialDataReadyEvent = true;
}

bool downloadEventReporter::checkReportEvent(const uint32 downloadStatus)
{
    // PVMFInfoContentLength, PVMFErrContentTooLarge and PVMFInfoContentTruncated
    if (!checkContentInfoEvent(downloadStatus)) return false;

    // PVMFInfoBufferingStart, PVMFInfoBufferingStatus and PVMFInfoBufferingComplete event
    return checkBufferInfoEvent(downloadStatus);
}

bool downloadEventReporter::checkBufferInfoEvent(const uint32 downloadStatus)
{
    // PVMFInfoBufferingStart event
    if (!iSendBufferStartInfoEvent)
    {
        iNode->ReportInfoEvent(PVMFInfoBufferingStart); // first coming media data triggers sending PVMFInfoBufferingStart event
        iSendBufferStartInfoEvent = true;
        if (!isDownloadComplete(downloadStatus)) return true;
    }

    // PVMFInfoBufferingStatus and PVMFInfoBufferingComplete event
    if (iStarted && iNode->iDownloadProgess)
    {
        uint32 aProgessPercent = 0;
        if (iNode->iDownloadProgess->getNewProgressPercent(aProgessPercent))
        {
            iNode->ReportInfoEvent(PVMFInfoBufferingStatus, (OsclAny*)aProgessPercent,
                                   PVMFPROTOCOLENGINENODEInfo_BufferingStatus);
            LOGINFODATAPATH((0, "downloadEventReporter::checkBufferInfoEvent() DOWNLOAD PERCENTAGE: %d", aProgessPercent));
        }

        // check and send buffer complete, data ready and unexpected data events
        checkBufferCompleteEvent(downloadStatus);
    }

    return true;
}

// check and send buffer complete, data ready and unexpected data events
void downloadEventReporter::checkBufferCompleteEvent(const uint32 downloadStatus)
{
    if (!iSendBufferCompleteInfoEvent && isDownloadComplete(downloadStatus))
    {
        uint32 aProgessPercent = 0;
        iNode->iDownloadProgess->getNewProgressPercent(aProgessPercent);
        if (aProgessPercent < 100)
        {
            aProgessPercent = 100;
            iNode->ReportInfoEvent(PVMFInfoBufferingStatus, (OsclAny*)aProgessPercent,
                                   PVMFPROTOCOLENGINENODEInfo_BufferingStatus);
        }

        // send buffer complete event
        iNode->ReportInfoEvent(PVMFInfoBufferingComplete, (OsclAny*)iNode->iProtocol->getDownloadSize());
        iSendBufferCompleteInfoEvent = true;

        // check and send data ready event
        if (!iSendInitialDataReadyEvent)
        {
            iNode->ReportInfoEvent(PVMFInfoDataReady);
            iSendInitialDataReadyEvent = true;
        }
    }

    checkUnexpectedDataAndServerDisconnectEvent(downloadStatus);
}

void downloadEventReporter::checkUnexpectedDataAndServerDisconnectEvent(const uint32 downloadStatus)
{
    if (!iSendBufferCompleteInfoEvent && isDownloadComplete(downloadStatus))
    {
        // check and send unexpected data event
        checkUnexpectedDataEvent(downloadStatus);
    }

    // check and send unexpected data event, PVMFInfoUnexpectedData
    checkUnexpectedDataEvent(downloadStatus);

    // check and send server disconnect event, PVMFInfoSessionDisconnect
    // especially for no content length case
    checkServerDisconnectEvent(downloadStatus);
}

void downloadEventReporter::checkUnexpectedDataEvent(const uint32 downloadStatus)
{
    if (!iSendUnexpectedDataEvent && !iSendServerDisconnectEvent && // if PVMFInfoSessionDisconnect is sent, no need to send PVMFInfoUnexpectedData
            downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA)
    {
        iNode->ReportInfoEvent(PVMFInfoUnexpectedData);
        iSendUnexpectedDataEvent = true;
    }
}

void downloadEventReporter::checkServerDisconnectEvent(const uint32 downloadStatus)
{
    if (!iSendServerDisconnectEvent)
    {
        if (downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT ||
                (!iNode->iCfgFileContainer->getCfgFile()->IsNewSession() &&
                 downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE &&
                 iSendBufferCompleteInfoEvent))   // resume download and previous complete download
        {
            iNode->ReportInfoEvent(PVMFInfoSessionDisconnect);
            iSendServerDisconnectEvent = true;
        }
    }
}


bool downloadEventReporter::checkContentInfoEvent(const uint32 downloadStatus)
{
    // short-cut
    if (!needToCheckContentInfoEvent()) return true;

    // PVMFInfoContentType
    if (!iSendContentTypeEvent)
    {
        OSCL_HeapString<OsclMemAllocator> aContentType;
        if (iNode->iProtocol->getContentType(aContentType))
        {
            iNode->ReportInfoEvent(PVMFInfoContentType, (void*)(aContentType.get_cstr()));
            iSendContentTypeEvent = true;
        }
    }

    // check and send PVMFInfoContentLength or PVMFErrContentTooLarge
    if (!checkContentLengthOrTooLarge()) return false;

    // check and send PVMFInfoContentTruncated
    return checkContentTruncated(downloadStatus);
}

bool downloadEventReporter::checkContentLengthOrTooLarge()
{
    // PVMFInfoContentLength
    uint32 fileSize = iInterfacingObjectContainer->getFileSize();
    uint32 maxAllowedFileSize = iNode->iCfgFileContainer->getCfgFile()->GetMaxAllowedFileSize();

    if (!iSendContentLengthEvent && fileSize > 0)
    {
        iNode->ReportInfoEvent(PVMFInfoContentLength, (OsclAny*)fileSize);
        iSendContentLengthEvent = true;

        // PVMFErrContentTooLarge
        if (fileSize > maxAllowedFileSize)
        {
            ProtocolStateErrorInfo aInfo(PVMFErrContentTooLarge);
            PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
            iNode->DispatchInternalEvent(&aEvent);
            return false;
        }
    }
    return true;
}

// check and send PVMFInfoContentTruncated
bool downloadEventReporter::checkContentTruncated(const uint32 downloadStatus)
{
    if (!iStarted) return true;
    if (!iSendContentTruncateEvent)
    {
        int32 status = isDownloadFileTruncated(downloadStatus);
        if (status > 0)
        {
            if (status == 1) iNode->ReportInfoEvent(PVMFInfoContentTruncated, (OsclAny*)iNode->iProtocol->getDownloadSize());
            if (status == 2) iNode->ReportInfoEvent(PVMFInfoContentTruncated, (OsclAny*)iNode->iProtocol->getDownloadSize(),
                                                        PVMFPROTOCOLENGINENODEInfo_TruncatedContentByServerDisconnect);
            //iNode->Clear();
            iSendContentTruncateEvent = true;
        }
    }
    return true;
}

// return code: 0 - no truncation,
//				1 - truncation (download size >= maximum file size)
//				2 - truncation (download size < content length, server disconnect)
int32 downloadEventReporter::isDownloadFileTruncated(const uint32 downloadStatus)
{
    // 1. connection shutdown case with content length
    // if no content length and connection is done, this case should be download complete,
    // and the download size should be file size (this is NOT truncated case)
    uint32 currDownloadSize = iNode->iProtocol->getDownloadSize();
    uint32 contentLength = iInterfacingObjectContainer->getFileSize();
    if (isDownloadComplete(downloadStatus))
    {
        // short-cut: for resume download, if previous download is complete download, then return 0 (no truncation)
        if (!iNode->iCfgFileContainer->getCfgFile()->IsNewSession() && downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE) return 0;
        if (currDownloadSize < contentLength) return 2;
    }

    // 2. no content length case : download size >= maximum file size (storage size)
    if (contentLength == 0)
    {
        if (downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED) return 1;
        uint32 maxFileSize = iNode->iCfgFileContainer->getCfgFile()->GetMaxAllowedFileSize();
        if (currDownloadSize <= maxFileSize) return 0;
        if (currDownloadSize > maxFileSize)  return 1;
    }
    return 0;
}


