/*
* Copyright (c) 2005-2006 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:  mmsregisteredapplications implementation
*
*/


   
// INCLUDE FILES   
#include <centralrepository.h>
#include <msvids.h>

// USERINCLUDE FILES
#include "mmsregisteredapplications.h"
#include "mmssettings.h"
#include "mmsdebuglogging.h"
#include "MmsEngineDomainCRKeys.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES  

// CONSTANTS
const TInt KMmsApplicationIdArrayGranularity = 4;
const TInt KMmsApplicationNameDefaultLength = 64; // a reasonable guess for the length

// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

// ============================== LOCAL FUNCTIONS ==============================

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

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

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::CMmsRegisteredApplications
//
// -----------------------------------------------------------------------------
//
CMmsRegisteredApplications::CMmsRegisteredApplications()
    {
    }

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::~CMmsRegisteredApplications
//
// -----------------------------------------------------------------------------
//
CMmsRegisteredApplications::~CMmsRegisteredApplications()
    {
    LOG(_L("~CMmsRegisteredApplications"));
    delete iUserFriendlyName;
    delete iRepository;
    delete iAppIdArray;  
    }

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::ConstructL
//
// -----------------------------------------------------------------------------
//
void CMmsRegisteredApplications::ConstructL()
    {
   
    iAppIdArray = new ( ELeave )CDesCArrayFlat( KMmsApplicationIdArrayGranularity );

    iRepository = CRepository::NewL( KCRUidMMSApplicationRegistrations ); 
    // The length may change later if the names are long.
    iUserFriendlyName = HBufC::NewL( KMmsApplicationNameDefaultLength );
    }

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::LoadRegisteredApplicationsL
//
// -----------------------------------------------------------------------------
//

EXPORT_C void CMmsRegisteredApplications::LoadRegisteredApplicationsL()
    {
    LOG(_L("CMmsRegisteredApplications::LoadRegisteredApplicationsL"));
    iAppIdArray->Reset();
    TInt count = 0;
    TInt error = iRepository->Get( KMmsEngineNbrOfRegisteredApplications, count );
    if ( error == KErrNotFound )
        {
        iRepository->Set( KMmsEngineNbrOfRegisteredApplications, 0 );   
        }
    
    // KMaxUnicodeStringLength is the maximum length of string in repository -
    // The strings will always fit into the bugger.
    HBufC* buffer = HBufC::NewL( NCentralRepositoryConstants::KMaxUnicodeStringLength );
    CleanupStack::PushL( buffer );
    TPtr ptr = buffer->Des();
    // We use the same buffer for reading everything - AppendL will always allocate
    // a new buffer anyway. No need to keep allocating a new read buffer every time
    for( TInt i = 0; i < count; i++ )
        {
        error = iRepository->Get( KMmsEngineRegisteredApplicationsArrayBase + i, ptr ) ;
        if ( error == KErrNone )
            { 
            iAppIdArray->AppendL( ptr );
            }
        else
            {
            LOG3(_L("- Loading registered appid array item %d returned error %d"), i, error );
            }
        }   
    CleanupStack::PopAndDestroy( buffer );
    buffer = NULL;
    
    }


// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::NumberOfRegisteredApplicationsL
//
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMmsRegisteredApplications::NumberOfRegisteredApplicationsL() const
    {
    return iAppIdArray->MdcaCount();
    }
    
// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::RegisteredL
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CMmsRegisteredApplications::RegisteredL( const TDesC& aApplicationId )
    {
    TInt index = -1;
    return Registered( aApplicationId, index );
    }  


    
// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::RegisterL
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMmsRegisteredApplications::RegisterL( const TDesC& aApplicationId )
    {
    return RegisterL( aApplicationId, TPtrC() );
    }

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::UnregisterL
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMmsRegisteredApplications::UnregisterL( const TDesC& aApplicationId )
    {
    TInt index = 0;
    if ( !Registered( aApplicationId, index ) )
        {
        return KErrNone;            
        }
    LOG2(_L("CMmsRegisteredApplications::Unregister: array[%d]"), index );
    
    TInt error = KErrNone;
    
    // if item is not last one in the array. move the last item here.
    TInt lastIndex = iAppIdArray->MdcaCount() - 1;
    if ( index != lastIndex )
        {
        HBufC* buffer = HBufC::NewL( NCentralRepositoryConstants::KMaxUnicodeStringLength );
        CleanupStack::PushL( buffer );
        TPtr ptr = buffer->Des();
    
        error = iRepository->Get(
            KMmsEngineRegisteredApplicationsArrayBase + lastIndex, ptr );
        if ( error == KErrNone )
            {
            error = iRepository->Set(
                KMmsEngineRegisteredApplicationsArrayBase + index, ptr );
            }
        // local array has to follow the same order
        if ( error == KErrNone )
            {
            // delete the old user friendly name.
            // The new one will replace it in a moment, but we make sure 
            // there is no incorrect name left in place in case InsertL
            // leaves because of lack of memory.
            iRepository->Delete( KMmsEngineApplicationNameArrayBase + index );
            // array index should be safe
            iAppIdArray->InsertL( index, ptr );
            iAppIdArray->Delete( index + 1 ); 
            }
        if ( error == KErrNone )
            {
            error = iRepository->Get( KMmsEngineApplicationNameArrayBase + lastIndex, ptr );
            if ( error == KErrNone && ptr.Length() > 0 )
                {
                error = iRepository->Set(
                    KMmsEngineApplicationNameArrayBase + index, ptr );
                }
            // The setting of the name must not prevent final cleanup    
            error = KErrNone;    
            }
            
        CleanupStack::PopAndDestroy( buffer );
        buffer = NULL;
        }
    // delete the last item from the arrays
    if ( error == KErrNone )
        {
        error = iRepository->Delete( KMmsEngineRegisteredApplicationsArrayBase + lastIndex );
        if ( error == KErrNone )
            {
            iAppIdArray->Delete( lastIndex );
            iAppIdArray->Compress();
            SaveCount();        
            }
        // The user friendly name of the last item is deleted in any case
        // We are trying to make sure there are no friendly names pointing
        // to incorrect application ids left over.
        // The name can be fixed by trying to register the application again
        // Even if the application is already registered, the user friedly name
        // can be changed by registering the same application id again. 
        iRepository->Delete( KMmsEngineApplicationNameArrayBase + lastIndex );
        }
    return error;       
  
    }
    
