/*
* Copyright (c) 2005 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:  
*       Recognizes MIME type for a file.
*       Maps MIME types to media types.
*       Creates media info object for a file.
*
*/




// INCLUDE FILES
#include <e32std.h>
#include <e32base.h> // CBase
#include <apmstd.h>  // TDataType
#include <f32file.h> // RFs, RFile
#include <apgcli.h>  // RApaLsSession
#include <apmrec.h>

#include <coemain.h>
#include <barsread.h>
#include <bautils.h>
#include <data_caging_path_literals.hrh> 

#include <DRMHelper.h>
#include <fileprotectionresolver.h>

// Features
#include <featmgr.h>    
#include <bldvariant.hrh>
#include <messagingvariant.hrh>

// Resources
#include <MsgMimeToMediaMapping.rsg>

#include "MsgMedia.hrh"
#include "MsgMediaResolver.h"
#include "MsgMediaTypeGroup.h"
#include "MsgMediaPanic.h"
#include "MsgMediaInfo.h"
#include "MsgImageInfo.h"
#include "MsgAudioInfo.h"
#include "MsgTextInfo.h"
#include "MsgVideoInfo.h"
#include "MsgMimeTypes.h"

// LOCAL CONSTANTS AND MACROS
// Unrecognised media type is 'x-epoc/x-app0'. 
// Media type 'x-epoc/x-appN', in which N>0 may also be possible. 
// N stands for Uid of the app handling the content on the Symbian OS platform 
_LIT8( KMmsSymbianInternalPattern, "x-epoc/x-app0");

_LIT( KMsgMediaResourceFileName, "MsgMimeToMediaMapping.rsc" ); 

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// Factory
// -----------------------------------------------------------------------------
//
EXPORT_C CMsgMediaResolver* CMsgMediaResolver::NewLC()
    {
    CMsgMediaResolver* self = new ( ELeave ) CMsgMediaResolver();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }
         
