/*
* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Implementation of CMPXVideoDownloadMgrInterface class.
*
*/

// Version : %version: 21 %


#include <MMFROPCustomCommandConstants.h>
#include <mmf/common/mmfcontrollerframework.h>
#include <mpxplaybackpluginobserver.h>
#include <mpxmessagegeneraldefs.h>
#include <mpxcommandgeneraldefs.h>
#include <pathinfo.h>
#include <f32file.h>

#ifdef RD_MULTIPLE_DRIVE
#include <driveinfo.h>
#endif  //RD_MULTIPLE_DRIVE

#include "mpxvideoplaybackcontroller.h"
#include "mpxvideodlmgrif.h"
#include "mpxvideodrmhelper.h"
#include <mpxvideoplaybackdefs.h>
#include "mpxvideo_debug.h"


CMPXVideoDlMgrIf*
CMPXVideoDlMgrIf::NewL( CMPXVideoPlaybackController* aController )
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::NewL()"));

    CMPXVideoDlMgrIf* self = new (ELeave) CMPXVideoDlMgrIf();
    CleanupStack::PushL( self );
    self->ConstructL( aController );
    CleanupStack::Pop();
    return self;
}


void CMPXVideoDlMgrIf::ConstructL( CMPXVideoPlaybackController* aController )
{
    iController = aController;
    iUpdateDownload = CIdle::NewL( CActive::EPriorityLow );
}

CMPXVideoDlMgrIf::CMPXVideoDlMgrIf()
    : iDlId(KErrNotFound)
{
}

CMPXVideoDlMgrIf::~CMPXVideoDlMgrIf()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::~CMPXVideoDlMgrIf()"));

    //
    //  Check if we need to move the clip or remove PDL flag from download
    //
    HandleClose();

    //
    //  Close the connection to the Download Manager
    //  if one has been established
    //
    if ( iDlMgrConnected )
    {
        iDlMgr.Close();
        iDlMgrConnected = EFalse;
    }

    if ( iUpdateDownload->IsActive() )
    {
        iUpdateDownload->Cancel();
    }

    delete iUpdateDownload;

    if ( iClipName )
    {
        delete iClipName;
        iClipName = NULL;
    }
}


void CMPXVideoDlMgrIf::ConnectToDownloadL( CMPXCommand& aCmd )
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::ConnectToDownloadL()"));

    //
    //  Retrieve the download id from the message
    //
    TInt downloadId = *aCmd.Value<TInt>( KMPXCommandPlaybackPDTransactionID );
    TPtrC fileName( aCmd.ValueText( KMPXMediaVideoPlaybackFileName ) );
    iMovePdlFile = *aCmd.Value<TInt>( KMPXMediaVideoMovePdlFile );

    MPX_DEBUG(_L("CMPXVideoDlMgrIf::ConnectToDownloadL(%S, %d)"), &fileName, downloadId );

    if ( iClipName )
    {
        delete iClipName;
        iClipName = NULL;
    }

    iClipName = fileName.AllocL();

    //
    //  A new download id has been sent.  Reset member variables
    //
    iMoveNeeded    = EFalse;
    iCurrentDl     = NULL;
    iDlId          = downloadId;
    iPlayerOpened  = EFalse;
    iDlTotalSize   = 0;
    iDownloadProgress = 0;
    iCodDownload   = EFalse;

    if ( iDlMgrConnected )
    {
        iDlMgr.Close();
        iDlMgrConnected = EFalse;
    }

    if ( iDlId != KErrNotFound )
    {
        const TUid KUidLWPlayer = { 0x102824CD };

        //
        //  Connect to the Download Manager
        //
        iDlMgr.ConnectL( KUidLWPlayer, *this, EFalse );
        iDlMgrConnected = ETrue;

        //
        //  Attach to the download id
        //
        RHttpDownload& newDownload = iDlMgr.AttachToDownloadL( iDlId );

        //
        //  Update the members with the current download info
        //
        iCurrentDl = &newDownload;

        //
        //  Set the progressive download attribute on the download
        //
        iCurrentDl->SetBoolAttribute( EDlAttrProgressive, ETrue );

        iCurrentDl->SetBoolAttribute( EDlAttrSilent, EFalse );

        //a temp hack until dl manager has a fix for this
        TInt32 activeDownload( 0 );
        iCurrentDl->GetIntAttribute( EDlAttrActiveDownload, activeDownload );
        iCurrentDl->SetIntAttribute( EDlAttrActivePlayedDownload, activeDownload );

        //
        //  Set the Local File attribute
        //
        iCurrentDl->SetStringAttribute( EDlAttrLocalFileName, iClipName->Des() );

        TInt32 dlState;

        //
        //  Get the state, downloaded and total size of the download and save it
        //
        iCurrentDl->GetIntAttribute( EDlAttrLength, iDlTotalSize );
        iCurrentDl->GetIntAttribute( EDlAttrDownloadedSize, iDownloadProgress );
        iCurrentDl->GetIntAttribute( EDlAttrState, dlState );

        MPX_DEBUG(_L("   dlSize = %d, currentSize = %d, state = %d"),
            iDlTotalSize, iDownloadProgress, dlState );

        ConvertDMgrStatetoMpxState( dlState );

        if ( iDownloadState == EPbDlStateDownloadCompleted )
        {
            HandleDownloadComplete();
        }

        MPX_DEBUG(_L("CMPXVideoDlMgrIf::ConnectToDownloadL() Download State = %d Total Size=%d"),
            iDownloadState, iDlTotalSize);
    }
}

