/*
* Copyright (c) 2002 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: 
*     Updates Log events adding remote party
*
*/


// INCLUDE FILES
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <logfilterandeventconstants.hrh>
#endif
#include <logcli.h>
#include <logview.h>
#include <VPbkEng.rsg>
#include <PbkFields.hrh>
#include <CVPbkContactFieldIterator.h>
#include <CVPbkContactManager.h>
#include <MVPbkFieldType.h>
#include <MVPbkStoreContact.h>
#include <MVPbkContactFieldTextData.h>

#include "CLogsEventUpdater.h"
#include "MLogsObserver.h"
#include "MLogsReaderConfig.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES  

// CONSTANTS
const TInt KLogsPbkTypeIdLength = 11;
// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

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

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


// ----------------------------------------------------------------------------
// CLogsEventUpdater::CLogsEventUpdater
// ----------------------------------------------------------------------------
//
CLogsEventUpdater::CLogsEventUpdater( 
    RFs& aFsSession,
    MLogsObserver* aObserver ) :
        CLogsBaseUpdater( aFsSession, aObserver ),
        iNumberFieldType( EPbkFieldIdNone )
    {
    }

// ----------------------------------------------------------------------------
// CLogsEventUpdater::NewL
// ----------------------------------------------------------------------------
//
CLogsEventUpdater* CLogsEventUpdater::NewL( 
    RFs& aFsSession,
    MLogsObserver* aObserver,
    CVPbkPhoneNumberMatchStrategy::TVPbkPhoneNumberMatchFlags aMatchFlags )
    {
    CLogsEventUpdater* self = new ( ELeave ) CLogsEventUpdater( aFsSession, aObserver );
    CleanupStack::PushL( self );
    self->ConstructL( aMatchFlags );
    CleanupStack::Pop();
    return self;
    }
  
// ----------------------------------------------------------------------------
// CLogsEventUpdater::ConstructL
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::ConstructL( CVPbkPhoneNumberMatchStrategy::TVPbkPhoneNumberMatchFlags aMatchFlags )
    {
    BaseConstructL( aMatchFlags );
    iLogViewEvent = CLogViewEvent::NewL( *iLogClient );
    iFilter->SetNullFields( ELogRemotePartyField );
    CActiveScheduler::Add( this );
    }

// ----------------------------------------------------------------------------
// CLogsEventUpdater::~CLogsEventUpdater
// ----------------------------------------------------------------------------
//
CLogsEventUpdater::~CLogsEventUpdater()
    {
    delete iNumber;
    }

// ----------------------------------------------------------------------------
// CLogsEventUpdater::StartRunningL
//
// Called from base class 
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::StartRunningL()   
    {
    Cancel();

    //Important that ConfigureL is called before we start here 
    if( iNumber )
        {
        //We first try to search corresponding contact for this phonenumber from Phonebook
        SearchRemotePartyL( *iNumber );   
        }
    }


// ----------------------------------------------------------------------------
// CLogsEventUpdater::ContinueRunningL
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::ContinueRunningL( TInt aFieldId )
    {
    TBool okToContinue( EFalse );    

    //1. Continue only if the contact was found from Phonebook as we prcess only one phone number at a time.
    if( aFieldId != KErrNotFound )    
        {
        
        // iFieldId.Num( aFieldId );
        okToContinue = iLogViewEvent->SetFilterL( *iFilter, iStatus );  //ETrue, if at least one row in db available for filter,
                                                                        //current entry will be the first in view when asynch call
                                                                        //is finished.
        }
    
    //2. Continue only if found one or more database entries that need updating the remote party.
    if( okToContinue )
        {
        iState = EStateActive;
        iPhase = ERead;
        SetActive();                //Continue
        }
    else if( iObserver )            //End this run
        {
        iState = EStateEventUpdaterFinished;
        iPhase = EDone;
        iObserver->StateChangedL( this );
        }
    }

// ----------------------------------------------------------------------------
// CLogsEventUpdater::ConfigureL
//
// Sets the phone number that is used as search criteria this time (all events containing this 
// phone number are updated to log database)
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::ConfigureL( const MLogsReaderConfig* aConfig )   //Implemented from MLogsReader
    {
    if( iNumber )
        {
        delete iNumber;
        iNumber = NULL;
        }
    iNumber = aConfig->Number().AllocL();
    iFilter->SetNumber( *iNumber );
    }


// ----------------------------------------------------------------------------
// CLogsEventUpdater::RunL
//
// Update Log database entries corresponding to the filter
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::RunL()
    {
    if( iStatus != KErrNone && iObserver || 
        *iName == KNullDesC )  // If the contact name is empty, dont update. Otherwise the code below the else 
                               // statement loops forewer between asynch calls to iLogClient->ChangeEvent and
                               // iLogViewEvent->FirstL
        {
        iState = EStateEventUpdaterFinished;
        if ( iObserver )
            {
            iObserver->StateChangedL( this );
            }
        }
    else
        {
        switch( iPhase )
            {
            case ERead:
                {
                TBuf<KLogsPbkTypeIdLength> subject;
                subject.Zero();
                iEvent->CopyL( iLogViewEvent->Event() );   
                iEvent->SetRemoteParty( *iName );
                subject.AppendNum( iNumberFieldType );
                iEvent->SetSubject( subject );
                iEvent->SetContact( KNullContactId );    //In Pbk2 links are used instead of TContactItemId
                iPhase = EUpdate;
                iLogClient->ChangeEvent( *iEvent, iStatus );
                SetActive();
                }
                break;

            case EUpdate:
                if( iLogViewEvent->FirstL( iStatus ) )  //If there's still at least one entry in view, let's continue 
                                                        //processing it (this assumes that the event updated above has
                                                        //already disappeared from view and the "next" shows now as "first"
                                                        //in view, otherwise not all events are updated correctly).        
                    {
                    iPhase = ERead;
                    SetActive();
                    }
                else if( iObserver )
                    {
                    iState = EStateEventUpdaterFinished;
                    iPhase = EDone;
                    iObserver->StateChangedL( this );
                    }
                break;

            default:
                break;
            }
        }   
    }