// -----------------------------------------------------------------------------
// Factory
// -----------------------------------------------------------------------------
//
EXPORT_C CMsgMediaResolver* CMsgMediaResolver::NewL()
    {
    CMsgMediaResolver* self = NewLC();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// C++ constructor
// -----------------------------------------------------------------------------
//
CMsgMediaResolver::CMsgMediaResolver() :
    iRecognizeCharSet( ETrue ) // CharSet recognition is on by default.
    {
    }

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
CMsgMediaResolver::~CMsgMediaResolver()
    {
    iFs.Close();
    iApaLsSession.Close();
    iMimeGroupArray.ResetAndDestroy();
    delete iFileProt;
    delete iDRMHelper;
    }

// -----------------------------------------------------------------------------
// 2nd phase constructor
// -----------------------------------------------------------------------------
//
void CMsgMediaResolver::ConstructL()
    {
    // Create own shared file server session.
    User::LeaveIfError( iFs.Connect() );
    User::LeaveIfError( iFs.ShareProtected() );
    User::LeaveIfError( iApaLsSession.Connect() );
    
    iDRMHelper = CDRMHelper::NewL();
    iFileProt = CFileProtectionResolver::NewL( iFs );
    CreateMediaTypeGroupsL();
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::CreateMediaTypeGroupsL
// -----------------------------------------------------------------------------
//
void CMsgMediaResolver::CreateMediaTypeGroupsL()
    {
    	TFileName fileName;	
		TFindFile finder( iFs );
		//Search Y->A then Z:
		TInt err = finder.FindByDir( KMsgMediaResourceFileName, KDC_RESOURCE_FILES_DIR );
		if(err == KErrNone)
		{
	    	fileName = finder.File();
		    RResourceFile resourceFile;
		    resourceFile.OpenL( iFs, fileName );
		    CleanupClosePushL( resourceFile );
		    resourceFile.ConfirmSignatureL( 0 );

		    HBufC8* dataBuffer = resourceFile.AllocReadLC( R_MSG_MEDIAGROUPS );

		    TResourceReader reader;
		    reader.SetBuffer( dataBuffer );

		    TInt numMediaGroups( reader.ReadInt16() );

		    for ( TInt i = 0; i < numMediaGroups; i++ )
		        {
		        CMsgMediaTypeGroup* mimeTypeGroup = CMsgMediaTypeGroup::NewLC( reader );
		        iMimeGroupArray.AppendL( mimeTypeGroup );
		        CleanupStack::Pop( mimeTypeGroup );
		        }

		    CleanupStack::PopAndDestroy( 2, &resourceFile ); // resourceFile.Close, dataBuffer
		}
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::FileHandleL
// -----------------------------------------------------------------------------
//
EXPORT_C RFile CMsgMediaResolver::FileHandleL( const TDesC& aFileName )
    {
    RFile file;
    User::LeaveIfError( file.Open( iFs, aFileName, EFileRead | EFileShareReadersOnly ) );
    return file;
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::RecognizeL
// -----------------------------------------------------------------------------
//
EXPORT_C void CMsgMediaResolver::RecognizeL( RFile& aFile,
                                             TDataType& aMimeType )
    {
    TFileName* name = new ( ELeave ) TFileName;
    CleanupStack::PushL( name );
    User::LeaveIfError( aFile.Name( *name ) );
    TParsePtrC parse( *name );
    if ( parse.Ext().CompareF( KMsgExtSmil1 ) == 0 ||
         parse.Ext().CompareF( KMsgExtSmil2 ) == 0 ||
         parse.Ext().CompareF( KMsgExtSmil3 ) == 0 )
        {
        aMimeType = KMsgMimeSmil();
        }
    else
        {
        TDataRecognitionResult dataType;
        TInt err = iApaLsSession.RecognizeData( aFile, dataType );
        // Unrecognised content and no leaves in recogniser plugins
        // return err = KErrNone & dataType = 'x-epoc/x-app0'.
        // Unrecognised content and a leave in recogniser plugins
        // return err = <leave-code-in-recogniser>        
        if (    err
            ||  dataType.iDataType.Des8().Length() == 0
            ||  !dataType.iDataType.Des8().CompareF( KMmsSymbianInternalPattern ) )
            {
            // Not recognized
            aMimeType = KMsgMimeUnknown();
            }
        else
            {
            aMimeType = dataType.iDataType;
            }
        }
    CleanupStack::PopAndDestroy( name );
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::MediaType
// -----------------------------------------------------------------------------
//
EXPORT_C TMsgMediaType CMsgMediaResolver::MediaType( const TDesC8& aMimeType ) const
    {
    TInt mimeGroupCount( iMimeGroupArray.Count() );
    for ( TInt i = 0; i < mimeGroupCount; i++ )
        {
        CMsgMediaTypeGroup* group = iMimeGroupArray[ i ];
        if ( group->HasMimeType( aMimeType ) )
            {
            return group->MediaType();
            }
        }
    return EMsgMediaUnknown;
    }
    
// -----------------------------------------------------------------------------
// CMsgMediaResolver::MediaInfoL
// -----------------------------------------------------------------------------
//
EXPORT_C CMsgMediaInfo* CMsgMediaResolver::CreateMediaInfoL( RFile& aFile )
    {
    TDataType* mimeType = new ( ELeave ) TDataType;
    CleanupStack::PushL( mimeType );
    RecognizeL( aFile, *mimeType );
    CMsgMediaInfo* info = DoCreateMediaInfoL( aFile, *mimeType );
    CleanupStack::PopAndDestroy( mimeType );
    return info;
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::MediaInfoL
// -----------------------------------------------------------------------------
//
EXPORT_C CMsgMediaInfo* CMsgMediaResolver::CreateMediaInfoL( RFile& aFile, TDataType& aMimeType )
    {
    return DoCreateMediaInfoL( aFile, aMimeType );
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::ParseInfoDetailsL
// -----------------------------------------------------------------------------
//
EXPORT_C void CMsgMediaResolver::ParseInfoDetailsL( CMsgMediaInfo* aInfo, RFile& aFile )
    {
    aInfo->ParseInfoDetailsL( aFile, *iDRMHelper, *this );
     if ( iWait.IsStarted() )
        {
        // Stop active wait.
        iWait.AsyncStop();
        }
    // Start active wait
    iWait.Start();
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::DoCreateMediaInfoL
// -----------------------------------------------------------------------------
//
CMsgMediaInfo* CMsgMediaResolver::DoCreateMediaInfoL( RFile& aFile, 
                                                      TDataType& aMimeType )
    {
    CMsgMediaInfo* mediaInfo = NULL;
    TMsgMediaType mediaType = MediaType( aMimeType.Des8() );
    switch ( mediaType )
        {
        case EMsgMediaText:
            {
            mediaInfo = CMsgTextInfo::NewL( aFile, aMimeType, iFs );
            if ( !iRecognizeCharSet )
                {
                // Suppress charset recognition.
                static_cast< CMsgTextInfo* >( mediaInfo )->SetCharacterSet( 0 );
                }
            break;
            }
        case EMsgMediaImage:
            {
            mediaInfo = CMsgImageInfo::NewL( aFile, aMimeType );
            break;
            }
        case EMsgMediaVideo:
            {
            mediaInfo = CMsgVideoInfo::NewL( aFile, aMimeType );
            break;
            }
        case EMsgMediaAudio:
            {
            mediaInfo = CMsgAudioInfo::NewL( aFile, aMimeType );
            break;
            }
        case EMsgMediaUnknown:
        default:
            {
            mediaInfo = CMsgMediaInfo::NewL( aFile, aMimeType, mediaType );
            break;
            }
        }
    
    CleanupStack::PushL( mediaInfo );

    TUid appUid( KNullUid );
    // Ignore possible error.
    TInt err = iApaLsSession.AppForDataType( aMimeType, appUid );
    mediaInfo->SetHandlerApplicationUid( appUid );

    HBufC8* drmUri = NULL;
    TInt protection = iFileProt->ProtectionStatusL( aFile, aMimeType, drmUri );
    mediaInfo->SetProtection( protection );
    mediaInfo->SetDRMContentURI( drmUri ); // ownership transferred

    CleanupStack::Pop( mediaInfo );
        
    return mediaInfo;
    }

// -----------------------------------------------------------------------------
// CMsgMediaResolver::MediaInfoParsed
// -----------------------------------------------------------------------------
//
void CMsgMediaResolver::MediaInfoParsed()
    {
    if ( iWait.IsStarted() )
        {
        // Stop active wait.
        iWait.AsyncStop();
        }
    }

//  End of File  
