/*
* Copyright (c) 2007-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:  This Class provides the core functionality to Media Management
*				 SAPI Interafce
*
*/



#include <mclfitemlistmodel.h>
#include <mclfcontentlistingengine.h>
#include <contentlistingfactory.h>
#include <mclfsortingstyle.h>


#include "mgservice.h"
#include "mgpostfilter.h"
#include "mgoperationobserver.h"
#include "mgclfoperationobserver.h"
#include "mgconsts.h"

// Inclusion for thumbnail generation

#include"mgthumbnailgeneration.h"
#include"mgthumbobserver.h"

//Media types.
_LIT8( KMgMusic        ,"Music" );
_LIT8( KMgSound        ,"Sound" );
_LIT8( KMgImage        ,"Image" );
_LIT8( KMgVideo        ,"Video" );
_LIT8( KMgStreamingURL ,"StreamingURL" );


//SortingOrder
_LIT8( KMgDescending,   "Descending" );
//_LIT8( KMgAscending,   "Ascending" );



// -----------------------------------------------------------------------------
// CMgService::NewLC
// Returns the instance of CMgService class.
// -----------------------------------------------------------------------------
EXPORT_C CMgService* CMgService::NewL()
	{
	CMgService* self = new ( ELeave )CMgService();
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	return self;
	}
// -----------------------------------------------------------------------------
// CMgService::~CMgService
// Destructor
// -----------------------------------------------------------------------------

CMgService::~CMgService()
	{
    
        //release filter class
    if(iFilter)
        {
        delete iFilter;
        }
    
        // release sorting style
    if(iSortingStyle)
        {
        delete iSortingStyle;
        }
    
        // release clf observer class
    if(iClfObserver)
        {
        delete iClfObserver;
        }
        
        //release iEngine;
    if(iEngine)
        {
        delete iEngine;
        }
    
        // releasing iTumbnailGeneration
    if(iTumbnailGeneration)
        {
        delete iTumbnailGeneration;
        }

	}




// -----------------------------------------------------------------------------
// CMgService::GetFiles
// This function extracts all media item that match the given arguments
// -----------------------------------------------------------------------------

EXPORT_C void CMgService::GetListL(const TMgServiceRequest& aInParameters,
						  MMgOperationObserver* aServiceObserver)
	{

	//Check if the class is busy or waiting for asynchronous request
	//This has already been verified by SAPI interface class ,still this condition
	//is checked keeping in mind that this class may be called directly by a
	//Series60 application in future
	if( EMgFree == iState )
		{



		if( NULL != aServiceObserver )//Asynchronous request
			{
			// create the instance of CLF list Model for the current request
   	 	    MCLFItemListModel* listModel = iEngine->
   	 	                                   CreateListModelLC( *iClfObserver );


			

		    SendRequestToClfL( aInParameters.iFileType,
		    				   aInParameters.iFilterField,
		    				   aInParameters.iStartVal,
		    				   aInParameters.iEndVal,
		    				   aInParameters.iSortField,
		    				   aInParameters.iOrder,
		    				   listModel );
		    				   
		    CleanupStack::Pop();
		    
		    iTransactionID = aInParameters.iTransactionID;
		    iClfObserver->SetMemberVar( aInParameters.iTransactionID,
		                                aServiceObserver,
										listModel,
										this );
		    

	 
			}
		else
			{
			//Synchronous request handling is currently not supported
			User::Leave( KErrNotSupported );
			}

		}//SAPI State
	else
	    {
        User::Leave( KErrServerBusy ); // busy in previous request
	    }

	}


// -----------------------------------------------------------------------------
// CMgService::Cancel
// Cancel the pending asynchronous request
// -----------------------------------------------------------------------------
EXPORT_C TInt CMgService::CancelL( TUint aTransactionID)
	{
		// call cancel of CLF
		// Right now we are not supporting aTransactionID
		// but in future we have to find the iClfObserver
		// coresponding to this Transaction ID and Call cancel
		// on that observer
	if( EMgBusy == iState )
		{
		if( aTransactionID == iTransactionID )
		    {
		    iClfObserver->CancelL( );
		    Clear();
		    return KErrNone;
	    	}
		}

// Calling cancel of thumbnail
	
	if(aTransactionID != iTransactionID)
	    {
	    return CancelThumbnailReq(aTransactionID);
	    }
	
 		return KErrArgument;
     
	}