// ----------------------------------------------------------------------------
// CLogsEventUpdater::ProcessVPbkSingleContactOperationCompleteImplL
//
// Detrived function by base class for get the number's pbk field type
// ----------------------------------------------------------------------------
//
void CLogsEventUpdater::ProcessVPbkSingleContactOperationCompleteImplL(
    MVPbkContactOperationBase& aOperation,
    MVPbkStoreContact* aContact )
    {
	//invoke the base class function firstly to get the event's title(name) 
    CLogsBaseUpdater::ProcessVPbkSingleContactOperationCompleteImplL( aOperation, aContact );
 
    iNumberFieldType = EPbkFieldIdNone ;
    TBool found( EFalse );
      
    TInt count = iContactManager->FieldTypes().FieldTypeCount();
        
    for ( TInt i = 0; i < count && !found; i++ )
        {
        const MVPbkFieldType& fieldType = iContactManager->FieldTypes().FieldTypeAt( i );
        const TInt fieldTypeResId = fieldType.FieldTypeResId();
                       
        if ( fieldTypeResId == R_VPBK_FIELD_TYPE_MOBILEPHONEGEN
             || fieldTypeResId == R_VPBK_FIELD_TYPE_MOBILEPHONEWORK
             || fieldTypeResId == R_VPBK_FIELD_TYPE_MOBILEPHONEHOME 
             || fieldTypeResId == R_VPBK_FIELD_TYPE_LANDPHONEHOME
             || fieldTypeResId == R_VPBK_FIELD_TYPE_LANDPHONEWORK
             || fieldTypeResId == R_VPBK_FIELD_TYPE_LANDPHONEGEN
             || fieldTypeResId == R_VPBK_FIELD_TYPE_CARPHONE
             || fieldTypeResId == R_VPBK_FIELD_TYPE_ASSTPHONE
             || fieldTypeResId == R_VPBK_FIELD_TYPE_PAGERNUMBER
             || fieldTypeResId == R_VPBK_FIELD_TYPE_FAXNUMBERGEN
             || fieldTypeResId == R_VPBK_FIELD_TYPE_FAXNUMBERHOME
             || fieldTypeResId == R_VPBK_FIELD_TYPE_FAXNUMBERWORK )
            {
            CVPbkBaseContactFieldTypeIterator* itr = 
                CVPbkBaseContactFieldTypeIterator::NewLC( fieldType, 
                    aContact->Fields() );
                               
            while ( !found && itr->HasNext() )
                {
                const MVPbkBaseContactField* field = itr->Next();
                // Check field type before casting.
                const MVPbkContactFieldData& contactFieldData = field->FieldData();
                if ( EVPbkFieldStorageTypeText == contactFieldData.DataType() )
                    {
                    // get field data
                    const MVPbkContactFieldTextData& data = 
                    MVPbkContactFieldTextData::Cast( contactFieldData );
					//Get the rightmost string pointer with the max length of match(iDigitsToMatch)
                    TPtrC clipNumber = iNumber->Right( iDigitsToMatch );
                    TPtrC fieldNumber = data.Text().Right( iDigitsToMatch );
                    
                    if ( 0 == fieldNumber.Compare( clipNumber ) )               
                        {
                        found = ETrue;
                        iNumberFieldType = NumberPbkFieldFromVPbk( fieldTypeResId );
                        }  
                    }                  
                }
            CleanupStack::PopAndDestroy( itr );
            }   
        } 
    }

TInt CLogsEventUpdater::NumberPbkFieldFromVPbk( TInt aNumberFieldType ) const
    {
    TInt pbkFieldType = EPbkFieldIdNone;
       
    switch ( aNumberFieldType ) 
        {   
        case R_VPBK_FIELD_TYPE_MOBILEPHONEGEN:
        case R_VPBK_FIELD_TYPE_MOBILEPHONEWORK:
        case R_VPBK_FIELD_TYPE_MOBILEPHONEHOME:
            pbkFieldType = EPbkFieldIdPhoneNumberMobile;           
            break;

        case R_VPBK_FIELD_TYPE_LANDPHONEHOME:
        case R_VPBK_FIELD_TYPE_LANDPHONEWORK:
        case R_VPBK_FIELD_TYPE_LANDPHONEGEN:
            pbkFieldType = EPbkFieldIdPhoneNumberGeneral;            
            break;
                
        case R_VPBK_FIELD_TYPE_PAGERNUMBER:
            pbkFieldType = EPbkFieldIdPagerNumber;            
            break;
            
        case R_VPBK_FIELD_TYPE_FAXNUMBERGEN:
        case R_VPBK_FIELD_TYPE_FAXNUMBERHOME:
        case R_VPBK_FIELD_TYPE_FAXNUMBERWORK:
            pbkFieldType = EPbkFieldIdFaxNumber;           
            break;
             
        case R_VPBK_FIELD_TYPE_ASSTPHONE:
            pbkFieldType = EPbkFieldIdAssistantNumber; 
            break;
  
        case R_VPBK_FIELD_TYPE_CARPHONE:
            pbkFieldType = EPbkFieldIdCarNumber; 
            break;                   
                     
        default:
            break;
        }
    
    return pbkFieldType;  
    }

// End of File