void
CMPXVideoDlMgrIf::HandleDMgrEventL( RHttpDownload& aDownload, THttpDownloadEvent aEvent )
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::HandleDMgrEventL()"),
                   _L("iDownloadState = %d iProgressState = %d"),
                    aEvent.iDownloadState, aEvent.iProgressState );

    TMPXPlaybackPdDownloadState prevDownloadState = iDownloadState;

    if ( &aDownload == iCurrentDl )
    {
        switch ( aEvent.iDownloadState )
        {
            case EHttpDlInprogress:
            {
                iDownloadState = EPbDlStateDownloading;

                switch ( aEvent.iProgressState )
                {
                    case EHttpProgResponseBodyReceived:
                    {
                        if ( ! iUpdateDownload->IsActive() )
                        {
                            iUpdateDownload->Start(
                                    TCallBack( CMPXVideoDlMgrIf::UpdateDownloadProgress, this ) );
                        }
                        break;
                    }
                    case EHttpProgCodLoadEnd:
                    {
                        //
                        //  Set the member variable identifying this
                        //  as a COD download and handle the completion
                        //  of the download
                        //
                        iCodDownload = ETrue;

                        HandleDownloadComplete();

                        break;
                    }
                    case EHttpProgMovingContentFile:
                    {
                        //
                        //   Moving Started
                        //
                        MPX_DEBUG( _L("    Moving of file started"));
                        break;
                    }
                    case EHttpProgContentFileMoved:
                    case EHttpProgContentFileMovedAndDestFNChanged:
                    {
                        //
                        //  Move has completed, check error status
                        //
                        CheckForMoveError();

                        break;
                    }
                }

                break;
            }
            case EHttpDlPaused:
            {
                iDownloadState = EPbDlStateDownloadPaused;
                break;
            }
            case EHttpDlCompleted:
            {
                iDownloadState = EPbDlStateDownloadCompleted;

                switch ( aEvent.iProgressState )
                {
                    case EHttpProgNone:
                    {
                        //
                        //  Ignore this event since COD downloads send this
                        //  event after we have already moved the file.
                        //
                        if ( ! iCodDownload )
                        {
                            HandleDownloadComplete();
                        }

                        break;
                    }
                    case EHttpProgMovingContentFile:
                    {
                        //
                        //   Moving Started
                        //
                        MPX_DEBUG( _L("    Moving of file started"));
                        break;
                    }
                    case EHttpProgContentFileMoved:
                    case EHttpProgContentFileMovedAndDestFNChanged:
                    {
                        //
                        //  Move has completed, check error status
                        //
                        CheckForMoveError();

                        break;
                    }
                }

                break;
            }
            case EHttpDlFailed:
            case EHttpDlMediaRemoved:
            case EHttpDlDeleted:
            case EHttpDlDeleting:
            {
                iDownloadState = EPbDlStateDownloadCanceled;

                //
                //  Disconnect from the current download and Download Manager
                //
                iCurrentDl = NULL;
                iDlId = 0;

                break;
            }
            case EHttpDlMoved:
            case EHttpDlCreated:
            case EHttpContentTypeReceived:
            case EHttpDlMediaInserted:
            case EHttpDlPausable:
            case EHttpDlNonPausable:
            case EHttpDlAlreadyRunning:
            default:
                break;
        };

        if ( prevDownloadState != iDownloadState )
        {
            //
            //  Signal the view that the download state has changed
            //
            iController->iMPXPluginObs->HandlePluginEvent(
                MMPXPlaybackPluginObserver::EPDownloadStateChanged,
                iDownloadState,
                KErrNone );
        }
    }
    else
    {
        MPX_DEBUG(_L("CMPXVideoDlMgrIf::HandleDMgrEventL() Message for different Download"));
    }
}