// -----------------------------------------------------------------------------
// CMgService::CancelThumbnailReq
// Cancel the pending asynchronous request for thumbnail generation
// -----------------------------------------------------------------------------
TInt  CMgService::CancelThumbnailReq( TUint aTransactionID )
    {
    return iTumbnailGeneration->Cancel(aTransactionID);
    }
// -----------------------------------------------------------------------------
// CMgService::Clear
//	It will clear the set filter metadata field ,registered callback
//	function and sorting fields
// -----------------------------------------------------------------------------

void CMgService::Clear()
	{
       	iFilter->Clear();
		iState = EMgFree;
		iTransactionID = 0;
	}




// -----------------------------------------------------------------------------
// CMgService::State
// It will return the state of service class.
// return EMgFree if it is free and ready to accept
// the another request else EMgBusy
// -----------------------------------------------------------------------------
EXPORT_C const TMgState& CMgService::State() const
	{
    return iState;
	}




// -----------------------------------------------------------------------------
// CMgService::SetSortingField
// It will set the metadata field on which the result
// should be sorted.
// Leave with KErrArgument if aSortField is not valid.
// -----------------------------------------------------------------------------

void CMgService::SetSortingFieldL(const TDesC8& aSortField ,
								  const TDesC8&  aOrder ,
								  const RArray<TInt>& aMediaTypes,
								  MCLFItemListModel* alistModel )
	{

	// Default sorting as per file name
	TCLFDefaultFieldId metaDataId = ECLFFieldIdFileName;
    TCLFItemDataType  metaDataType = ECLFItemDataTypeDesC;

    //Check If the aSortField is not NULL Descriptor i.e.
    // sorting metadata is specified

   	if( 0 != aSortField.CompareF( KNullDesC8 ) )
   		{

    	GetMetaDataIdAndType( aSortField,
    						  metaDataId,
    						  metaDataType,
    						  aMediaTypes );

	 	if( ECLFFieldIdNull == metaDataId ) // check the return type
	 	    {
	 	    // The given Sort Field  is not supported by Media Management SAPI
	 		User::Leave( KErrArgument );
	 		}
    	}

	iSortingStyle->ResetL();


 	//Set the field on which sorting has to perform
	iSortingStyle->AddFieldL( metaDataId );

	// Set the sorting field data type
	iSortingStyle->SetSortingDataType( metaDataType );

	if( 0 == aOrder.CompareF( KMgDescending ) )
		{
		iSortingStyle->SetOrdering( ECLFOrderingDescending  );
		}
	else if( 0 == aOrder.CompareF( KMgAscending) )
		{
		iSortingStyle->SetOrdering( ECLFOrderingAscending );
		}
	else
		{
		User::Leave( KErrArgument );
		}

	//Items with undefined fields are placed after items with defined fields
	iSortingStyle->SetUndefinedItemPosition( ECLFSortingStyleUndefinedEnd );

	// set sorting style in CLF.
	alistModel->SetSortingStyle( iSortingStyle );


	}


// -----------------------------------------------------------------------------
// CPostFilter::SetFilterMetaData
// Method to set the filter metadata
// -----------------------------------------------------------------------------
void CMgService::SetFilterMetaDataL( const TDesC8& aFilterField,
									 const TDesC& aStartVal,
									 const TDesC& aEndVal,
									 const RArray<TInt>& aMediaTypes, 
									 MCLFItemListModel* alistModel )
	{
	TCLFDefaultFieldId metaDataId;
    TCLFItemDataType  metaDataType;
    


    //Check If the Filter Meta Data is NULL Descriptor, if so
    // no filtration will be performed
    if( 0 == aFilterField.CompareF( KNullDesC8 ) )
    	{
       	metaDataId = ECLFFieldIdNull;
       	metaDataType = ECLFItemDataTypeDesC;	// Blank Descriptor
        iFilter->SetFilterMetaData( metaDataId, metaDataType );
   		}
    else
    	{
    	GetMetaDataIdAndType( aFilterField,
    						  metaDataId,
    						  metaDataType,
    						  aMediaTypes);

	 	if( ECLFFieldIdNull == metaDataId )
	 		{
	 		// The given metaData is not supported by Media Management SAPI
	 		User::Leave( KErrArgument );
	 		}


	 	iFilter->SetFilterMetaData( metaDataId, metaDataType );

       	// set filter value of CLF
	    iFilter->SetFilterValueL( aStartVal,aEndVal );

		// Set Post Filter in CLF
	    alistModel->SetPostFilter( iFilter );

	 	}

  	}


