/*
* Copyright (c) 2005-2007 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:  A command for setting ringing tone.
*
*/


// INCLUDE FILES
#include "CPbk2SetToneCmd.h"

#include <MPbk2CommandObserver.h>
#include <CVPbkContactManager.h>
#include <MPbk2ContactUiControl.h>
#include <TVPbkFieldTypeMapping.h>
#include <MVPbkContactLinkArray.h>
#include <MVPbkContactFieldTextData.h>
#include <MVPbkStoreContactField.h>
#include <MVPbkStoreContact.h>
#include <CPbk2ContactRelocator.h>
#include <TPbk2StoreContactAnalyzer.h>
#include <MVPbkContactOperationBase.h>
#include <CPbk2PresentationContact.h>
#include <CPbk2FieldPropertyArray.h>
#include <CPbk2PresentationContactFieldCollection.h>
#include <CPbk2FieldFocusHelper.h>
#include <MPbk2ApplicationServices.h>
#include <MPbk2AppUi.h>
#include "CPbk2RingingToneFetch.h"

#include <Pbk2UIControls.rsg>
#include <coemain.h>

#include <Pbk2Debug.h>

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

namespace 
    {    
    #ifdef _DEBUG
    	enum TPanicCode
    	    {
    	    EPanicLogic_ReadFieldTypeL,
    	    EPanicLogic_ContactCommitCompelete,
    	    EPanicPreCond_RelocationProcessCompleteL
    	    };

    	void Panic(TInt aReason)
    	    {
    	    _LIT(KPanicText, "CPbk2SetToneCmd");
    	    User::Panic(KPanicText, aReason);
    	    }
    #endif // _DEBUG	    
    }

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

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::CPbk2SetToneCmd
// C++ default constructor can NOT contain any code, that
// might leave.
// --------------------------------------------------------------------------
//
CPbk2SetToneCmd::CPbk2SetToneCmd(
        MPbk2ContactUiControl& aUiControl ) :  
    CPbk2SetToneBase( aUiControl )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::~CPbk2SetToneCmd
