/*
* 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: 
*           Base class for image commands set, view and remove.
*
*/


// INCLUDE FILES
#include "CPbk2ImageCmdBase.h"
#include "CPbk2FieldFocusHelper.h"

// Phonebook 2
#include <CPbk2ImageManager.h>
#include <CPbk2ContactRelocator.h>
#include <MPbk2CommandObserver.h>
#include <RPbk2LocalizedResourceFile.h>
#include <Pbk2DataCaging.hrh>
#include <CPbk2FieldPropertyArray.h>
#include <CPbk2ApplicationServices.h>
#include <MPbk2AppUi.h>

// Virtual Phonebook
#include <MVPbkStoreContact.h>
#include <MPbk2ContactUiControl.h>
#include <MVPbkContactLink.h>
#include <MVPbkFieldType.h>
#include <CVPbkContactManager.h>
#include <MVPbkContactOperationBase.h>
#include <VPbkEng.rsg>

// System headers
#include <coemain.h>

// Debugging headers
#include <Pbk2Debug.h>


/// Unnamed namespace for local definitons
namespace {

#ifdef _DEBUG
    enum TPanicCode
        {
        EPanicInvalidOpCode,
        EPanicLogic_RelocateContactL
        };

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

} // namespace


CPbk2ImageCmdBase::CPbk2ImageCmdBase
        (MPbk2ContactUiControl& aUiControl) :
    iUiControl(&aUiControl)
    {
    }

CPbk2ImageCmdBase::~CPbk2ImageCmdBase()
    {
    if( iUiControl )
        {
        iUiControl->RegisterCommand( NULL );
        }

    delete iFieldFocusHelper;
    delete iImageManager;
    delete iContactLink;
    delete iRetrieveOperation;
    delete iStoreContact;
    delete iContactRelocator;
    }

void CPbk2ImageCmdBase::BaseConstructL()
    {
    CPbk2ApplicationServices* appServices = CPbk2ApplicationServices::InstanceLC();

    iContactManager =
        &(appServices->ContactManager());

    iContactLink = iUiControl->FocusedContactL()->CreateLinkLC();
    CleanupStack::Pop(); // iContactLink

    iImageManager = CPbk2ImageManager::NewL(*iContactManager);
    iFieldFocusHelper = CPbk2FieldFocusHelper::NewL( *iUiControl, 
        appServices->FieldProperties() );

    CleanupStack::PopAndDestroy(); // appServices

    iUiControl->RegisterCommand( this );        
    }

void CPbk2ImageCmdBase::ProcessDismissed(TInt aError)
    {
    if ( aError != KErrNone && 
         aError != KLeaveExit )
        {
        // Report the failure to the user
        CCoeEnv::Static()->HandleError( aError );
        }

    if (iUiControl)
        {
        // Not matter if saved field can not focused
        TRAP_IGNORE( iFieldFocusHelper->RestoreSavedFieldL() );
        iUiControl->UpdateAfterCommandExecution();
        }

    if (iCommandObserver)
        {
        // Notify command owner that the command has finished
        iCommandObserver->CommandFinished(*this);
        }
    }

void CPbk2ImageCmdBase::ExecuteLD()
    {
    CleanupStack::PushL(this);
    ReadFieldTypesL();
    iRetrieveOperation = iContactManager->RetrieveContactL(
        *iContactLink, *this);
    CleanupStack::Pop(this);
    }

void CPbk2ImageCmdBase::AddObserver( MPbk2CommandObserver& aObserver )
    {
    iCommandObserver = &aObserver;
    }

void CPbk2ImageCmdBase::ResetUiControl(
        MPbk2ContactUiControl& aUiControl)
    {
    if (iUiControl == &aUiControl)
        {
        iUiControl = NULL;
        }
    }

void CPbk2ImageCmdBase::ContactOperationCompleted
        ( TContactOpResult aResult )
    {
    __ASSERT_DEBUG((aResult.iOpCode == EContactCommit ||
            aResult.iOpCode == EContactLock),
            Panic(EPanicInvalidOpCode));

    if (aResult.iOpCode == EContactLock)
        {
        // Not matter, if focusing not success
        TRAP_IGNORE( iFieldFocusHelper->SaveInitiallyFocusedFieldL( *iStoreContact ) );
        TBool result (EFalse);
        TRAPD(err, result = ExecuteCommandL());
        if (err != KErrNone || !result)
            {
            ProcessDismissed(err);
            }
        }
    else
        {
        ProcessDismissed(KErrNone);
        }
    }