// -----------------------------------------------------------------------------
// CMgService::ConstuctL
// It will intialize the underlying CLF(Content Listing Framework)
// framework classes and CPostFilter class.
// -----------------------------------------------------------------------------
void CMgService::ConstructL()
	{
	// create the instance of CLF engine and store it in member data.
	iEngine = ContentListingFactory::NewContentListingEngineLC();
    CleanupStack::Pop();


    // create the instance of CPostFilter and store it in member data
    iFilter = CPostFilter::NewL();

    // Get the sorting style from CLF
	iSortingStyle = ContentListingFactory::NewSortingStyleLC();
 	CleanupStack::Pop();

 	//create the instance of clf observer
 	iClfObserver = CClfOperationObserver::NewL();
 	
 	// creates instance for async requestmanager for thumbnail
 	iTumbnailGeneration = CThumbnailGeneration::NewL();
 	
	}




// -----------------------------------------------------------------------------
// CMgService::CMgService
// Constructor
// -----------------------------------------------------------------------------
CMgService::CMgService()
          : iState( EMgFree ),
            iEngine( NULL ),
			iFilter( NULL ),
			iSortingStyle( NULL ),
			iClfObserver( NULL ),
			iTransactionID( 0 ),
			iTumbnailGeneration(NULL)
	{

	}



// -----------------------------------------------------------------------------
// CMgService::SetMediaTypeL
// It will convert the aFiletype string into
// equivalent Mediatype ID and Fill the Media Type Array
// if it is not valid then return KErrNotSupported
// -----------------------------------------------------------------------------
void CMgService::SetMediaTypeL (const TDesC8& aFileType,
								RArray<TInt>& aMediaType)
	{

	if( 0 == aFileType.CompareF( KMgMusic ) )
 		{
 	 	aMediaType.AppendL( ECLFMediaTypeMusic );
 	 	}
	else if( 0 == aFileType.CompareF( KMgSound ) )
 	 	{
 	 	aMediaType.AppendL( ECLFMediaTypeSound );
 	 	}

 	else if( 0 == aFileType.CompareF( KMgImage ) )
 	 	{
 	 	aMediaType.AppendL( ECLFMediaTypeImage );
 	 	}

 	else if( 0 == aFileType.CompareF( KMgVideo ) )
 	 	{
 	 	aMediaType.AppendL( ECLFMediaTypeVideo );
 	 	}

 	else if( 0 == aFileType.CompareF( KMgStreamingURL ) )
 	 	{
 	 	aMediaType.AppendL( ECLFMediaTypeStreamingURL );
 	 	}
 	else
 	 	{
 	 	User::Leave ( KErrArgument ); // Media Type Not suuported
 	 	}

   	}





// -----------------------------------------------------------------------------
// CMgService::SendRequestToCLF
// This Function will pass the request to CLF frame work for required media type.
// return KErrArgument if the FilterMetaData is not Supported
// return KErrArgument if the Start Value is not Supported
// return KErrArgument  if the End Value is mot supported
// return KErrNone if sucessful
// -----------------------------------------------------------------------------

void CMgService::SendRequestToClfL( const TDesC8& aFileType,
								    const TDesC8& aFilterField,
                				    const TDesC&  aStartVal,
                				    const TDesC&  aEndVal,
                				    const TDesC8& aSortField,
                				    const TDesC8&  aOrder,
                				    MCLFItemListModel* alistModel )
    {



	RArray<TInt> mediaTypes;
	CleanupClosePushL( mediaTypes );

	//check if it is a valid file type or not
	SetMediaTypeL( aFileType,mediaTypes );


	//set wanted media type in CLF
	alistModel->SetWantedMediaTypesL( mediaTypes.Array() );


	// Set Filter Meta Data  and Value
    SetFilterMetaDataL( aFilterField,aStartVal,aEndVal,mediaTypes,alistModel);
    


    // call set sorting field of CLF
    SetSortingFieldL( aSortField,aOrder,mediaTypes,alistModel );
   
 	// set the state = Busy
 	// till this request is complete
 	//which indicates no further request will be taken
 	iState = EMgBusy;

	//asynchronous call to CLF ECLFRefreshAll
 	alistModel->RefreshL();


 	CleanupStack::PopAndDestroy( &mediaTypes );


	}