void
CMPXVideoDlMgrIf::DoUpdateDownloadProgress()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::DoUpdateDownloadProgress()"));

    //
    //  Check if the current download is valid before updating
    //
    if ( iCurrentDl )
    {
        iCurrentDl->GetIntAttribute( EDlAttrDownloadedSize, iDownloadProgress );

        MPX_DEBUG(_L("   dlSize = %d, currentSize = %d"), iDlTotalSize, iDownloadProgress );

        //
        //  Update the size once the controller is initialized
        //
        if ( iController->iState->IsInitialized() )
        {
            iController->iMPXPluginObs->HandlePluginEvent(
                MMPXPlaybackPluginObserver::EPDownloadPositionChanged,
                iDownloadProgress,
                KErrNone );

            //
            //  Update the playback engine with the current downloaded size
            //  Helix needs this to handle reading past current file size
            //
            HandleCustomCommand( EMMFROPControllerSetDownloadSize, iDownloadProgress );
        }
    }
}

void
CMPXVideoDlMgrIf::DoHandleOpenComplete()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::DoHandleOpenComplete()"));

    if ( iCurrentDl )
    {
        //
        //  Set the player opened flag so messages can be sent to the
        //  video playback engine
        //
        iPlayerOpened = ETrue;

        //
        //  Do not enable progressive download on the playback engine
        //  if the download isn't active
        //
        if ( iDownloadState == EPbDlStateDownloading || iDownloadState == EPbDlStateDownloadPaused )
        {
            //
            //  Send the download id to Helix to trigger progressive
            //  download mode for the Helix engine
            //
            TInt error = HandleCustomCommand( EMMFROPControllerSetDownloadID, iDlId );

            if ( error == KErrNone )
            {
                iCurrentDl->GetIntAttribute( EDlAttrDownloadedSize, iDownloadProgress );

                //
                //  Update Helix with the current downloaded size
                //  Helix needs this to handle reading past current file size
                //
                error = HandleCustomCommand( EMMFROPControllerSetDownloadSize, iDownloadProgress );
            }

            //
            //  Update download size for DRM protected clips
            //
            MPX_TRAPD( updateError, UpdateDownloadSizeL() );
        }
    }
}

void
CMPXVideoDlMgrIf::CheckForMoveError()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::CheckForMoveError()"));

    TInt32 errorId = KErrNone;
    TInt32 globalErrorId = KErrNone;

    iCurrentDl->GetIntAttribute( EDlAttrErrorId, errorId );
    iCurrentDl->GetIntAttribute( EDlAttrGlobalErrorId, globalErrorId );

    MPX_DEBUG(_L("    Moving complete - error = %d global error = %d"), errorId, globalErrorId );

    //
    //  Move Complete
    //
    iMoveNeeded = EFalse;
    iDownloadState = EPbDlStateNotDownloading;
}

TInt CMPXVideoDlMgrIf::HandleCustomCommand( TUint32 aCommand, TUint32 aCmdValue )
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::HandleCustomCommand()"),
                   _L(" aCommand = %d, aCmdValue = %d)"), aCommand, aCmdValue );

    TUint result = KErrNone;

    //
    //  Block custom commands for progressive download if the player has not been opened
    //
    if ( iPlayerOpened )
    {
        TPckgBuf<TUint> cmdValue( aCmdValue );

        const TMMFMessageDestinationPckg dest( KUidInterfaceMMFROPController );
        TPckgBuf<TMMFMessageDestination> message( dest );

        result = iController->iPlayer->CustomCommandSync( dest, aCommand, cmdValue, KNullDesC8 );

        MPX_DEBUG(_L("    Engine CustomCommand retCode = %d"), result);
    }

    return result;
}

void CMPXVideoDlMgrIf::HandleDownloadComplete()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::HandleDownloadComplete()"));

    iDownloadState = EPbDlStateDownloadCompleted;

    //
    //  Since the download is complete, download should be moved
    //
    if ( iMovePdlFile )
    {
        iMoveNeeded = ETrue;
    }
    else
    {
        //
        //  Disconnect from the current download since move is not required
        //
        iCurrentDl = NULL;
        iDlId = 0;
    }

    //
    //  If the update CIdle object is active, cancel it since the download
    //  is complete and we are updating the values.
    //
    if ( iUpdateDownload->IsActive() )
    {
        iUpdateDownload->Cancel();
    }

    //
    //  Notify the player and the UI view that the download is complete
    //
    HandleCustomCommand( EMMFROPControllerSetDownloadComplete, ETrue );
}