void CPbk2ImageCmdBase::ContactOperationFailed
    ( TContactOp PBK2_DEBUG_ONLY( aOpCode ), TInt aErrorCode,
      TBool /*aErrorNotified*/ )
    {
    __ASSERT_DEBUG( ( aOpCode == EContactCommit || aOpCode == EContactLock ),
        Panic( EPanicInvalidOpCode ) );

    ProcessDismissed( aErrorCode );
    }

/**
 * Called when retrieve operation completes.
 */
void CPbk2ImageCmdBase::VPbkSingleContactOperationComplete(
    MVPbkContactOperationBase& aOperation, MVPbkStoreContact* aContact)
    {
    if (&aOperation == iRetrieveOperation)
        {
        delete iRetrieveOperation;
        iRetrieveOperation = NULL;

        if (iStoreContact)
            {
            delete iStoreContact;
            iStoreContact = NULL;
            }
        // We now have a store contact
        iStoreContact = aContact;
        }

    TBool contactNeedsRelocation = EFalse;
    TRAPD( err, contactNeedsRelocation = RelocateContactL());
    if (err == KErrNone && !contactNeedsRelocation)
        {
        TRAP(err, iStoreContact->LockL(*this));
        }
    if (err != KErrNone)
        {
        ProcessDismissed(err);
        }
    }

/**
 * Called when retrieve operation fails.
 */
void CPbk2ImageCmdBase::VPbkSingleContactOperationFailed(
        MVPbkContactOperationBase& aOperation, TInt aError)
    {
    if (&aOperation == iRetrieveOperation)
        {
        delete iRetrieveOperation;
        iRetrieveOperation = NULL;

        // We cannot get the contact, so we have to
        // fail. We cannot continue, since this operation
        // was executed only in case of one contact.
        ProcessDismissed(aError);
        }
    }

inline TBool CPbk2ImageCmdBase::RelocateContactL()
    {
    __ASSERT_DEBUG( iStoreContact, Panic( EPanicLogic_RelocateContactL ) );
    TBool ret = EFalse;

    delete iContactRelocator;
    iContactRelocator = NULL;
    iContactRelocator = CPbk2ContactRelocator::NewL();

    if ( !iContactRelocator->IsPhoneMemoryContact( *iStoreContact ) &&
        iContactRelocator->IsPhoneMemoryInConfigurationL() )
        {
        // Asynchronously relocate contact
        iContactRelocator->RelocateContactL( iStoreContact, *this,
            Pbk2ContactRelocator::EPbk2DisplayStoreDoesNotSupportQuery,
            CPbk2ContactRelocator::EPbk2RelocatorExistingContact );
        iStoreContact = NULL;    // Ownership was taken
        ret = ETrue;        // Indicate that contact needs relocating
        }

    return ret;
    }

void CPbk2ImageCmdBase::ContactRelocatedL
        (MVPbkStoreContact* aRelocatedContact)
    {
    iStoreContact = aRelocatedContact; // take ownership
    }

void CPbk2ImageCmdBase::ContactRelocationFailed
        (TInt aReason, MVPbkStoreContact* aContact)
    {
    // Take the contact back
    iStoreContact = 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);
    }

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

void CPbk2ImageCmdBase::RelocationProcessComplete()
    {
    // now lock the contact to start the actual process
    TRAPD( res, iStoreContact->LockL( *this ) );
    if ( res != KErrNone )
        {
        ProcessDismissed( res );
        }
    }

void CPbk2ImageCmdBase::ReadFieldTypesL()
    {
    iThumbnailFieldType =
        iContactManager->FieldTypes().Find(R_VPBK_FIELD_TYPE_THUMBNAILPIC);
    iImageFieldType =
        iContactManager->FieldTypes().Find(R_VPBK_FIELD_TYPE_CALLEROBJIMG);
        
    if (!iThumbnailFieldType || !iImageFieldType)
        {
        User::Leave(KErrNotFound);
        }
    }
    
TInt CPbk2ImageCmdBase::FindFieldIndex(const MVPbkFieldType& aFieldType)
	{
	if( iStoreContact )
	    {
    	const MVPbkBaseContactFieldCollection& fields = iStoreContact->Fields();	
    	const TInt fieldCount = fields.FieldCount();
        
        for (TInt i = 0; i < fieldCount; ++i)
            {
            const MVPbkFieldType* fieldType = 
                fields.FieldAt(i).BestMatchingFieldType();
            if (fieldType && fieldType->IsSame(aFieldType))
                {
                return i;
                }
            }
	    }
    return KErrNotFound;
	}    

//  End of File