// --------------------------------------------------------------------------
//
CPbk2SetToneCmd::~CPbk2SetToneCmd()
    {
    delete iFieldFocusHelper;
    iFieldFocusHelper = NULL;
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::NewL
// Two-phased constructor.
// --------------------------------------------------------------------------
//
CPbk2SetToneCmd* CPbk2SetToneCmd::NewL(
        MPbk2ContactUiControl& aUiControl)
    {
    CPbk2SetToneCmd* self = 
        new( ELeave ) CPbk2SetToneCmd( aUiControl );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::ConstructL
// Symbian 2nd phase constructor can leave.
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ConstructL()
    {
    BaseConstructL();
    iFieldFocusHelper = CPbk2FieldFocusHelper::NewL( 
        *iUiControl,
        Phonebook2::Pbk2AppUi()->ApplicationServices().FieldProperties() );
    }
	
// --------------------------------------------------------------------------
// CPbk2SetToneCmd::ContactRelocatedL
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ContactRelocatedL(
        MVPbkStoreContact* aRelocatedContact)
    {
    // Takes ownership of the aRelocatedContact
    delete iStoreContact;
    iStoreContact = aRelocatedContact;
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::ContactRelocationFailed
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ContactRelocationFailed(
        TInt aReason, MVPbkStoreContact* aContact)
    {
    // We got the ownership of aContact
    delete aContact;
    if ( aReason == KErrCancel )
        {
        // No error note is to be shown to the user when she
        // manually cancels the relocation process, therefore
        // the error code must be converted
        aReason = KErrNone;
        }
    ProcessDismissed( aReason );
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::ContactRelocationFailed
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ContactsRelocationFailed(
        TInt /*aReason*/, CVPbkContactLinkArray* /*aContacts*/ )
    {
    // Do nothing
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::RelocationProcessComplete
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::RelocationProcessComplete()
    {
    __ASSERT_DEBUG( iStoreContact, 
        Panic( EPanicPreCond_RelocationProcessCompleteL ) );
    // Lock contact for setting tone
    TRAPD( res, iStoreContact->LockL( *this ) );
    if ( res != KErrNone )
        {
        ProcessDismissed( res );
        }
    }
	
// --------------------------------------------------------------------------
// CPbk2SetToneCmd::RelocationProcessCompleteL
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::VPbkSingleContactOperationComplete(
        MVPbkContactOperationBase& /*aOperation*/,
        MVPbkStoreContact* aContact)
    {
    delete iRetrieveOperation;
    iRetrieveOperation = NULL;

    delete iStoreContact;    
   	iStoreContact = aContact;
   	
    if ( !ContactHasRingToneField( iStoreContact ) && iToneFilename.Length() <=0 )
        {
        // User has selected 'no personal ringtone' for contact which 
        // does not have ring tone field, so we can quit now
        ProcessDismissed( KErrNone );
        }
    else
        {
        TBool contactNeedsRelocation = EFalse;
        TInt err = KErrNone;
        TRAP( err, contactNeedsRelocation = 
                    RelocateContactL( iStoreContact ) );
                 
        if (err != KErrNone)
            {
            ProcessDismissed( err );
            }

        if ( !contactNeedsRelocation )
            {
            TRAP( err, iStoreContact->LockL( *this ) );
            if ( err != KErrNone )
                {
                ProcessDismissed( err );
                }
            }
        else
            {
            // Relocator has taken the ownership of the contact
            iStoreContact = NULL;
            }   	    
        }
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::RelocationProcessCompleteL
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::VPbkSingleContactOperationFailed(
        MVPbkContactOperationBase& /*aOperation*/, 
        TInt aError )
    {
    ProcessDismissed( aError );
    }
      
// --------------------------------------------------------------------------
// CPbk2SetToneCmd::RelocationProcessCompleteL
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ContactOperationCompleted(
        TContactOpResult aResult)
    {
    if ( aResult.iOpCode == EContactLock )
        {
        // We have to save the initially focused field, so that we can put
        // it back focused after setting and committing ringingtone.
        // If leaves the focus will not be set.
        TRAP_IGNORE( iFieldFocusHelper->SaveInitiallyFocusedFieldL
                        ( *iStoreContact ) );        
        TRAPD( err, SetToneAndCommitL( iStoreContact ) );        
        if ( err != KErrNone )
            {
            CCoeEnv::Static()->HandleError( err );
            ProcessDismissed( err );
            }
        }
    else if ( aResult.iOpCode == EContactCommit )
        {
        // Set the original field focused after command execution     
        TRAP_IGNORE( iFieldFocusHelper->RestoreSavedFieldL() );
        // Now, its time to exit the command
        IssueStopRequest();
        }    
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::RelocationProcessCompleteL
// --------------------------------------------------------------------------
//
void CPbk2SetToneCmd::ContactOperationFailed(
        TContactOp /*aOpCode*/, 
        TInt aErrorCode, 
        TBool /*aErrorNotified*/)
    {
    if ( aErrorCode != KErrNone )
        {
        CCoeEnv::Static()->HandleError( aErrorCode );
        }
    
    ProcessDismissed( aErrorCode );
    }

// --------------------------------------------------------------------------
// CPbk2SetToneCmd::ContactHasRingToneField
// --------------------------------------------------------------------------
//
inline TBool CPbk2SetToneCmd::ContactHasRingToneField( 
        MVPbkStoreContact* aContact  )
    {
    TBool ret( ETrue );

    TPbk2StoreContactAnalyzer analyzer
        ( Phonebook2::Pbk2AppUi()->ApplicationServices().ContactManager(),
            aContact );
    TInt fieldIndex( KErrNotFound );
    // No harm done if field finding leaves
    // it just might produce unnecessary relocation note but nothing more
    TRAP_IGNORE( fieldIndex = analyzer.HasFieldL( R_PHONEBOOK2_RINGTONE_SELECTOR ) );
    if ( fieldIndex == KErrNotFound  )
        {
        ret = EFalse;
        }

    return ret;
    }

//  End of File  