// -------------------------------------------------------------------------------------------------
//  CMPXVideoDlMgrIf::UpdateDownloadProgress
// -------------------------------------------------------------------------------------------------
//
TInt CMPXVideoDlMgrIf::UpdateDownloadProgress( TAny* aPtr )
{
    MPX_DEBUG(_L("CMPXVideoDlMgrIf::UpdateDownloadProgress()"));

    static_cast<CMPXVideoDlMgrIf*>(aPtr)->DoUpdateDownloadProgress();

    return KErrNone;
}

// -------------------------------------------------------------------------------------------------
//  CMPXVideoDlMgrIf::GetPdlStatusL
// -------------------------------------------------------------------------------------------------
//
void CMPXVideoDlMgrIf::GetPdlStatusL( CMPXCommand& aCmd )
{
    MPX_DEBUG(_L("CMPXVideoDlMgrIf::GetPdlStatusL()"));

    if ( iCurrentDl )
    {
        iCurrentDl->GetIntAttribute( EDlAttrDownloadedSize, iDownloadProgress );
    }

    aCmd.SetTObjectValueL<TMPXPlaybackPdDownloadState>( KMPXCommandPlaybackPDState,
                                                        iDownloadState );

    //
    //  If download is complete, ensure that the size is 100%
    //
    if ( iDownloadState == EPbDlStateDownloadCompleted )
    {
        aCmd.SetTObjectValueL<TInt>( KMPXCommandPlaybackPDDownloadedBytes, iDlTotalSize );
    }
    else
    {
        aCmd.SetTObjectValueL<TInt>( KMPXCommandPlaybackPDDownloadedBytes, iDownloadProgress );
    }

    aCmd.SetTObjectValueL<TInt>( KMPXCommandPlaybackPDTotalBytes, iDlTotalSize );
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::CalculateDestinationFileNameL()
// -------------------------------------------------------------------------------------------------
//
void CMPXVideoDlMgrIf::CalculateDestinationFileNameL()
{
    MPX_DEBUG(_L("CMPXVideoDlMgrIf::CalculateDestinationFileNameL()"));

    //
    //  We will try to move the file to the video path of the same
    //  drive where the download manager has saved it
    //
    TParsePtrC origFilePath( iClipName->Des() );

#ifdef RD_MULTIPLE_DRIVE
    DriveInfo::TDriveArray driveArray;
    TInt drive = 0;

    RFs::CharToDrive( origFilePath.Drive()[0], drive );

    User::LeaveIfError( PathInfo::GetFullPath( iDestinationFileName, drive, PathInfo::EVideosPath ) );
#else  //RD_MULTIPLE_DRIVE
    TParsePtrC phoneRoot( PathInfo::PhoneMemoryRootPath() );
    TParsePtrC mmcRoot( PathInfo::MemoryCardRootPath() );

    if ( origFilePath.Drive() == phoneRoot.Drive() )
    {
        iDestinationFileName = phoneRoot.DriveAndPath();
    }
    else
    {
        iDestinationFileName = mmcRoot.DriveAndPath();
    }

    iDestinationFileName += PathInfo::VideosPath();
#endif  //RD_MULTIPLE_DRIVE

    iDestinationFileName += origFilePath.NameAndExt();
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::HandleClose
// -------------------------------------------------------------------------------------------------
//
void CMPXVideoDlMgrIf::HandleClose()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::HandleClose()"));

    //
    //  Before we move any files, the controller in uninitialized.
    //  Set the player opened to false
    //
    iPlayerOpened  = EFalse;

    TInt errorCode = KErrNone;

    //
    //  Download may have already been moved.  Check for a current download.
    //
    if ( iCurrentDl )
    {
        //
        //  Check if the plugin should move the file and a move is needed
        //
        if ( iMoveNeeded )
        {
            MPX_TRAPD(err, CalculateDestinationFileNameL());

            if (err == KErrNone)
            {
                errorCode =
                    iCurrentDl->SetStringAttribute( EDlAttrDestFilename, iDestinationFileName );

                MPX_DEBUG(_L(
                    "CMPXVideoDlMgrIf::MoveDownloadedFile() SetStringAtt err = %d"), errorCode );

                if ( errorCode == KErrNone )
                {
                    errorCode = iCurrentDl->Move();
                }

                MPX_DEBUG(_L("CMPXVideoDlMgrIf::MoveDownloadedFile() Move err = %d"), errorCode );
            }

            MPX_DEBUG(_L("CMPXVideoDlMgrIf::MoveDownloadedFile() Calc Dest Filename err = %d"), err );
        }
        else
        {
            //
            //  Move has been called but we have not completed downloading
            //  the file.  We are going to clear the progressive download
            //  flag and the current download variable
            //
            errorCode = iCurrentDl->SetBoolAttribute( EDlAttrProgressive, EFalse );
            iCurrentDl = NULL;

            MPX_DEBUG(_L(
                "CMPXVideoDlMgrIf::MoveDownloadedFile() Removing PD attr retCode=%d"), errorCode);
        }
    }
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::GetDownloadRatio
// -------------------------------------------------------------------------------------------------
//
TReal CMPXVideoDlMgrIf::GetDownloadRatio()
{
    TReal downloadRatio = (TReal)iDownloadProgress / (TReal)iDlTotalSize;
    MPX_DEBUG(_L("CMPXVideoDlMgrIf::GetDownloadRatio(%f)"), downloadRatio);

    return downloadRatio;
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::IsDownloadPaused
// -------------------------------------------------------------------------------------------------
//
TBool CMPXVideoDlMgrIf::IsDownloadPaused()
{
    TBool paused = ( iDownloadState == EPbDlStateDownloadPaused );

    MPX_DEBUG(_L("CMPXVideoDlMgrIf::GetDownloadRatio(%d)"), paused);

    return paused;
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::ConvertDMgrStatetoMpxState
// -------------------------------------------------------------------------------------------------
//
void CMPXVideoDlMgrIf::ConvertDMgrStatetoMpxState( TInt32 aDMgrState )
{
    MPX_DEBUG(_L("CMPXVideoDlMgrIf::ConvertDMgrStatetoMpxState(%d)"), aDMgrState);

    switch ( aDMgrState )
    {
        case EHttpDlInprogress:
        case EHttpDlCreated:
        {
            iDownloadState = EPbDlStateDownloading;
            break;
        }
        case EHttpDlPaused:
        case EHttpDlNonPausableNetworkLoss:
        {
            iDownloadState = EPbDlStateDownloadPaused;
            break;
        }
        case EHttpDlCompleted:
        {
            iDownloadState = EPbDlStateDownloadCompleted;
            break;
        }
        case EHttpDlFailed:
        {
            iDownloadState = EPbDlStateDownloadError;
            break;
        }
        case EHttpDlDeleted:
        case EHttpDlDeleting:
        {
            iDownloadState = EPbDlStateDownloadCanceled;
            break;
        }
        case EHttpDlMoved:
        case EHttpDlMediaRemoved:
        case EHttpDlMediaInserted:
        case EHttpDlPausable:
        case EHttpDlNonPausable:
        case EHttpDlAlreadyRunning:
        case EHttpDlCancelTransaction:
        default:
        {
            iDownloadState = EPbDlStateNotDownloading;
            break;
        }
    }
}

// -------------------------------------------------------------------------------------------------
//   CMPXVideoDlMgrIf::UpdateDownloadSizeL
// -------------------------------------------------------------------------------------------------
//
void CMPXVideoDlMgrIf::UpdateDownloadSizeL()
{
    MPX_ENTER_EXIT(_L("CMPXVideoDlMgrIf::UpdateDownloadSizeL()"));

    if ( iController->iDrmHelper->IsProtected( iController->iFileHandle ) )
    {
        MPX_DEBUG(_L("CMPXVideoDlMgrIf::UpdateDownloadSizeL() download is DRM protected"));

        ContentAccess::CContent* content =
            ContentAccess::CContent::NewLC( iController->iFileHandle );

        ContentAccess::CData* data = content->OpenContentL( ContentAccess::EPeek );

        CleanupStack::PushL( data );

        TInt drmSize;
        data->DataSizeL( drmSize );

        MPX_DEBUG(_L("CMPXVideoDlMgrIf::UpdateDownloadSizeL()    DlMgr Size = %d, DRM Size = %d"),
            iDlTotalSize, drmSize );

        iDlTotalSize = drmSize;

        CleanupStack::PopAndDestroy( 2 );  // data & content
    }
}

//  EOF