// -----------------------------------------------------------------------------
// 
// -----------------------------------------------------------------------------
//
EXPORT_C const CDesCArray& CMmsRegisteredApplications::RegisteredApplicationList() const
    {
    return *iAppIdArray; 
    }
    
// -----------------------------------------------------------------------------
// 
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CMmsRegisteredApplications::RegisterL(
    const TDesC& aApplicationId,
    const TDesC& aUserFriendlyName )
    {
    TInt error = KErrNone;
    TInt index = -1;
    if ( aApplicationId.Length() > NCentralRepositoryConstants::KMaxUnicodeStringLength )
        {
        // The application id is too long, it cannot be registerd
        return KErrArgument;
        }
    if ( aUserFriendlyName.Length() > NCentralRepositoryConstants::KMaxUnicodeStringLength )
        {
        return KErrArgument;
        }
        
    if ( !Registered( aApplicationId, index ) )
        {
        // add new app id to last item in the array.
        index = iAppIdArray->MdcaCount();
        error = iRepository->Create(
            KMmsEngineRegisteredApplicationsArrayBase + index, aApplicationId );
        if ( error == KErrNone || error == KErrAlreadyExists )
            {
            // We should not get "already exists" unless someone has 
            // edited the registry behind our back...
            error = KErrNone;
            // The index now points to the newly created application id
            iAppIdArray->AppendL( aApplicationId );
            // update count in cenrep.
            SaveCount();
            }
        }
        
    // If index == -1 at this point, the registeration has failed.    
    if ( aUserFriendlyName.Length() > 0 && error == KErrNone && index != -1 )
        {
        error = iRepository->Set( KMmsEngineApplicationNameArrayBase + index,
            aUserFriendlyName );
        if ( error == KErrAlreadyExists )
            {
            error = KErrNone;
            }
        }
        
    return error;
    }
    
// -----------------------------------------------------------------------------
// 
// -----------------------------------------------------------------------------
//
EXPORT_C TPtrC CMmsRegisteredApplications::UserFriendlyName( const TDesC& aApplicationId )
    {
    // This is a "best effort" function. 
    // If memory runs out or some other error occurs, an empty string is returned
    TInt index = -1;
    if ( !Registered( aApplicationId, index ) )
        {
        return TPtrC();
        }
    
    TInt error = KErrNone;
    if ( !iUserFriendlyName )
        {
        // iUserFriendlyName may be NULL only if we have ran out of memory earlier
        TRAP( error, iUserFriendlyName = HBufC::NewL( KMmsApplicationNameDefaultLength ) );
        }
    if ( error != KErrNone )
        {
        // If no memory, return empty string
        return TPtrC();
        }
        
    TPtr ptr = iUserFriendlyName->Des();
    TInt actualLength = 0;

    error = iRepository->Get( KMmsEngineApplicationNameArrayBase + index, ptr, actualLength );
    if ( error == KErrOverflow )
        {
        delete iUserFriendlyName;
        iUserFriendlyName = NULL;
        TRAP( error,
            {
            iUserFriendlyName = HBufC::NewL( actualLength );
            ptr.Set( iUserFriendlyName->Des() ); 
            error = iRepository->Get( KMmsEngineApplicationNameArrayBase + index, ptr );
            });
        }
    if ( error == KErrNone )
        {
        return iUserFriendlyName->Des();
        }
    return TPtrC();
        
    }

    
// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::Registered
// -----------------------------------------------------------------------------
//
TBool CMmsRegisteredApplications::Registered( const TDesC& aApplicationId, TInt& aIndex )
    {
    aIndex = -1; 
    TInt count = iAppIdArray->MdcaCount();
    for( TInt i = 0; i < count && aIndex == -1; i++ )
        {
        TPtrC16 ptr = iAppIdArray->MdcaPoint( i );
        if ( ptr.Compare( aApplicationId ) == 0 )
            {
            aIndex = i; 
            }
        }
    return ( aIndex != -1 );        
    } 

// -----------------------------------------------------------------------------
// CMmsRegisteredApplications::SaveCount
// -----------------------------------------------------------------------------
//
TInt CMmsRegisteredApplications::SaveCount()
    {
    TInt count = iAppIdArray->MdcaCount();
    // Set also creates a new key if it does not exist
    TInt error = iRepository->Set( KMmsEngineNbrOfRegisteredApplications, count );
    if( error != KErrNone )
        {
        LOG3( _L("-ERROR saving appid count %d: %d"), KMmsEngineNbrOfRegisteredApplications, error );
        }
    return error;   
    }
    
    
// =========================== OTHER EXPORTED FUNCTIONS ========================

//  End of File  