// -----------------------------------------------------------------------------
// CMgService::GetMetaDataIdAndType
// It will convert the aFilterData string into equivalent Metadata ID and Type
// which is recognized by underlying framework.(i.e CLF)
// -----------------------------------------------------------------------------
void CMgService::GetMetaDataIdAndType(const TDesC8& aMetaData,
									  TCLFDefaultFieldId&  aMetaDataId,
          							  TCLFItemDataType& aMetaDataType,
          							  const RArray<TInt> &aMediaTypes)
	{
    //File name field
    if( 0 == aMetaData.CompareF( KMgFileName ))
    	{
    	aMetaDataType = ECLFItemDataTypeDesC;
    	aMetaDataId = ECLFFieldIdFileName;
    	}



    // File Extension
    else if( 0 == aMetaData.CompareF( KMgFileExtension ))
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId = ECLFFieldIdFileExtension;
    	}


    // File path field
    else if( 0 == aMetaData.CompareF( KMgPath ))
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId = ECLFFieldIdPath;
    	}


    // File drive field
    else if( 0 == aMetaData.CompareF( KMgDrive ))
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId = ECLFFieldIdDrive;
	    }


    // File size field
    else if( 0 == aMetaData.CompareF( KMgFileSize ))
       	{
   		aMetaDataType = ECLFItemDataTypeTInt32;
   		aMetaDataId = ECLFFieldIdFileSize;
       	}



    // File date field
    else if( 0 == aMetaData.CompareF( KMgFileDate ))
    	{
		aMetaDataType = ECLFItemDataTypeTTime;
		aMetaDataId = ECLFFieldIdFileDate;
    	}



    // Mime type field
    else if( 0 == aMetaData.CompareF( KMgMimeType ))
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId = ECLFFieldIdMimeType;
    	}


    // Full name and path of the file
    else if( 0 == aMetaData.CompareF( KMgFileNameAndPath ))
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
	   	aMetaDataId = ECLFFieldIdFileNameAndPath;
    	}

    // Music file song name: and also check If the File type is Music File
    else if( (0 == aMetaData.CompareF( KMgSongName )) &&( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeMusic )) )
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
	    aMetaDataId = ECLFFieldIdSongName;

    	}
   	// Music file artist
    else if( (0 == aMetaData.CompareF( KMgArtist )) &&( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeMusic )) )
    		 
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId =  ECLFFieldIdArtist;
    	}


    // Music file album
    else if((0 == aMetaData.CompareF( KMgAlbum )) &&
    		( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeMusic ) ) )
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId = ECLFFieldIdAlbum;
    	}



    // Music file genre
    else if((0==aMetaData.CompareF( KMgGenre))&&
    	( KErrNotFound != aMediaTypes.Find(ECLFMediaTypeMusic) ) )
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
		aMetaDataId =  ECLFFieldIdGenre;
    	}



    // Music file track number
    else if((0 == aMetaData.CompareF( KMgTrackNumber ))&&
    	( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeMusic ) ) )
    	{
		aMetaDataType = ECLFItemDataTypeTInt32;
		aMetaDataId =  ECLFFieldIdTrackNumber;
    	}



    // Music file composer
   	else if( (0 == aMetaData.CompareF( KMgComposer )) &&
   		( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeMusic ) ) )
    	{
		aMetaDataType = ECLFItemDataTypeDesC;
	    aMetaDataId =  ECLFFieldIdComposer;
    	}

    // Ram link first URL
    else if( (0 == aMetaData.CompareF( KMgLinkFirstURL )) &&
    	 ( KErrNotFound != aMediaTypes.Find( ECLFMediaTypeStreamingURL ) ) )
    	{
	    aMetaDataType = ECLFItemDataTypeDesC;
	    aMetaDataId =  ECLFFieldIdRamLinkFirstURL;
    	}

    else
    	{
		aMetaDataType = ECLFItemDataTypeTInt32;
		aMetaDataId = ECLFFieldIdNull;
     	}


	}
// -----------------------------------------------------------------------------
// CMgService::GetThumbnailL
// It generates the thumbnail for media type (image and video )
// -----------------------------------------------------------------------------

EXPORT_C void CMgService::GetThumbnailL(MThumbnailObserver* aThumbnailObserver, TDesC & aUrl, TInt32 aTransactionID,
        TInt aHeight, TInt aWidth)
    {
    // Calling getThumbnail Api
    iTumbnailGeneration->GetThumbnailL(aThumbnailObserver,aTransactionID,aUrl,aHeight,aWidth );
    
    }
