/*
* Copyright (c) 2002-2008 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:  Message handler
*
*/

// INCLUDE FILES
#include "cpecenrepmonitor.h"
#include "cpeclientcallrequestmonitor.h"
#include "cpeclientcallrequestmonitor.h"
#include "cpeclientcommandhandlermonitor.h"
#include "cpeclientservices.h"
#include "cpeexternaldatahandler.h"
#include "cpemanualcallcontrolhandler.h"
#include "cpemessagehandler.h"
#include "cpeparseremergencynumberhandler.h"
#include "cpeparsermanufacturerhandler.h"
#include "cpeparsermischandler.h"
#include "cpeparserphonenumberhandler.h"
#include "cpeparsersimcontrolhandler.h"
#include "cpeparsersscallhandler.h"
#include "cpeparsersshandler.h"
#include "cpeparservoipnumberhandler.h"
#include "cpepcnparserprocedurehandler.h"
#include "cpesimstatemonitor.h"
#include "cpetimer.h"
#include "mpephonemodelinternal.h"
#include "mpeservicehandling.h"
#include "cperemotepartyinfomediator.h"

#include <apacmdln.h>
#include <apgcli.h>
#include <apgtask.h>
#include <AudioPreference.h>
#include <barsc.h> 
#include <barsread.h>
#include <bldvariant.hrh>
#include <ccpdefs.h>
#include <coreapplicationuisdomainpskeys.h>
#include <cpeclientinformation.h>
#include <cpegsmaudiodata.h>
#include <CPhoneGsmHandlerContainer.h>
#include <CPhoneGsmOptionContainerBase.h>
#include <CPhoneGsmParserBase.h>
#include <CPhoneGsmParserResult.h>
#include <featmgr.h>
#include <mccecall.h>
#include <mpeaudiodata.h>
#include <mpecallhandling.h>
#include <mpecontacthandling.h>
#include <mpedatastore.h>
#include <mpeloghandling.h>
#include <pathinfo.h>
#include <pepanic.pan>
#include <PhCltTypes.h>
#include <PhoneGsmParser.h>
#include <ProfileEngineDomainConstants.h>
#include <talogger.h>
#include <w32std.h>

// EXTERNAL DATA STRUCTURES
// None.

// EXTERNAL FUNCTION PROTOTYPES  
// None.

// CONSTANTS
// Prefix change off. See settingsinternalcrkeys.h
const TInt KPEPrefixChangeOff = 0;
// Prefix change on. See settingsinternalcrkeys.h
const TInt KPEPrefixChangeOn = 1;
// International prefix
_LIT( KPEIntPrefix, "+" );
// Japan prefix
_LIT( KPEJapanPrefix, "+81" );
// Zero prefix
_LIT( KPEZeroPrefix, "0" );
// Valid dtmf sting
_LIT( KValidDtmfChars, "0123456789pw*+#" );

// Timeout for automatic answer. 
const TInt KPEAutomaticAnswerTimeOut = 5000000;

_LIT( KPEClirSuppress, "*31#" );
_LIT( KPEClirInvoke, "#31#" );

const TInt KPENumberPlus = '+';
const TInt KPENumberHash = '#'; 
const TInt KPENumberAsterisk = '*'; 

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

// -----------------------------------------------------------------------------
// CPEMessageHandler::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CPEMessageHandler* CPEMessageHandler::NewL
        ( 
        MPEPhoneModelInternal& aModel,
        MPECallHandling& aCallHandling,
        MEngineMonitor& aEngineMonitor,
        CPEGsmAudioData& aAudioData,
        MPELogHandling& aLogHandling,
        MPEContactHandling& aContactHandling,
        CPESimStateMonitor& aSimStateMonitor,
        CPEExternalDataHandler& aGsmExternalDataHandler,
        MPEServiceHandling& aServiceHandling,
        RFs& aFsSession )
    {
    CPEMessageHandler* self = new ( ELeave ) CPEMessageHandler( 
        aModel, 
        aCallHandling, 
        aEngineMonitor, 
        aAudioData, 
        aLogHandling, 
        aContactHandling, 
        aSimStateMonitor,
        aGsmExternalDataHandler,
        aServiceHandling,
        aFsSession );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::CPEMessageHandler
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CPEMessageHandler::CPEMessageHandler( 
        MPEPhoneModelInternal& aModel,                 // The model of the phone object which owns this object
        MPECallHandling& aCallHandling,              // The reference parameter of the phone data object which is used to create call handling request
        MEngineMonitor& aEngineMonitor,        // The reference parameter of the engine monitor object which is used to communication with phone application
        CPEGsmAudioData& aAudioData,              // The reference parameter of the audio data object which is used to handle audio requests
        MPELogHandling& aLogHandling,                // The reference parameter of the logs data object which is used to handle log requests   
        MPEContactHandling& aContactHandling,          // The reference parameter of the contact data object which is used to handle contact requests
        CPESimStateMonitor& aSimStateMonitor,
        CPEExternalDataHandler& aExternalDataHandler, // The reference parameter of external data handler object
        MPEServiceHandling& aServiceHandling,
        RFs& aFsSession )                // The reference parameter of CustomAPI
        : iModel( aModel ), 
            iCallHandling( aCallHandling ),
            iEngineMonitor( aEngineMonitor ),
            iGsmAudioData( aAudioData ),
            iLogHandling( aLogHandling ),
            iContactHandling( aContactHandling ),
            iExternalDataHandler( aExternalDataHandler ),
            iSimStateMonitor( aSimStateMonitor ),
            iFsSession( aFsSession ),
			iSwitchToVidCalReconFlag( EFalse ),
            iServiceHandling( aServiceHandling ),
            iDataStore( *aModel.DataStore() )
    {
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::BaseConstructL
// Performs base construction of the object.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::ConstructL()
    {
    iClientInformation = CPEClientInformation::NewL();

    iParser = PhoneGsmParser::CreateParserL();
    iOptions = PhoneGsmParser::CreateOptionContainerL();
    iManualCallControlHandler = CPEManualCallControlHandler::NewL( iCallHandling, *this, iDataStore );
    iClientServices = CPEClientServices::NewL( iModel, *this, iCallHandling, *iManualCallControlHandler );
    iParserHandlerContainer = CPhoneGsmHandlerContainer::NewL();

    // NOTE: The handler objects will break some CleanUpStack usage rules:
    // CPEMessageHandler class construct handler objects but ownership will be 
    // transfered to Handler Container. And therefore CleanUpStack will be 
    // used to member object because if iParserHandlerContainer->AddHandlerL 
    // leaves CPEMessageHandler don't delete handler object hence CleanUpStack
    // must delete handler object. 

    // Handles manufacturer specific codes from the parser.
    CPEParserManufacturerHandler* manufacturerHandler = 
        new ( ELeave ) CPEParserManufacturerHandler( iModel, iCallHandling, iFsSession );
    CleanupStack::PushL( manufacturerHandler );
    iParserHandlerContainer->AddHandlerL( *manufacturerHandler ); // ownership will be transfered to Handler Container.
    CleanupStack::Pop( manufacturerHandler );

    // Handles misc codes from the parser.
    CPEParserMiscHandler* miscHandler = new ( ELeave ) CPEParserMiscHandler( 
        *this, 
        iCallHandling );
    CleanupStack::PushL( miscHandler );
    iParserHandlerContainer->AddHandlerL( *miscHandler );// ownership will be transfered to Handler Container.
    CleanupStack::Pop( miscHandler );

    CPEParserPhoneNumberHandler* tempPhoneNumberHandler = 
        new ( ELeave ) CPEParserPhoneNumberHandler( *this, 
                                                       iCallHandling, 
                                                       iDataStore );
    CleanupStack::PushL( tempPhoneNumberHandler );
    iParserHandlerContainer->AddHandlerL( *tempPhoneNumberHandler ); // ownership will be transfered to Handler Container.
    CleanupStack::Pop( tempPhoneNumberHandler );
    iPhoneNumberHandler = tempPhoneNumberHandler;

    // Handles sim control procedures from the parser.
    CPEParserSimControlHandler* simControlHandler = CPEParserSimControlHandler::NewL( 
        iModel, 
        iContactHandling );
    CleanupStack::PushL( simControlHandler );
    iParserHandlerContainer->AddHandlerL( *simControlHandler );// ownership will be transfered to Handler Container.
    CleanupStack::Pop( simControlHandler );

    // Handles supplementary services during calls from the parser.
    CPEParserSSCallHandler* sSCallHandler = new ( ELeave ) CPEParserSSCallHandler( 
        *this, 
        iModel, 
        *iManualCallControlHandler );
    CleanupStack::PushL( sSCallHandler );
    iParserHandlerContainer->AddHandlerL( *sSCallHandler );// ownership will be transfered to Handler Container.
    CleanupStack::Pop( sSCallHandler );

    iSSHandler = CPEParserSSHandler::NewL( *this, iModel ); 
    iParserHandlerContainer->AddHandlerL( *iSSHandler );// ownership will be transfered to Handler Container.

    // Handles pcn service requests from the parser.
    CPEPcnParserProcedureHandler* pcnProcedureHandler = CPEPcnParserProcedureHandler::NewL( 
        *this, 
        iModel ); 
    CleanupStack::PushL( pcnProcedureHandler );
    iParserHandlerContainer->AddHandlerL( *pcnProcedureHandler );// ownership will be transfered to Handler Container.
    CleanupStack::Pop( pcnProcedureHandler );
    
    // Handles emergency phone number
    CPEParserEmergencyNumberHandler* tempEmergencyNumberHandler 
        = new ( ELeave ) CPEParserEmergencyNumberHandler( *this, 
                                                          iCallHandling, 
                                                          iDataStore );
    CleanupStack::PushL( tempEmergencyNumberHandler );
    iParserHandlerContainer->AddHandlerL( *tempEmergencyNumberHandler ); // ownership will be transfered to Handler Container.
    CleanupStack::Pop( tempEmergencyNumberHandler );
    iEmergencyNumberHandler = tempEmergencyNumberHandler;

    CPEParserVoipNumberHandler* tempVoipNumberHandler
        = CPEParserVoipNumberHandler::NewLC( *this, 
                                               iCallHandling, 
                                               iServiceHandling,
                                               iDataStore );

    iParserHandlerContainer->AddHandlerL( *tempVoipNumberHandler ); // ownership will be transfered to Handler Container.
    CleanupStack::Pop( tempVoipNumberHandler );
    iVoipNumberHandler = tempVoipNumberHandler;
    
    iAutomaticAnswerTimer = CPETimer::NewL( iModel );
 
    // Reserve needed callinfo and remoteinfo from heap.
    iCallInfo = new ( ELeave ) RMobileCall::TMobileCallInfoV3;
    
    iResult = PhoneGsmParser::CreateResultL();
    }
        
// Destructor
CPEMessageHandler::~CPEMessageHandler()
    {
    delete iClientInformation;
    delete iAsyncCallBack;
    delete iCallInfo;
    delete iAutomaticAnswerTimer;
    delete iParserHandlerContainer;
    delete iClientServices;
    delete iManualCallControlHandler;
    delete iOptions;
    delete iParser;
    delete iResult;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleAnswerCall
// Handles answer message from phone application. Method calls AnswerCall 
// method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleAnswerCall(
        const TBool aAutomaticAnswer ) // Informs is this automatic answer or not
    {
    // Stop DTMF sending and empty buffers if answer was requested in the
    // middle of DTMF sequence.
    StopDtmfSending();
    
    //Check if this is automatic answer and play redialCompletedTone (confusing naming)
    if( !aAutomaticAnswer )
        {
        iAutomaticAnswerTimer->Cancel();
        }

    return iCallHandling.AnswerCall();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleAudioRouting
// Handles accessory mode changed message from AudioHandling subsystem. Method 
// fecths accessory mode from AudioHandling subsystem and method sets new accessory
// mode value to the CPEEngineInfo class. Method finds previously used volume
// values for accessory and changes volume accordingly.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleAudioRouting( TBool aVideoCall, TInt aCallId )
    {
    TInt error( ECCPErrorNone );
    
    if ( aCallId == KPEEmergencyCallId )     
         {
         error = iGsmAudioData.HandleEnergencyCallStarting();
         }
     else
         {
         error = iGsmAudioData.HandleCallStarting( aVideoCall );
         }
    
    return error;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleRoutePreferenceChanged
// Handles route preference changed message from AudioHandling subsystem. 
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleRoutePreferenceChanged()
    {
    TInt error( ECCPErrorNone );
    
    TEFLOGSTRING( KTAMESINT, "PE CPEMessageHandler::HandleRoutePreferenceChanged()" );
    
    error = iGsmAudioData.CallAudioRoutePreferenceChanged();
     
    return error;
    }    
// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleContinueDtmfSending
// Handles continue dtmf sending after 'w' character in the dtmf string
// Method calls ContinueDtmfSending or StopDtmfSending method from the 
// CallHandling subsystem.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleContinueDtmfSending( 
        const TBool aContinue )
    {
    if ( aContinue )
        {
        HandleSendDtmf();
        }
    else
        {
        StopDtmfSending();
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleReleaseAll
// Handles release all message from phone application
// Method calls ReleaseAll method from the CallHandling subsystem object..
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleReleaseAll()
    {
    return iCallHandling.ReleaseAll();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleReleaseCall
// Handles release message from phone application
// Method fecths call id number from the CPEEngineInfo structure and then
// Method calls HangUp method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleReleaseCall( TPEHangUpOptions aAutoResumeOption )
    {
    TInt callId;
    TInt errorCode( ECCPErrorNone );
    callId = iDataStore.CallId();
    
    if ( CallIdCheck::IsVideo( callId ) )
        {
        //Video call
        iGsmAudioData.StopInbandTonePlay();
        errorCode = iCallHandling.HangUp( callId, ETPEHangUpNotResumeHeldCall );
        }
    else
        {
        errorCode = iCallHandling.HangUp( callId, aAutoResumeOption );
        }
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleReleaseConference
// Handles release message from phone application
// Method calls HangUp method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleReleaseConference()
    {
    
    return iCallHandling.ReleaseConference(); 
 
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSendDtmf
// Handles send dtmf message from phone application
// Method fetches dtmf string from the CPEEngineInfo class and then
// Method parses the DTMF string and then take action properly: 
// hard pause: triggers sending MEngineMonitor::EPEMessageStoppedDTMF 
//      to phone model
// '+': triggers substitution speed dial digit with speed dial number. 
//
// Method calls SendDtmf method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleSendDtmf()
    {
    TInt errorCode( ECCPErrorNone );
    TPEDtmfString dtmfString = iDataStore.DtmfStringCommand();

    RemoveInvalidChars( dtmfString, KPEClientValidChars, EFalse );

    if ( dtmfString.Length() == 0 )
        {
        iDataStore.SetDtmfString( KNullDesC() ); 
        errorCode = KErrArgument;
        }
    // Parse the first character of the string
    else if ( dtmfString[ 0 ] == KPEDtmfStopCharLowercase || 
              dtmfString[ 0 ] == KPEDtmfStopCharUppercase ) // hard pause
        {
        TEFLOGSTRING( KTAMESINT, "PE CPEMessageHandler::HandleSendDtmf(), Processing W" );
        // remove the hard pause char from the string
        iDataStore.SetDtmfString( dtmfString.Mid( 1 ) );
        iDataStore.SetDtmfStringCommand( dtmfString.Mid( 1 ) );
        
        // Send EPEMessageStoppedDTMF message asynchronic.

        TCallBack callBack( CallbackSendMessageStoppedDTMF, this );
        delete iAsyncCallBack;
        iAsyncCallBack = NULL;
        // Function does not allow to leave.
        iAsyncCallBack = new CAsyncCallBack( callBack, CActive::EPriorityHigh );
        if ( iAsyncCallBack )
            {
            iAsyncCallBack->CallBack();
            }
        else
            {
            iModel.SendMessage( MEngineMonitor::EPEMessageStoppedDTMF );
            }
        
        dtmfString = KNullDesC;
        }    
    else if ( dtmfString[ 0 ] == KPEDtmfPlusChar ) // speed-dial substitution
        {
        TEFLOGSTRING( KTAMESINT, "PE CPEMessageHandler::HandleSendDtmf(), Processing +" );
        HandlePlusSignInDtmf( dtmfString );
        dtmfString = KNullDesC;
        }
    else if ( dtmfString[ 0 ] == KPEDtmfPauseCharLowercase || 
              dtmfString[ 0 ] == KPEDtmfPauseCharUppercase ) // soft pause
        {
        TEFLOGSTRING( KTAMESINT, "PE CPEMessageHandler::HandleSendDtmf(), Processing P" );
        
        // store the full string for UI to display 
        iDataStore.SetDtmfString( dtmfString );

        if ( dtmfString.Length() > 1 )
            {
            // store the remainder of the string to be processed later
            iDataStore.SetDtmfStringCommand( dtmfString.Mid( 1 ) ); 
            }
        else
            {
            // nothing left to process
            iDataStore.SetDtmfStringCommand( KNullDesC() );
            }
        // set the dtmf string to send 
        dtmfString = dtmfString.Left( 1 );
        }
    else 
        {
        // store the full string for UI to display 
        iDataStore.SetDtmfString( dtmfString );
        
        // Find the next stop point
        TInt stopPoint = ECCPErrorNotFound;
        TPtrC validDtmfStringStopChars( KPEValidDTMFStringStopChars );
        for ( TInt index = 0 ; index < dtmfString.Length(); index++ )
            {
            if ( validDtmfStringStopChars.Locate( dtmfString[index] ) != ECCPErrorNotFound )
                {
                stopPoint = index;
                break; 
                }
            }

        if ( stopPoint != ECCPErrorNotFound ) 
            {
            // store the remainder of the string to be processed later
            iDataStore.SetDtmfStringCommand( dtmfString.Mid( stopPoint ) ); 
            // set the dtmf string to send 
            dtmfString = dtmfString.Left( stopPoint );            
            }
        else
            {
            // nothing left to process
            iDataStore.SetDtmfStringCommand( KNullDesC() );
            }
        }

    if ( dtmfString.Length() )  
        {
        TEFLOGSTRING2( KTAMESINT, "PE CPEMessageHandler::HandleSendDtmf(), Starting to play %S", &dtmfString );
        // send the dtmf string to call handling subsystem
        errorCode = iCallHandling.SendDtmf( dtmfString );
        }
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::CallBackHandleSendDtmf
// Asyncronous callback for HandleSendDtmf() function.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::CallBackHandleSendDtmf( TAny* aAny )
    {
    __ASSERT_ALWAYS( aAny , Panic( EPEPanicNullPointer ) );
    CPEMessageHandler* self = static_cast<CPEMessageHandler*>(aAny);

    delete self->iAsyncCallBack;
    self->iAsyncCallBack = NULL;
    return self->HandleSendDtmf();  
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandlePlusSignInDtmf
// Handles plus (+) sign in a DTMF string.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandlePlusSignInDtmf(const TPEDtmfString& aDtmfString )
    {
    TEFLOGSTRING2( KTAMESINT, "PE CPEMessageHandler::HandlePlusSignInDtmf(), aDtmfString: %S", &aDtmfString ); 
          
    // Find the SD index after the plus sign
    TPtrC validManualDTMFChars( KPEValidSpeedDialChars );
    TInt index = ECCPErrorNotFound;
    for ( index = 1 ; index < aDtmfString.Length() ; index++ )
        {
        if ( validManualDTMFChars.Locate( aDtmfString[index] ) == ECCPErrorNotFound )
            {
            TEFLOGSTRING( KTAMESINT, "PE CPEMessageHandler::HandlePlusSignInDtmf(), Not Found" ); 
            break; 
            }
        }
    TPESpeedDialSubstituionStatus sdStatus = EPEDtmfSpeedDialOk;
    
    // Empty string after the plus sign
    if ( index == 1 )
        {
        if ( aDtmfString.Length() > 1 )
            {
            // pw+ after the plus sign.
            sdStatus = EPEDtmfSpeedDialInvalidSpeedDial;
            }
        else
            {
            // string ended with the plus sign.
            sdStatus = EPEDtmfSpeedDialPromptUser;
            }
        // Clear DTMF string.
        iDataStore.SetDtmfString( KNullDesC() );
        }
    // Else if the SD location ends the DTMF string, move the index to the
    // last character instead of one over.
    else if ( index == aDtmfString.Length() )
        {
        index--;
        }
    
    // Check that the index is valid
    TInt sdIndex = ECCPErrorNotFound; 
    if ( sdStatus == EPEDtmfSpeedDialOk )
        {
        TLex lexer( aDtmfString.Mid( 1, index ) );
        // convert it to a number
        if ( lexer.Val(sdIndex) == ECCPErrorNone )
            {
            // Is it out of range
            if ( sdIndex < KPESpeedDialIndexMin  ||
                sdIndex > KPESpeedDialIndexMax )
                {
                sdStatus = EPEDtmfSpeedDialInvalidSpeedDial;
                }
            }
        else
            {
            sdStatus = EPEDtmfSpeedDialInvalidSpeedDial;
            }
        }
    
    // Fetch the SD location
    TPEPhoneNumber speedDialLocationString;
    if ( sdStatus == EPEDtmfSpeedDialOk )
        {
        TEFLOGSTRING2( KTAMESINT, "PE CPEMessageHandler::HandlePlusSignInDtmf(), SD location %i", sdIndex ); 
        if ( iContactHandling.GetSpeedDialLocation( 
            sdIndex, speedDialLocationString ) == ECCPErrorNone )
            {
            // Is content found
            if ( speedDialLocationString.Length() == 0)
                {
                sdStatus = EPEDtmfSpeedDialNotAssigned;
                }
            else if ( speedDialLocationString[0] == KPEDtmfPlusChar)  
                {
                // plus char must be removed from dtmf string before sending
                RemovePlusPrefix( speedDialLocationString );
                }
            }
        else
            {
            sdStatus = EPEDtmfSpeedDialInvalidSpeedDial;
            }
        }
    
    // Now interpret the sdStatus to the next action
    switch ( sdStatus )
        {
        case EPEDtmfSpeedDialOk:
            {
            TEFLOGSTRING2( KTAMESINT, "PE CPEMessageHandler::HandlePlusSignInDtmf(), SD result: %S", &speedDialLocationString ); 
            // Take the SD location string and use that as new DTMF string
            iDataStore.SetDtmfStringCommand( speedDialLocationString );
            
            // Do recursion asyncronously                        
            TCallBack callBack( CallBackHandleSendDtmf, this );
            delete iAsyncCallBack;
            iAsyncCallBack = NULL;
            // Function does not allow to leave.
            iAsyncCallBack = new CAsyncCallBack( callBack, CActive::EPriorityStandard );
            if ( iAsyncCallBack )
                {
                iAsyncCallBack->CallBack();
                }
            else
                {
                iModel.SendMessage( MEngineMonitor::EPEMessageDTMFSendingAborted );
                }
            }
            break;
        case EPEDtmfSpeedDialPromptUser:
            // Speed dial location not given.
            iDataStore.SetDtmfString( KNullDesC() );
            iModel.SendMessage( MEngineMonitor::EPEMessagePromptSpeedDial );
            break;
        case EPEDtmfSpeedDialNotAssigned:
            // Speed dial location valid but not assigned
            iDataStore.SetDtmfString( KNullDesC() );
            iDataStore.SetDtmfStringCommand( KNullDesC() );
            iModel.SendMessage( MEngineMonitor::EPEMessageDTMFSendingAborted);
            iModel.SendMessage( MEngineMonitor::EPEMessageSpeedDialNotAssigned );
            break;
        case EPEDtmfSpeedDialInvalidSpeedDial:
            // Speed dial location invalid
            iDataStore.SetDtmfString( KNullDesC() );
            iDataStore.SetDtmfStringCommand( KNullDesC() );
            iModel.SendMessage( MEngineMonitor::EPEMessageDTMFSendingAborted);
            iModel.SendMessage( MEngineMonitor::EPEMessageInvalidSpeedDial );
            break;
        default:
            Panic( EPEPanicInvalidState );
            break;
        } // end switch
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::CheckPrefix
// Checks the status of phone number prefix change setting
// and calls CPEMessageHandler::ChangePrefix for execution.
// If error occurs the phone number is left untouched
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::CheckPrefix()
    {
    TInt err = ECCPErrorNone;
    TBool checkPrefix = 
        FeatureManager::FeatureSupported( KFeatureIdJapanPrefixChange );

    if ( checkPrefix )
        {
        TInt prefixMode = KPEPrefixChangeOff; // Default is "off"

        err = iExternalDataHandler.Get(
            EPEDialPrefixChangeSetting,
            prefixMode );

        if ( !err )
            {
            if ( prefixMode == KPEPrefixChangeOn )
                {
                TPEPrefixText prefixText;
                
                err = iExternalDataHandler.GetText(
                    EPEDialPrefixTextSetting,
                    prefixText );

                if ( !err )
                    {
                    err = ChangePrefix( prefixText );
                    }
                }
            }
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::ChangePrefix
// Executes phone number prefix change.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::ChangePrefix(
    const TPEPrefixText& aPrefixText )
    {
    TInt err = ECCPErrorNone;

    const TInt beginning = 0; // The beginning for replacement.
    TInt replaceLength = 0; // The string length to be replaced.
    TInt location = ECCPErrorNotFound; // The location of searched string.
    TPEPhoneNumber phoneNumber = iDataStore.PhoneNumber();

    // Try to find Japan prefix.
    location = phoneNumber.Find( KPEJapanPrefix );
    if ( location == beginning )
        {
        // The string was found, so make replacement. 
        // Safe because KPEZeroPrefix < KPEJapanPrefix.
        replaceLength = KPEJapanPrefix().Length();
        phoneNumber.Replace( beginning, replaceLength, KPEZeroPrefix );
        }
    else
        {
        // Try to find international prefix.
        location = phoneNumber.Find( KPEIntPrefix );
        if ( location == beginning )
            {
            replaceLength = KPEIntPrefix().Length();
            // The string was found, so try to make replacement. 
            const TInt phoneNumLength = phoneNumber.Length();
            const TInt prefixLength = aPrefixText.Length();

            TInt stringLength = 
                ( phoneNumLength + prefixLength - replaceLength );

            if ( phoneNumber.MaxLength() >= stringLength )
                {
                // There is enough space to make this replace.
                phoneNumber.Replace( beginning, replaceLength, aPrefixText );
                }
            else
                {
                // There is no space to combine the strings, so inform it.
                err = KErrOverflow;
                }
            }
        }

    if ( err == ECCPErrorNone )
        {
        iDataStore.SetPhoneNumber( phoneNumber );
        }

    return err;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDtmfSent
// Handles DTMF sent message from the CallHandling subsystem.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleDtmfSent()
    {
    TInt errorCode( ECCPErrorNone );

    // check if there are still parts of the string left to process
    if ( iDataStore.DtmfStringCommand().Length() ) 
        {
        HandleSendDtmf();
        errorCode = KPEDontSendMessage;
        }
    else 
        {
        // dtmf sending complete
        iDataStore.SetDtmfString( KNullDesC() );
        }
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::StopPlayingDtmf
// Stops/Cancels playing dtmf tones and string (audio feedback and network)
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::StopDtmfSending()
    {
    // cancel subtitution callback:
    if ( iAsyncCallBack )
        {
        iAsyncCallBack->Cancel();
        delete iAsyncCallBack;
        iAsyncCallBack = NULL;
        }

    iCallHandling.StopDtmfSending();
    
    iDataStore.SetDtmfString( KNullDesC() ); 
    iDataStore.SetDtmfStringCommand( KNullDesC() );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSetAudioMute
// Handles audio mute message from the phone application.
// Method fecths mute value from the CPEEngineInfo and then
// Method sets mute value to the AudioHandling subsystem.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleSetAudioMute()
    {
    TEFLOGSTRING( KTAGENERAL, "PE: CPEMessageHandler::HandleSetAudioMute" );
    TBool mute = iDataStore.AudioMuteCommand();
    iGsmAudioData.SetAudioMuteSync( mute );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSetAudioOutput
// Handles audio output from the phone application.
// Method fecths output and note values from the CPEEngineInfo and then
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleSetAudioOutput()
    {
    TEFLOGSTRING( KTAGENERAL, "PE: CPEMessageHandler::HandleSetAudioOutput" );
    return iGsmAudioData.SetAudioOutput( iDataStore.AudioOutputCommand(),
                                      iDataStore.ShowNoteCommand() );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSetAudioVolume
// Handles change volume message from the phone application.
// Method fecths volume value from the CPEEngineInfo and then
// Method sets volume value to the AudioHandling subsystem.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleSetAudioVolume()
    {    
    TInt volume = iDataStore.AudioVolumeCommand();
    TEFLOGSTRING2( KTAGENERAL, "PE: CPEMessageHandler::HandleSetAudioVolume %d", volume );
    iGsmAudioData.SetAudioVolumeSync( volume );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandlePlayDTMFL
// Handles key down event.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandlePlayDTMFL()
    {
    ProcessPlayDTMFL();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleEndDTMF
// Handles key up event.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleEndDTMF()
    {
    return ProcessEndDTMF();
    }
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::SetClientInformation
// Sets client information.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::SetClientInformation(
        const TInt aCallId,  
        const TDesC& aMainPartOfPhoneNumber ) 
    {
    // Other ClientInformation it was already set before, in SetClientData
    // method. Methods is called from HandleClientCallDataL before CallId is known.
    iClientInformation->SetNumber( aMainPartOfPhoneNumber );
    
    iDataStore.SetCallClientInformation( *iClientInformation, aCallId );
    
    const TPECallOrigin& origin = iDataStore.CallOriginCommand();    
    iDataStore.SetCallOrigin( origin, aCallId );    
    }
 
// -----------------------------------------------------------------------------
// CPEMessageHandler::SetClientData
// Sets client dial data to member variable.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::SetClientData(
        const CPhCltDialData& aClientDialData ) 
    {
    CCCECallParameters& params = iDataStore.CallParameters();
    
    iClientDialData = &const_cast<CPhCltDialData&>( aClientDialData );

    iClientInformation->SetName( iClientDialData->Name() );
    
    if ( iClientDialData->CallType() == EPhCltVideo || 
        iClientDialData->CallType() == EPhCltForcedVideo )
        {
        iClientInformation->SetCallType( EPECallTypeVideo );
        iDataStore.SetCallTypeCommand( EPECallTypeVideo );
        params.SetCallType( CCPCall::ECallTypeVideo );
        }
    else if ( iClientDialData->CallType() == EPhCltCallVoIP )
        {
        iClientInformation->SetCallType( EPECallTypeVoIP );
        iDataStore.SetCallTypeCommand( EPECallTypeVoIP );        
        params.SetCallType( CCPCall::ECallTypePS );
        }
    else
        {
        iClientInformation->SetCallType( EPECallTypeCSVoice );
        iDataStore.SetCallTypeCommand( EPECallTypeCSVoice );
        params.SetCallType( CCPCall::ECallTypeCSVoice );
        }
      
    iClientInformation->SetEndOtherCalls( iClientDialData->EndOtherCalls() );
    
    iClientInformation->SetAllowMatch( iClientDialData->AllowMatch() );
    
    iClientInformation->SetContactLink( iClientDialData->ContactLink() );
   
    iClientInformation->SetShowNumber( iClientDialData->ShowNumber() );

    // Not accept 0, TODO Requirement clarification needed, 
    // does service id 0 need special handling!
    if ( iClientDialData->ServiceId() != 0 )
        {
        iDataStore.SetServiceIdCommand( iClientDialData->ServiceId() );
        params.SetServiceId( iClientDialData->ServiceId() );
        }
        
    iDataStore.SetUserToUserInformation( iClientDialData->UUI() );
    
    params.SetBearer( iClientDialData->Bearer() );
    params.SetSubAddress( iClientDialData->SubAddress() );
    
    if ( iClientDialData->SATCall() )
        {
        params.SetOrigin( CCCECallParameters::ECCECallOriginSAT );
        }
    else
        {
        params.SetOrigin( CCCECallParameters::ECCECallOriginPhone );
        }
    }
     
// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleTerminateAllConnections
// Method resets redial timer if active and calls TerminateAllConnection 
// method from the CallHandling subsytem object.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleTerminateAllConnections()
    {
    TInt errorCode( ECCPErrorNone );
    errorCode = iCallHandling.TerminateAllConnections();
    TEFLOGSTRING2( 
        KTAGENERAL, 
        "PE: CPEMessageHandler::HandleTerminateAllConnections: Callhandling::TerminateAllConnections() called, Error code: %d", 
        errorCode );

    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsItCharThatCanDelete
// Checks if character can be delete. If given charter can be located from 
// KPECharsThatCanBeDelete, method returns ETrue else EFalse.
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::IsItCharThatCanDelete( 
        const TChar& aChar ) const
    {
    TPtrC Invalid( KPECharsThatCanBeDelete );

    return Invalid.Locate( aChar ) != ECCPErrorNotFound;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsValidChar
// Checks if character is acceptable. If given charter can be located from 
// KPEClientValidChars, method returns ETrue else EFalse.
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::IsValidChar( 
        const TChar& aChar, //character to be checked
        const TDesC& aValidChars ) const
    {
    return aValidChars.Locate( aChar ) != ECCPErrorNotFound;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::RemoveInvalidChars
// Check all characters validity from descriptor one by one. 
//    (1) If chater is valid then OK and next charter... 
//    (2) If invalid check if that can be delete from string.
//    (3) If it can be delete then DELETE and next charter... 
//    (4) But if charter can NOT be delete then return value is EFalse.
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::RemoveInvalidChars( 
        TDes& aString, //string to be processed
        const TDesC& aValidChars,
        const TBool aCheckForDelete ) const
    {
    TBool returnValue = ETrue;
    TInt index = aString.Length() - 1;

    TEFLOGSTRING2( KTAGENERAL, 
        "PE: CPEMessageHandler::RemoveInvalidChars, String to parse = %S", &aString );

    for ( ; index >= 0; index-- )
        {
        if ( !IsValidChar( aString[ index ], aValidChars ) )//(1)
            {
            if ( !aCheckForDelete 
                || ( aCheckForDelete && IsItCharThatCanDelete( aString[index] ) ) )//(2)
                {
                aString.Delete( index, 1 ); // one character  //(3)
                }
            else
                {
                returnValue = EFalse;//(4) //if String includes alphabets or other forbidden characters return TFalse
                }
            }
        }
    if ( aCheckForDelete )
        {
        TLex input( aString );

        TLexMark start;
        input.Mark( start );

        while ( input.Peek().IsDigit() ) 
            {
            input.Inc();
            }

        TPtrC mainpart( input.MarkedToken( start ) );
        if ( mainpart.Length() )
            {
            aString = mainpart;
            }
    
        if ( input.Remainder().Length() > 0 )
            {
            TPEDtmfString dtmfString = input.Remainder();
            iDataStore.SetDtmfStringCommand( dtmfString );
            }
        else
            {
            TPEDtmfString dtmfString( KNullDesC );
            iDataStore.SetDtmfStringCommand( dtmfString );
            } 
        
        }
    TEFLOGSTRING2( 
        KTAGENERAL, 
        "PE: CPEMessageHandler::RemoveInvalidChars, Parsed string = %S", 
        &aString);
    return returnValue;
    }


// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleGetLifeTimerData
// Reads lifetimerdata from custom api and stores it to engine info
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleGetLifeTimerData() const
    {
    TCCPLifeTimeData lifeTimeData; 
    TCCPLifeTimeDataPckg pckg( lifeTimeData );

    if ( iCallHandling.GetLifeTime( pckg ) )
        {
        TEFLOGSTRING2( 
            KTAGENERAL, 
            "PE: CPEMessageHandler::HandleGetLifeTimerData, iHours = %d", 
            lifeTimeData.iHours);
        TEFLOGSTRING2( 
            KTAGENERAL, 
            "PE: CPEMessageHandler::HandleGetLifeTimerData, iMinutes = %d", 
            lifeTimeData.iMinutes);
            
        iDataStore.SetLifeTimerData( pckg );
        }
    
    return ECCPErrorNone;
    }
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::CallbackSendMessageStoppedDTMF
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::CallbackSendMessageStoppedDTMF( TAny* aAny )
    {
    __ASSERT_ALWAYS( aAny , Panic( EPEPanicNullPointer ) );
    CPEMessageHandler* self = static_cast<CPEMessageHandler*>(aAny);

    delete self->iAsyncCallBack;
    self->iAsyncCallBack = NULL;
    self->iModel.SendMessage( MEngineMonitor::EPEMessageStoppedDTMF ); 

    return ECCPErrorNone;
    }
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::RemovePlusPrefix
// Remove '+' from begin of the string
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::RemovePlusPrefix(
    TPEPhoneNumber& aPhoneNumber )
    {
    TLex input( aPhoneNumber);

    if ( input.Peek() == KPEDtmfPlusChar )
        {
        // remove plus char 
        input.Inc();
        aPhoneNumber = input.Remainder();
        TEFLOGSTRING2( KTAMESINT, 
            "PE CPEMessageHandler::RemovePlusPrefix(), aPhoneNumber: %S"
            , &aPhoneNumber ); 
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleBuildConferenceCall
// Handles Create conference message from phone application.
// Method calls BuildConference method from MPECallHandling object.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleBuildConferenceCall()
    {
    return iCallHandling.BuildConference();
    }


// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleGoOneToOne
// Handles GoOneToOne message from PhoneApplication. Calls GoOneToOne
// method from CallHandling object.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleGoOneToOne()
    {
    TInt callId = iDataStore.CallId();
    __ASSERT_DEBUG( CallIdCheck::IsVoice( callId ), 
        Panic( EPEPanicCallIndexOutOfRange ) );
    return iCallHandling.GoOneToOne( callId );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleAddConferenceMember
// Handles Add conference member message from phone application.
// Method creates AddMember request to the CallHandling object.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleAddConferenceMember()
    {
    TEFLOGSTRING( KTAINT, 
       "PE CPEMessageHandler::HandleAddConferenceMember ");
    return iCallHandling.AddConferenceMember();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleAddConferenceMember
// Handles dropped conference member message from callhandling subsystem.
// In case a long dtmf string is being sent, cancels the sending process.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleDroppedConferenceMember()
    {
    TEFLOGSTRING( KTAINT, 
       "PE CPEMessageHandler::HandleDroppedConferenceMember");
    
    StopDtmfSending();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleCallHandlingError
// Handles error message from CallHandling subsystem
// Method fetches error code from CallHandling subsystem and
// Method sends error code to SAT
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandleCallHandlingError(
        const TInt aCallId,
        const TBool /*aBusyCall*/ )
    {
    // Call data not valid for call id -1, i.e. non-call error situations
    if ( aCallId != KPECallIdNotUsed )
        {
        //Update local call info
        const TInt errorCode = iCallHandling.GetCallInfo( *iCallInfo, aCallId );
        
        // Take the error from call handling.
        TInt errorForClient = iDataStore.ErrorCode(); 
        if (  errorCode == ECCPErrorNone )
            {
            const TInt diagnosticInfo = 
                iCallHandling.CallTerminatedError( aCallId );
            if ( diagnosticInfo != ECCPErrorNone )
                {
                errorForClient = diagnosticInfo;
                }
            }
        
        TEFLOGSTRING2( KTAINT,
                "PE CPEMessageHandler::HandleCallHandlingError, SendRespond errorForClient: %d", errorForClient );
        iClientServices->CallRequestMonitor()->SendRespond( errorForClient );            
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleEngineInfo
// Handles call logging. Method add and update the call info.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleEngineInfo(
    const TInt aCallId )       
    {
    TEFLOGSTRING2( KTAINT,
        "PE CPEMessageHandler::HandleEngineInfo, call id: %d", aCallId );
    TInt errorCode(  ECCPErrorNone );
    TPEState callState;
    
    errorCode = FindCallInfo( aCallId );

    if ( !errorCode )
        {
        callState = iCallHandling.GetCallState( aCallId );
        TEFLOGSTRING2( KTAINT, 
            "PE CPEMessageHandler::HandleEngineInfo, call state: %d", 
            callState );

        SetPhoneNumberForCallLogging( aCallId );

        if ( callState == EPEStateDialing || callState == EPEStateRinging )
            {
            errorCode = UpdateClientInfo( aCallId );

            iDataStore.SetRemoteIdentity( 
                static_cast< RMobileCall::TMobileCallRemoteIdentityStatus > ( 
                    iCallInfo->iRemoteParty.iRemoteIdStatus ), 
                aCallId );
            iTime.UniversalTime();
            iDataStore.SetCallStartTime( iTime, aCallId );
            iDataStore.SetCallDuration( 0, aCallId );
            }

        // Calls have to log also without a contact (ECCPErrorNotFound).
        if ( errorCode == ECCPErrorNone || errorCode == ECCPErrorNotFound)
            {
            errorCode = ECCPErrorNone;
            
            // If call is emergency call, phonenumber must be fetched from engine info
            // Log type must be recognized from call id also, because in idle state
            // TSY has cleaned call info information
            CheckAndHideIdentity( aCallId );

            // Save the rest of information to EngineInfo.
            SetLoggingInfo( aCallId, callState );
            // Set missed call to EngineInfo.
            IsMissedCall( aCallId, callState );
            errorCode = iLogHandling.SaveCallEntry( aCallId );
            }
        } //if ( !errorCode )
        
    return errorCode;
    }   
 
// -----------------------------------------------------------------------------
// CPEMessageHandler::UpdateClientInfo
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::UpdateClientInfo( 
    const TInt aCallId )
    {
    TInt errorCode( ECCPErrorNone );
    const MPEClientInformation& clientInformation = iDataStore.CallClientInformation( aCallId );
    
    TEFLOGSTRING2( 
        KTAINT, 
        "PE CPEMessageHandler::UpdateClientInfo, remote name: '%S'", 
        &iDataStore.RemoteName( aCallId ) );

    TEFLOGSTRING2( 
        KTAINT, 
        "PE CPEMessageHandler::UpdateClientInfo, name: '%S'", 
        &clientInformation.Name() );

    TEFLOGSTRING2( 
        KTAINT, 
        "PE CPEMessageHandler::UpdateClientInfo, allowmatch: %d", 
        clientInformation.AllowMatch() );
    
    if ( clientInformation.AllowMatch() && ( aCallId != KPEEmergencyCallId ) )
        {
        TEFLOGSTRING2( 
            KTAINT, 
            "PE CPEMessageHandler::UpdateClientInfo, match phone number: '%S'", 
            &iDataStore.RemotePhoneNumber( aCallId ) );
        if ( clientInformation.ContactLink().Length() > 0 )
            {
            errorCode = iContactHandling.FindContactInfoSync( 
            aCallId, 
            EPEFindWithContactId );
            }    
        else
            {
            errorCode = iContactHandling.FindContactInfoSync( 
            aCallId, 
            EPEFindWithPhoneNumber );            
            }
            
        TEFLOGSTRING2( 
            KTAINT, 
            "PE CPEMessageHandler::UpdateClientInfo > MPEContactHandling::FindContactInfoSync( EPEFindWithPhoneNumber ), error code: %d", 
            errorCode );
        }
    else if ( clientInformation.Name().Length() )
        {
        iDataStore.SetRemoteName( clientInformation.Name(), aCallId );
        }
    
    // Calls have to log also without a contact (ECCPErrorNotFound).
    if ( errorCode == ECCPErrorNone || errorCode == ECCPErrorNotFound)
        {
        // Set name to EngineInfo
        SetName( aCallId );
        }
     return errorCode;   
     }   
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::CheckAndHideIdentity
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::CheckAndHideIdentity(
    const TInt aCallId )   
    {
    // If call is emergency call, phonenumber must be fetched from engine info
    // Log type must be recognized from call id also, because in idle state
    // TSY has cleaned call info information
    RMobileCall::TMobileCallRemoteIdentityStatus tempIdentity;
    tempIdentity = iDataStore.RemoteIdentity( aCallId );
    
    TEFLOGSTRING2( KTAINT,
        "PE CPEMessageHandler::CheckAndHideIdentity, Identity: %d", tempIdentity );
    if ( iCallInfo->iEmergency || aCallId == KPEEmergencyCallId ) 
        {
        iDataStore.SetRemotePhoneNumberType( EPEEmergencyNumber, aCallId );
        }
    else if( iDataStore.CallDirection( aCallId ) != RMobileCall::EMobileOriginated )
		{
		switch( tempIdentity )
			{
			case RMobileCall::ERemoteIdentitySuppressed:
				{
				// It is neccessary to perform an additional check for available
				// remote party phone number to comply with Italian operator
				// requirement: "If CLIR is active but network still provides
				// the device with a phone number, it should not be blocked
				// but passed to a client when requested."
				if( iDataStore.RemotePhoneNumber( aCallId ).Length() == 0 )
					{
					HideIdentification( EPEPrivateNumber, aCallId );
					}
				else
				    {
				    // Align remote identity with remote phone number availability.
				    iDataStore.SetRemoteIdentity( RMobileCall::ERemoteIdentityAvailable, aCallId );
				    }
				break;
				}
			case RMobileCall::ERemoteIdentityAvailableNoCliRejectedByUser:
				{
				HideIdentification( EPEPrivateNumber, aCallId );
				break;
				}
			case RMobileCall::ERemoteIdentityUnknown:
			case RMobileCall::ERemoteIdentityAvailableNoCliInteractionWithOtherService:
			case RMobileCall::ERemoteIdentityUnavailableNoCliInteractionWithOtherService:
			case RMobileCall::ERemoteIdentityAvailableNoCliCoinOrPayphone:
			case RMobileCall::ERemoteIdentityUnavailableNoCliCoinOrPayphone:
			case RMobileCall::ERemoteIdentityAvailableNoCliUnavailable:
				{
				HideIdentification( EPEUnknownNumber, aCallId );
				break;
				}
			case RMobileCall::ERemoteIdentityAvailable:
			default:
				{
				TEFLOGSTRING( KTAINT,
					"PE CPEMessageHandler::CheckAndHideIdentity, CLI available" );
				break;
				}
			}
		}
	}
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::FindCallInfo
// Return callInfo from Etel/TSY.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::FindCallInfo(
        const TInt aCallId )
    {
    TInt errorCode( ECCPErrorNone );
    if ( CallIdCheck::IsVoice( aCallId ) || CallIdCheck::IsVideo( aCallId ) )
        {
        // Single call
        errorCode = iCallHandling.GetCallInfo( *iCallInfo, aCallId );
        TEFLOGSTRING3( 
            KTAREQOUT, 
            "CNT CPEMessageHandler::FindCallInfo > MPECallHandling::GetCallInfo, call id: %d, error code: %d", 
            aCallId, 
            errorCode );
        TEFLOGSTRING2( 
            KTAINT, 
            "CNT CPEMessageHandler::FindCallInfo, remote number: '%S'", 
            &iCallInfo->iRemoteParty.iRemoteNumber );
        TEFLOGSTRING2( 
            KTAINT, 
            "CNT CPEMessageHandler::FindCallInfo, direction: %d", 
            iDataStore.CallDirection( aCallId ) );
        TEFLOGSTRING2( 
            KTAINT, 
            "CNT CPEMessageHandler::FindCallInfo, id status: %d", 
            iCallInfo->iRemoteParty.iRemoteIdStatus );
        }
    else
        {
        // We don't log the master conference call and other unknown calls.
        errorCode = KErrUnknown;
        }
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::SetPhoneNumberForCallLogging
// Set phonenumber for call logging
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::SetPhoneNumberForCallLogging(
        const TInt aCallId )
    {
    // if call is MO then the phonenumber must be stored from dialled party.
    if ( iDataStore.CallDirection( aCallId ) == RMobileCall::EMobileOriginated )
        {

        TPEPhoneNumber number;        
        const TPECallOrigin origin = iDataStore.CallOrigin( aCallId );
        
        if ( origin == EPECallOriginSAT )
            {
            // Dont set for SAT calls >> number not logged
            }
        else if( iDataStore.PhoneNumber().Length() )
            {
            // Phonenumber given by user, includes pfe- and postfix.
            number = iDataStore.PhoneNumber();
            }   
        else
            {
            // If call is made using ETel api, then phonenumber must take from callinfo.
            number = iCallInfo->iDialledParty.iTelNumber;
            }
        
        
        // WholeOutgoingPhoneNumber should set only one time because in connected state 
        // PhoneNumber is cleaned from datastore.
        if( !iDataStore.WholeOutgoingPhoneNumber( aCallId ).Length() )
            {
        
            TEFLOGSTRING2( KTAINT,
                    "PE CPEMessageHandler::SetPhoneNumberAndDataCallLogging, number: '%S'"
                    ,&number );
            iDataStore.SetWholeOutgoingPhoneNumber( number, aCallId ); 
            }
        
        // RemotePhoneNumber should set only one time because user can edit DataStore::PhoneNumber after dialing was started.
        if( !iDataStore.RemotePhoneNumber( aCallId ).Length() )
            {
            TEFLOGSTRING3( 
                KTAMESINT, 
                "PE CPEMessageHandler::SetPhoneNumberForCallLogging, remote phone number: '%S', call id: %d", 
                &number, aCallId );
                                         
            RemovePreAndPostFix( number );
  
            iDataStore.SetRemotePhoneNumber( number, aCallId );
            }            
        }
    else if ( iDataStore.CallDirection( aCallId ) == RMobileCall::EMobileTerminated )
        {
        iDataStore.SetRemotePhoneNumber( iCallInfo->iRemoteParty.iRemoteNumber.iTelNumber, aCallId );
        TEFLOGSTRING2( 
            KTAMESINT, 
            "PE CPEMessageHandler::SetPhoneNumberForCallLogging: remote phone number: '%S'", 
            &iCallInfo->iRemoteParty.iRemoteNumber.iTelNumber );
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::SetLoggingInfo
// Store call information for logging
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::SetLoggingInfo(
        const TInt aCallId,
        TPEState aCallState )
    {
    if ( aCallState == EPEStateConnected )
        {
        iDataStore.SetCallStartTime( iCallInfo->iStartTime, aCallId );   
        }
    iDataStore.SetCallForwarded( iCallInfo->iForwarded, aCallId );
    iDataStore.SetCallService( iCallInfo->iService, aCallId );
    iDataStore.SetCallState( aCallState, aCallId );
    iDataStore.SetCallDuration( iCallInfo->iDuration.Int() );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::SetName
// Set calling name or client name to RemoteInfo.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::SetName( const TInt aCallId )
    {
    if ( iDataStore.RemoteName( aCallId ).Length() <= 0 &&
         iDataStore.RemoteCompanyName( aCallId ).Length() <= 0 &&
         iCallInfo->iRemoteParty.iCallingName.Length() >0 ) 
        { 
        iDataStore.SetRemoteName( iCallInfo->iRemoteParty.iCallingName, aCallId );
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HideIdentification
// Hide identification to RemoteInfo.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HideIdentification(
        TPEPhoneNumberIdType aPhoneNumberId,
        const TInt aCallId )
    {
    TEFLOGSTRING2( KTAINT,
        "PE CPEMessageHandler::HideIdentification: aPhoneNumberId = %d", aPhoneNumberId );
    iDataStore.SetRemotePhoneNumberType( aPhoneNumberId, aCallId );
    iDataStore.SetRemotePhoneNumber( KNullDesC(), aCallId );
    iDataStore.SetRemoteName( KNullDesC(), aCallId );
    iDataStore.SetRemotePartyName( KNullDesC(), aCallId );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsMissedCall
// Check missed call in the idle state.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::IsMissedCall(
        const TInt aCallId,
        TPEState aCallState )
    {
    if ( iDataStore.CallDirection( aCallId ) == RMobileCall::EMobileTerminated )
        {
        // If remote party has hanged up the current call on Ringing state, 
        // this call is the missed call in the idle state.
        if ( aCallState == EPEStateIdle )
            {
            TBool missedCall = EFalse;

            if ( CallIdCheck::IsVoice( aCallId ) || CallIdCheck::IsVideo( aCallId ) )
                {
                iCallHandling.GetMissedCall( missedCall, aCallId );
                }

            iDataStore.SetMissedCall( missedCall, aCallId );
            } 
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleCancelSSstringCommand
// Handles cancel SS string command.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleCancelSSstringCommand()
    {
    TInt returnValue( ECCPErrorNone );

    returnValue = iSSHandler->Cancel();

    return returnValue;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleConferenceIdleState
// Handles EPEMessageConferenceIdle message.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleConferenceIdleState( 
        const TInt aCallId )
    {
    TInt counter;
    TInt conferenceValue;

    TTimeIntervalSeconds duration;
    TInt errorCode = iCallHandling.GetCallDuration( duration, aCallId );
    
    // Duration offset is stored previously to data store using conference members
    // duration. If we do not check for null here then the stored offset is ignored..
    if ( ECCPErrorNone == errorCode && duration.Int() > 0 ) 
        {
        // Set last conference duration
        iDataStore.SetCallDuration( duration.Int() );
        }
    else if ( ECCPErrorNone == errorCode && duration.Int() == 0 )
        {
        // copy conference call duration to last call duration
        // all call specific data is erased a few lines down
        iDataStore.SetCallDuration( iDataStore.CallDuration( aCallId ).Int() );
        }   

    //Reset values to the TPECallInfo structure
    iDataStore.ResetCallInfo( aCallId );

    // Reset Conference Master info from all ex-members
    for ( counter = 0; counter < KPEMaximumNumberOfVoiceCalls; counter++ )
        {
        conferenceValue = iDataStore.CallConference( counter );
        if ( conferenceValue == aCallId )
            {
            iDataStore.SetCallConference( KPENormalVoiceCall, counter );
            }
        }
    
    //Stops possible ringing tone playing
    //APS Stops possible remote alerting tone playing
    TEFLOGSTRING( KTAMESINT, 
        "PE  CPEMessageHandler::HandleConferenceIdleState > iGsmAudioData.StopInbandTonePlay()");
    iGsmAudioData.StopInbandTonePlay(); 
    
    ClearCallAudio();    
        
    return ECCPErrorNone;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleConnectedState
// Handles connected message from the CallHandling subsystem 
// 
//  Method fetches call state and ALS line values from the Callhandling subsystem and then
//  Method fetches remote information from the CPEEngineInfo class and then
//  Method sets new values to the logInfo parameters and then
//  Method updates call values to the LogHandling subsystem and then
//  Method sets new values to the CPEEngineInfo class and then
//  Method fecths possible dtmf string from the CPEParserPhoneNumberHandler class and then
//  Method calls HandleSendDtmf method if dtmf string lenght was more than zero.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleConnectedState( 
        const TInt aCallId )
    {
    TInt errorCode( ECCPErrorNone );
    TPEState callState;
    TPEDtmfString dtmfString;

    RMobileCall::TMobileCallDirection callDirection;
    callDirection = iDataStore.CallDirection( aCallId );

    //Stops possible local playing of remote alerting tone
    TEFLOGSTRING( 
        KTAMESINT, 
        "PE  CPEMessageHandler::HandleConnectedState: Calling iGsmAudioData.StopInbandTonePlay()");
    iGsmAudioData.StopInbandTonePlay();

    //If call was held then no logging is done.
    callState = iDataStore.CallState( aCallId );
    if ( callState != EPEStateHeld )
        {
        errorCode = HandleEngineInfo( aCallId );

        // If phone number has contained dtmf string, phone engine sends dtmf string now.
        // Only in MO - call.

        if ( callDirection == RMobileCall::EMobileOriginated )
            {
            if ( aCallId == KPEEmergencyCallId )
                {
                dtmfString = iDataStore.DtmfStringCommand();
                if ( dtmfString.Length() > 0 )
                    {
                    errorCode = HandleSendDtmf();
                    }
                }
             else 
                {

                dtmfString = iDataStore.DtmfPostFix( aCallId );
				
                if ( dtmfString.Length() > 0 )
                    {
                    iDataStore.SetDtmfStringCommand( dtmfString );
                    errorCode = HandleSendDtmf();
                    }
                }
            // Reset unattended transfer callback flag
            iDataStore.SetDoCallBackRequest( EFalse, aCallId );
            
            iDataStore.SetErrorCode( errorCode );
            }  
		}
    // For Sat call ( normal or emergency )    
    iClientServices->CallRequestMonitor()->SendRespond( ECCPErrorNone );
    
    
    
    // Reset Phonenumber from engine info, this is necessary so that call number
    // logging works OK (see CPEMessageHandler::SetPhoneNumberForCallLogging).  
    iDataStore.SetPhoneNumber( KNullDesC() );
    
    return ECCPErrorNone;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDialCall
// Handles dial message from phone application
// 
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDialCall(
    const TBool aClientCall )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDialCall" );
    TInt errorCode( ECCPErrorNone );

    TRAPD( trapError, errorCode = HandleDialCallL( aClientCall ));

    if ( trapError )    
        {
        if ( aClientCall )    
            {
            iClientServices->CallRequestMonitor()->SendRespond( trapError );                    
            }
        TEFLOGSTRING2( KTAINT, "PE CPEMessageHandler::HandleDialCall: trapError = %d", trapError );
        return trapError;
        }
    return errorCode;
    }


// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDialEmergencyCall
// Handles dial message from phone application
// 
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDialEmergencyCall(
    const TBool aClientCall )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDialEmergencyCall" );
    TInt errorCode( ECCPErrorNone );

    if( iEmergencyCallActive && aClientCall )
        {
        // Client tried to make an emergency call even though we already
        // have an active emergency call.
        iClientServices->CallRequestMonitor()->SendRespond( ECCPErrorAlreadyInUse );
        // Notify PhoneApp which is responsible for showing the error note
        return ECCPErrorAlreadyInUse;
        }
    
    iDataStore.SetCallTypeCommand( EPECallTypeCSVoice );
        
    // Check the phone number and change the prefix if needed
    CheckPrefix();
    
    if ( aClientCall )
        {
        TPEPhoneNumber phoneNumber = iDataStore.PhoneNumber();
        __ASSERT_DEBUG( !( phoneNumber == KNullDesC ), Panic( EPEPanicInvalidParameter));

        TBuf<KPEPhoneNumberMaxLength> tempPhoneNumber = phoneNumber;
        RemoveInvalidChars( tempPhoneNumber, KPEClientValidChars, ETrue );
        RemovePreAndPostFix( tempPhoneNumber );
        
        SetClientInformation( KPEEmergencyCallId, tempPhoneNumber );
        iClientServices->CallRequestMonitor()->SendRespond( ECCPErrorNone );
        }

    if ( IsActiveVideo() )
        {
        // PhoneApp needs to request releasing of data port from video telephony engine
        // Emergency call initialization will continue after receiving MPEPhoneModel::
        // EPEMessageContinueEmergencyCallInitialization
        iModel.SendMessage( MEngineMonitor::EPEMessageInitiatedEmergencyWhileActiveVideo );
        }
    else
        {
        ContinueDialEmergency();
        }

    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDialCallL
// Handles dial message from phone application
// 
//  Method fecths phone number from the CPEEngineInfo class and then
//  Method sets process type to the CPEParserPhoneNumberHandler and then
//  Method fecths clir settings from the Settings utility subsystem and tehn
//  Method fecths call parameters from the CallHandling subsystem and then
//  Method sets updated call parameter to the CallHandling subsystem and then
//  Method parsers phonenumber and then
//  Method process parsing result with PhoneParser
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDialCallL(
    const TBool aClientCall )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDialCallL" );
    TBool parsingResult;
    TPEPhoneNumber phoneNumber;
    TInt errorCode( ECCPErrorNone );
    TInt numberOfCalls;
    
    if ( aClientCall )
        {
        HandleClientCallData();
        }
    else
        {
        ResetClientCallData();
        }
        
    //Get number of calls
    numberOfCalls = iCallHandling.GetNumberOfCalls();

    // Check the phone number for prefix change and change the prefix if needed
    CheckPrefix();

    if( iSwitchToVidCalReconFlag )
        {
        phoneNumber = iDataStore.SwitchToNumberCommand();
		// Clear flag to match the previous set operation in HandleSwitchToVideoOrVoice() function.
        iSwitchToVidCalReconFlag = EFalse;
        }
    else
        {
        phoneNumber = iDataStore.PhoneNumber();
        }
    
    __ASSERT_ALWAYS( !( phoneNumber == KNullDesC ), User::Leave( ECCPErrorInvalidPhoneNumber ));
    
    // Number parser operations
    iOptions->SetOptionStatus( KPhoneOptionSend, ETrue );
    iOptions->SetOptionStatus( KPhoneOptionInCall, numberOfCalls > 0 );
    // If voip call request
    if( iDataStore.CallTypeCommand() == EPECallTypeVoIP )
        {
        iOptions->SetOptionStatus( KPhoneOptionVoipCall, ETrue );
        }
    else
        {
        iOptions->SetOptionStatus( KPhoneOptionVoipCall, EFalse );
        }

    parsingResult = iParser->ParseL( phoneNumber, *iResult, *iOptions );
    if ( parsingResult )
        {
        iGsmParserErrorCode = ECCPErrorNone;
        iParserHandlerContainer->ProcessL( *iResult );
        errorCode = iGsmParserErrorCode;
        }
    else
        {
        // string was not recognised by any of the parser objects
        TEFLOGSTRING( KTAERROR, 
            "PE CPEMessageHandler::HANDLEDIALCALLL: PHONEPARSER DID NOT RECOGNIZE THE STRING!" );
        errorCode = KErrArgument;
        }

    if ( aClientCall )
        {
        // Do not sent the response to SAT, unless there is error.
        const TPECallOrigin& origin = iDataStore.CallOriginCommand();            
        if ( origin != EPECallOriginSAT || errorCode )    
            {
            iClientServices->CallRequestMonitor()->SendRespond( errorCode );                    
            }
        }

    TEFLOGSTRING2( KTAINT, "PE CPEMessageHandler::HandleDialCallL: errorCode = %d", errorCode );
        
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::ResetClientCallData
// Reset CCCECallParameters to prevent of use a previous call´s parameters
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::ResetClientCallData()
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::ResetClientCallData()" );

    CCCECallParameters& params = iDataStore.CallParameters();
    params.SetLineType( CCCECallParameters::ECCELineTypePrimary );
    params.SetUUSId( KNullDesC() );
    params.SetBearer( KNullDesC8() );
    params.SetSubAddress( KNullDesC() );
    params.SetOrigin( CCCECallParameters::ECCECallOriginPhone );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSatCallRequestCompleted
// Sends respond to SAT after dial request completion
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandleSatCallRequestCompleted()
    {
    // Monitor with active request completes
    iClientServices->CallRequestMonitor()->
        SendRespond( iCallHandling.CallTerminatedError( iDataStore.CallId() ));                    
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDialEmergency
// Handles emergency call message from phone application
//
//  Method calls DialEmergencyCall method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::ContinueDialEmergency()
    {
    iDataStore.SetCallId( KPEEmergencyCallId );
    if ( !iEmergencyCallActive )
        {
        iExternalDataHandler.Set( EPEEmergencyCallInfo, ETrue );  
        iEmergencyCallActive = ETrue;        
        }
        // unmute mic
        iDataStore.SetAudioMuteCommand( EFalse );
        HandleSetAudioMute();

    iCallHandling.DialEmergencyCall( iDataStore.PhoneNumber() );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDialingStateL
// Handles dialing state transition for voice and video calls
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandleDialingStateL( 
        const TInt aCallId )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDialingStateL <");
    
    if( iCallHandling.GetNumberOfCalls() == 1 )
        {
        // Check volume levels - zero level needs to be reset to default value
        iGsmAudioData.SetDefaultVolume();
        }
    // Save call direction to engine info.
    iDataStore.SetCallDirection( RMobileCall::EMobileOriginated, aCallId );
    
    // Log the call information.
    User::LeaveIfError( HandleEngineInfo( aCallId ) );
    
    // publish remote party info to Mediator after contact matching is done
    // as remote party info contains information from contact matching. 
    UpdateRemotePartyInfo();
    
    TBool videoCall =
        ( iDataStore.CallType( aCallId ) == EPECallTypeVideo ) ? ETrue : EFalse;

    TEFLOGSTRING2(
            KTAINT,
            "CPEMessageHandler::HandleDialingStateL, callType: %d",
            iDataStore.CallType( aCallId ) );
        
    // Determine the preferred output for call audio and route accordingly.
    // Routing for incoming voice call is done in answering state.
    HandleAudioRouting( videoCall, aCallId );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleIncomingCallL
// Handles incoming voice and video call
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleIncomingCallL( 
        const TInt aCallId )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleIncomingCallL <");
    
    // Save call direction to engine info.
    iDataStore.SetCallDirection( RMobileCall::EMobileTerminated, aCallId );

    // Log the call information.
    User::LeaveIfError( HandleEngineInfo( aCallId ) );
    
    // publish remote party info to Mediator after contact matching is done
    // as remote party info contains information from contact matching. 
    UpdateRemotePartyInfo();    
    
    TInt numberOfCalls = iCallHandling.GetNumberOfCalls();
    
    if( numberOfCalls > 1 )
        {
        TEFLOGSTRING( 
            KTAMESINT, 
            "PE  CPEMessageHandler::HandleIncomingCallL: Calling iGsmAudioData->PlayInbandTone() for call waiting tone");
        iDataStore.SetInbandTone( ECCPCallWaiting );
        iGsmAudioData.PlayInbandTone();
        iWaitingCallId = aCallId;
        }
    else if( numberOfCalls == 1 )
        {
        // Check volume levels - zero level needs to be reset to default value
        iGsmAudioData.SetDefaultVolume();
        }
    if( AutomaticAnswer( aCallId ) )
        {
        TEFLOGSTRING( KTAINT, 
        "PE  CPEMessageHandler::HandleIncomingCallL: iAutomaticAnswerTimer->StartTimer");
        iAutomaticAnswerTimer->StartTimer( KPEAutomaticAnswerTimeOut, MEngineMonitor::EPEMessageAnswer, aCallId );
        }

    // Cancel EnableService, if in progress
    iServiceHandling.CancelServiceEnabling();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDisconnecting
// Handles disconnecting. This means network doesn't play inband tones, but PE must play those.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDisconnecting
        (
        const TInt /*aCallId*/  //The identification number of the call.
        )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDisconnecting" );

    iAutomaticAnswerTimer->Cancel();

    // Prevent playing inband tone when phone is in silent mode and 
    // audio output is not defined (call is  not connected).
    if ( ( iDataStore.RingingType() != EProfileRingingTypeSilent ) || 
         ( iDataStore.AudioOutput() != EPENotActive ) )
        {
        TEFLOGSTRING( KTAMESOUT, 
        "PE CPEMessageHandler::HandleDisconnecting > iGsmAudioData.PlayInbandTone()");
        iGsmAudioData.PlayInbandTone();
        }

    return ECCPErrorNone;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDisconnectingWithInband
// Handles disconnecting with inband. This means network plays the inband tones
// and PhoneEngine does not.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDisconnectingWithInband(
        const TInt /*aCallId*/ )
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDisconnectingWithInband" );
    return ECCPErrorNone;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDropConferenceMember
// Handles drop message from phone application
// Method calls DropMember method from CallHandling object.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleDropConferenceMember()
    {
    TInt callId = iDataStore.CallId();
    __ASSERT_DEBUG( CallIdCheck::IsVoice( callId ), 
        Panic( EPEPanicCallIndexOutOfRange ) );
    return iCallHandling.DropMember( callId );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleHoldCall
// Handles hold message from phone application
// Method fecths call id number from the CPEEngineInfo class and then
// Method calls HoldCall method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleHoldCall()
    {
    return iCallHandling.HoldCall();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleVoiceCallIdleState
// Handles idle message from the CallHandling subsystem.
//
//  Method stops playing possible ringing tone and the
//  Method gets call and ALS line information from the CallHandling subsystem and then
//  Method fecth remote party information from the CPEEngineInfo class and then
//  Method sets new values to the logInfo parameter and then
//  Method updates log values to the LogHandling subsystem and then
//  Method updates Engine Info's call terminated diagnostics value and then
//  Method resets call information.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleVoiceCallIdleState( 
    const TInt aCallId )
    {
    TInt errorCode( ECCPErrorGeneral );
    TInt returnValue( ECCPErrorNone );
    TInt numberOfCalls;

    //Stops possible ringing tone playing
    //APS Stops possible remote alerting tone playing
    TEFLOGSTRING( KTAMESINT, 
        "PE  CPEMessageHandler::HandleVoiceCallIdleState > iGsmAudioData.StopInbandTonePlay()");
    iGsmAudioData.StopInbandTonePlay(); 
    
    ClearCallAudio();
    
    errorCode = iCallHandling.GetCallInfo( *iCallInfo, aCallId );
    
    if (  errorCode == ECCPErrorNone )
        {
        TInt diagnosticInfo = iCallHandling.GetCallTerminatedDiagnostics( 
            iCallInfo->iCallName );
        // if diagnosticInfo available set diagnostic error code to DataStore    
        if ( diagnosticInfo != ECCPErrorNone )
            {
            iDataStore.SetErrorCode( diagnosticInfo );
            }
        }

    errorCode = HandleEngineInfo( aCallId );  
    iDataStore.SetErrorCode( ECCPErrorNone );

    numberOfCalls = iCallHandling.GetNumberOfCalls();

    if ( numberOfCalls == 0 )
        {
        // unmute mic
        iDataStore.SetAudioMuteCommand( EFalse );
        HandleSetAudioMute();
        
        if ( iEmergencyCallActive )
            {
            iExternalDataHandler.Set( EPEEmergencyCallInfo, EFalse );
            iEmergencyCallActive = EFalse;
            }
        }

    // If there is a waiting call (voice or data) on 
    // the line, and no other calls, play ringing tones for it.
    else if ( numberOfCalls == 1 )
        {
        TPEState callState;
        callState = iCallHandling.GetCallState( iWaitingCallId );
        // EPEStateRinging equals MT call
        if( callState == EPEStateRinging )
            {
            // unmute mic
            iDataStore.SetAudioMuteCommand( EFalse );
            HandleSetAudioMute();
            TEFLOGSTRING2( KTAMESINT, 
                "CPEMessageHandler::HandleVoiceCallIdleState: aCallId = %d", 
                aCallId );
            }
        else 
            {
            TEFLOGSTRING2( KTAMESINT, 
                "CPEMessageHandler::HandleVoiceCallIdleState: callState = %d", 
                callState );
            }
        }
    else
        {
        TEFLOGSTRING2( KTAMESINT, 
            "CPEMessageHandler::HandleVoiceCallIdleState: numberOfCalls = %d", 
            numberOfCalls );
        }
    
    if ( iDataStore.DoCallBackRequest( aCallId ) )
        {
        iModel.SendMessage( MEngineMonitor::EPEMessageTransferCallBackRequest, aCallId );
        }
    
    iDataStore.ResetCallInfo( aCallId );    
    
    //publish remote party info to Mediator after call info has been cleared.
    UpdateRemotePartyInfo();    

    return returnValue;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::ProcessPlayDTMFL
// Handles key down message from phone application
//
//  Method fecths key code value from the CallHandling subsystem and then
//  Method calls StartDtmfTone method from the CallHandling subsystem.

// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::ProcessPlayDTMFL()
    {
    const TChar keyCode = iDataStore.KeyCode();
    
    TBuf<1> keyCodeBuf;
    keyCodeBuf.Append( keyCode );
    
    if ( KPEValidDTMFChars().Find( keyCodeBuf ) >= 0 )
        {
        if ( iCallHandling.GetNumberOfCalls() > 0 )
            {   //There is ongoing call(s)
            iCallHandling.StartDtmfTone( keyCode );
            }
        else
            {
            iGsmAudioData.PlayDtmfTone( keyCode );            
            }
        }
        
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::ProcessEndDTMF
// Handles end playing DTMF message from phone application
// Method calls StopDtmfTone method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::ProcessEndDTMF()
    {
    TInt returnValue( ECCPErrorNone ); 
    // Number parser operations
    if ( iCallHandling.GetNumberOfCalls() > 0 )
        {   //There is ongoing call(s)
        returnValue =  iCallHandling.StopDtmfTone();
        }
    iGsmAudioData.StopDtmfTonePlay();
    return returnValue;
    }


// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleRejectCall
// Handles reject message from phone application
//  Method stops playing possible ringing tone and then
//  Method calls RejectCall method from the CallHandling subsystem.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleRejectCall
        (
        // None.
        )
    {
    //Stops playing ringing tone
    //Data call
    iGsmAudioData.StopInbandTonePlay(); 
    iAutomaticAnswerTimer->Cancel();
    return iCallHandling.RejectCall( );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleResumeCall
// Handles resume message from phone application
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleResumeCall()
    {
    return iCallHandling.ResumeCall();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSendUssd
// Handles request from CPEParserMiscHandler
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleSendUssd(
        const TDesC& aString )   // USSD string to be sent.

    {
    return iClientServices->SendUssd( aString );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSimStateChanged
// Handles EPEMessageSIMStateChanged message from DosServer.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandleSimStateChanged()  
    {
    iDataStore.SetSimState( iSimStateMonitor.SimState() );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleStartUpL
// Handles startup message from the phone application.
// Method calls StartUp method from the CallHandling subsystem and then
// Method calls StartUp method from the AudioHandling subsystem and then
// Method starts monitoring client originated calls.
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandleStartUp()
    {
    iCallHandling.StartUp( );
    iGsmAudioData.StartUp( );
    
    iClientServices->StartMonitoring( );
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleVideoCallConnected
// Handles data call logging in connected and idle state.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleVideoCallConnected(
        const TInt aCallId )
    {
    //Stops possible remote alerting tone playing
    TEFLOGSTRING( 
        KTAINT, 
        "PE  CPEMessageHandler::HandleVideoCallConnected > CPEGsmAudioData::StopInbandTonePlay()");
    iGsmAudioData.StopInbandTonePlay(); 
    // EFalse updates log information.
    TInt errorCode = HandleEngineInfo( aCallId );
    iDataStore.SetErrorCode( errorCode );
    return ECCPErrorNone; 
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleVideoCallIdle
// Handles data call logging and a possible waiting voice call in Idle state.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleVideoCallIdle(
        const TInt aCallId )
    {
    TInt numberOfCalls;
    //Stops possible remote alerting tone playing
    TEFLOGSTRING( KTAINT,
        "PE CPEMessageHandler::HandleVideoCallIdle > CPEGsmAudioData::StopInbandTonePlay()");
    iGsmAudioData.StopInbandTonePlay(); 
    HandleEngineInfo( aCallId );
    iDataStore.SetErrorCode( ECCPErrorNone );
    TInt returnValue( ECCPErrorNone );

    numberOfCalls = iCallHandling.GetNumberOfCalls();
    if ( numberOfCalls == 0 )
        {
        iGsmAudioData.HandleCallEnding();

        // unmute mic
        iDataStore.SetAudioMuteCommand( EFalse );
        HandleSetAudioMute();
        }
    else if ( numberOfCalls == 1 )
        {
        TPEState callState;
        callState = iCallHandling.GetCallState( iWaitingCallId );
        // EPEStateRinging equals MT call
        if ( callState == EPEStateRinging )
            {
            TEFLOGSTRING2( KTAMESINT, 
                "CPEMessageHandler::HandleVideoCallIdle: aCallId = %d", 
                aCallId );
            iGsmAudioData.HandleCallEnding();
            
            // unmute mic
            iDataStore.SetAudioMuteCommand( EFalse );
            HandleSetAudioMute();
            }
        else 
            {
            TEFLOGSTRING2( KTAMESINT, 
                "CPEMessageHandler::HandleVideoCallIdle: callState = %d", 
                callState );
            }
        }
    else
        {
        TEFLOGSTRING2( KTAMESINT, 
            "CPEMessageHandler::HandleVideoCallIdle: numberOfCalls = %d", 
            numberOfCalls );
        }
    iDataStore.ResetCallInfo( aCallId );
    
    //publish remote party info to Mediator after call info has been cleared.
    UpdateRemotePartyInfo();    
    
    return returnValue;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleEmergencyCheck
// Check is given number emergency number.
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleEmergencyCheck( )
    {
    TInt errorCode( ECCPErrorNone );
    TPEPhoneNumber emergencyNumber;
    TBool isEmergency;
    emergencyNumber = iDataStore.PhoneNumber();

    errorCode = iClientServices->IsEmergencyPhoneNumber( emergencyNumber, isEmergency );
    if ( isEmergency  && errorCode == ECCPErrorNone )
        {
        iModel.SendMessage( MEngineMonitor::EPEMessageValidEmergencyNumber );
        }
    else
        {
        iModel.SendMessage( MEngineMonitor::EPEMessageInValidEmergencyNumber );
        }

    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandlePhoneNumberEditedL
// Handles Phone Number Edited message from phone application, 
// called when user is used paste or delete command.
// Method check if there is ongoing call(s) if there is return ECCPErrorNone else
// method fecths phone number from the CPEEngineInfo class and 
// then method parsers phonenumber and then method process parsing result
// with PhoneParser and Phoneengine.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
// 
void CPEMessageHandler::HandlePhoneNumberEditedL()
    {
    TBool isServiceCode( EFalse );

    iOptions->SetOptionStatus( KPhoneOptionInCall, 
        ( iCallHandling.GetNumberOfCalls() > 0 ) );

    iOptions->SetOptionStatus( KPhoneOptionSend, EFalse );
    iOptions->SetOptionStatus( KPhoneOptionVoipCall, EFalse );

    if( iParser->ParseL( iDataStore.PhoneNumber(), *iResult, *iOptions ) )
        {
        isServiceCode = ETrue;
        iGsmParserErrorCode = ECCPErrorNone;
        iParserHandlerContainer->ProcessL( *iResult );
        }
    else // check for service codes that require SEND
        {
        iOptions->SetOptionStatus( KPhoneOptionSend, ETrue );
        if ( iParser->ParseL( iDataStore.PhoneNumber(), *iResult, *iOptions ) )
            {
            // if there is an incoming call only certain codes are allowed       
            if ( iCallHandling.IsCallInState( EPEStateRinging ) &&
                 !iCallHandling.IsCallInState( EPEStateConnected ) )
                {
                isServiceCode = PhoneGsmParser::IsAllowedForArriving( *iResult );
                }
            else
                {
                const PhoneGsmParser::TContentType type = 
                    PhoneGsmParser::DetermineContentType( *iResult );
                    
                if ( type == PhoneGsmParser::EContentSupplementaryService ||
                     type == PhoneGsmParser::EContentUnstructuredService )
                    {
                    isServiceCode = ETrue;
                    }
                }
            }
        }
        
    iDataStore.SetPhoneNumberIsServiceCode( isServiceCode );    
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::AutomaticAnswer
// Checks if automatic answer is defined for connected accessory.
// -----------------------------------------------------------------------------
// 
TBool CPEMessageHandler::AutomaticAnswer( const TInt aCallId ) const
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::AutomaticAnswer <" );
    
    TInt automaticAnswer( EFalse );
    TInt accessory( 0 );
         
    if ( iCallHandling.GetNumberOfCalls() > 1 ) // The new call need to be the first in the array
        {
        return EFalse;
        }
        
    iExternalDataHandler.Get( EPEAccessoryMode, accessory );
    
    switch ( accessory )
        {
        case EAccModeWiredHeadset:    //Wired headset
        case EAccModeWirelessHeadset: //Wireless headset
            {
            // Safe to ignore error code here, 
            // automatic answer setting just equals zero == EFalse if it fails
            iExternalDataHandler.Get( EPEAutomaticAnswerHeadsetSetting, automaticAnswer );
            break;
            }
        case EAccModeWiredCarKit:     //Wired carkit
            {
            iExternalDataHandler.Get( EPEAutomaticAnswerCarkitSetting, automaticAnswer );
            break;
            }           
        case EAccModeWirelessCarKit:  //Wireless carkit
            {
            iExternalDataHandler.Get( EPEAutomaticAnswerWirelessCarkitSetting, automaticAnswer );                
            break;
            }           
        case EAccModeLoopset:         //Loopset
            {
            iExternalDataHandler.Get( EPEAutomaticAnswerLoopsetSetting, automaticAnswer );                
            break;
            }           
        case EAccModeMusicStand:      //Musicstand
            {
            iExternalDataHandler.Get( EPEAutomaticAnswerMusicStandSetting, automaticAnswer );                
            break;
            }
         default:
            break;
         }

    if ( automaticAnswer )
        {
        TFileName noneFilepath;
        noneFilepath.Append( TParsePtrC( PathInfo::RomRootPath() ).Drive() );
        noneFilepath.Append( KProfileNoSoundPath() );
        
        TProfileRingingType ringingType = iDataStore.RingingType(); 
        TPEContactFileName ringingTone = iDataStore.RingingTone( aCallId );
         
        if ( ringingType == EProfileRingingTypeBeepOnce ||
             ringingType == EProfileRingingTypeSilent ||
             ringingTone == noneFilepath )
            {
            automaticAnswer = EFalse;
            }
        } 
    TEFLOGSTRING2( KTAINT, 
        "PE CPEMessageHandler::AutomaticAnswer > ret: %d", automaticAnswer );
    return automaticAnswer;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleStopInbandTonePlay
// Stop playing a InBand tone
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleStopInbandTonePlay()
    {
    iGsmAudioData.StopInbandTonePlay();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleAutomaticAnswerOff
// Gets EPEMessageAutomaticAnswerOff from UI and makes soft cancelation of the
// automatic answer when needed
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleAutomaticAnswerOff() const
    {
    iAutomaticAnswerTimer->Cancel();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleATDialingStarted()
// Handles AT dialing completed message from Phone UI
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleATDialingStarted( const TBool aSucceed ) const
    {
    iClientServices->CommandHandlerMonitor()->DoCompleteCmdAtd( aSucceed ); 
    }    

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsEmergencyAllowed()
// Checks if emergency call is allowed. 
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::IsEmergencyAllowed() const
    {
    TBool networkConnectionAllowed( EFalse );
    //It is safe to ignore error code here: a default value of EFalse is used if the get fails
    iExternalDataHandler.Get( EPENetworkConnectionAllowedSetting, networkConnectionAllowed );
    return networkConnectionAllowed;
    }
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleClientCallData()
// Handle Client Call Data.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleClientCallData() 
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleClientCallData" );
    
    CPhCltDialData* dialData = iClientServices->CallRequestMonitor()->ClientDialData();
    
    // Set already known Client information
    SetClientData( *dialData );
    
    if ( dialData->CallType() == EPhCltVideo || dialData->CallType() == EPhCltForcedVideo )
        {
        iDataStore.SetCallTypeCommand( EPECallTypeVideo );
        }
    else if( dialData->CallType() == EPhCltCallVoIP )
        {
        iDataStore.SetCallTypeCommand( EPECallTypeVoIP );
        }
    else
        {
        iDataStore.SetCallTypeCommand( EPECallTypeCSVoice );
        }
        
    // End other calls before dial SAT call
    if ( dialData->EndOtherCalls() )
        {
        HandleReleaseAll();
        TEFLOGSTRING( KTAINT,
            "PE CPEMessageHandler::HandleClientCallData > HandleReleaseAll()" );
         }       
    }    
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::ClearCallAudio
// Notifies audio handling that there is no active call and audio should be routed
// accordingly.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::ClearCallAudio()
    {
    TEFLOGSTRING( KTAMESINT, "PE CPEMGsmessageHandler::ClearCallAudio()" );
    TBool restrictingCalls( EFalse );

    if ( iCallHandling.GetNumberOfCalls() > 0 )
        {
        restrictingCalls = 
            // Single call states restricting the devsound notification
            iCallHandling.IsCallInState( EPEStateConnected ) ||
            iCallHandling.IsCallInState( EPEStateConnecting ) ||
            iCallHandling.IsCallInState( EPEStateDialing ) ||
            iCallHandling.IsCallInState( EPEStateHeld ) ||
            // Conference call states restricting the devsound notification
            ( iDataStore.CallState( KPEConferenceCallID )== EPEStateConnectedConference ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateCreatingConference ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateGoingOneToOne ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateAddingConferenceMember ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateAddedConferenceMember ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateDroppingConferenceMember ) ||
            ( iDataStore.CallState( KPEConferenceCallID ) == EPEStateDroppedConferenceMember );
        }
    
    if ( restrictingCalls == EFalse )
        {
        // deactivate audio
        TEFLOGSTRING( KTAMESINT, "PE CPEMGsmessageHandler::ClearCallAudio() Deactivating" );
        iGsmAudioData.HandleCallEnding();
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleSwitchToVideoOrVoice 
// This method handle EPEMessageSwitchToVideoOrVoice message. If current call id
// is Data then call will be switched to Voice call and the other way around. 
// Method set current phonenumber to dataStore and get call parameter and call 
// hangUp to current call. 
// When hangUp is completed (EPEMessageIdle was sent) sequence will be continue 
// from ContinueSwitchToCall method.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleSwitchToVideoOrVoice( const TInt aCallId )
    {
    // First get the current phone number and then end voice call
    // or video call.
    TInt err( ECCPErrorNone );
    
    TEFLOGSTRING2( KTAINT, 
        "PE CPEMessageHandler::HandleSwitchToVideoOrVoice, aCallId : %d", aCallId );
    // if out of memory case then phonenumber is already datastore.
    if( aCallId != KPECallIdNotUsed )
        {
        if ( iDataStore.CallDirection( aCallId ) == RMobileCall::EMobileOriginated )
            {
            iDataStore.SetSwitchToNumberCommand( iDataStore.WholeOutgoingPhoneNumber( aCallId ) );  
            // Clear phonenumber to prevent using the wrong number in MO video call.
            iDataStore.SetPhoneNumber( KNullDesC() );
            iSwitchToVidCalReconFlag = ETrue;
            }
        else
            {
            iDataStore.SetSwitchToNumberCommand( iDataStore.RemotePhoneNumber( aCallId ) );
            // Remote phone number must be stored as the phone number in case of low-memory situation where 
            // an MO voice call can be initiated after failing to answer an MT video call.
            iDataStore.SetPhoneNumber( iDataStore.RemotePhoneNumber( aCallId ) );
            }

        err = HandleReleaseCall();
        }

    return err;
    }
    
// -----------------------------------------------------------------------------
// CPEMessageHandler::ContinueSwitchToCall
// Metdod calls dial to multimedia call or voice call.
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::ContinueSwitchToCall( const TInt aCallId )  
    {
    TEFLOGSTRING2( KTAINT, 
        "PE CPEMessageHandler::ContinueSwitchToCall, aCallId : %d", aCallId );
    TInt callId;
    TInt errorCode( ECCPErrorNone );
  
    TPEPhoneNumber phoneNumber = iDataStore.SwitchToNumberCommand();
    RemovePreAndPostFix( phoneNumber );
    
    TEFLOGSTRING2( KTAINT, 
        "PE CPEMessageHandler::ContinueSwitchToCall, phoneNumber : %S", 
        &phoneNumber );

    // Check is current call voice or video
    if ( CallIdCheck::IsVoice( aCallId ) )
        {
        // Create new video call to same phonenumber
        iDataStore.SetCallTypeCommand( EPECallTypeVideo );
        errorCode = iCallHandling.DialMultimedia( phoneNumber, callId );
        }
    else if ( CallIdCheck::IsVideo( aCallId ) )
        {
        // Create new voice call to same phonenumber
        iDataStore.SetCallTypeCommand( EPECallTypeCSVoice );
        errorCode = iCallHandling.DialCall( phoneNumber, callId );
        }
    TEFLOGSTRING2( KTAINT, 
        "PE CPEMessageHandler::ContinueSwitchToCall(), error : %d", errorCode );    
    return errorCode;    
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::RemovePreAndPostFix
// Remmove supplementary service prefix and dtmf postfix.
// Phone number can contain following parts: supplementary
// service prefix, main part and dtmf postfix.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::RemovePreAndPostFix( 
        TDes& aString )
    {
    // Check that string contains only valid dtmf characters.
    if ( IsValidDtmfString( aString ))
        {
        TLex input( aString ); 
        
        RemovePrefix( input );
        // Take number part.
        HandleNumberPart( input, aString );        
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::RemovePrefix
// Removes clir suppress/invoke prefix in the string.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::RemovePrefix( 
        TLex& aLex )
    {
    TPtrC remainder( aLex.Remainder() );

    if ( EqualsLeft( remainder, KPEClirSuppress ) )
        {
        aLex.Inc( KPEClirSuppress().Length() );
        }
    else if ( EqualsLeft( remainder, KPEClirInvoke ) )
        {
        aLex.Inc( KPEClirSuppress().Length() );
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleNumberPart
// Search the main part of the phone number.
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleNumberPart(
        TLex& aLex,
        TDes& aNumberPart )
    {   
    TLexMark start;
    aLex.Mark( start );
  
    // Optional forced call prefixes. 
    if ( aLex.Peek() == KPENumberAsterisk || 
         aLex.Peek() == KPENumberHash ) 
         {
         aLex.Inc(); 
         }
         
    // Optional international prefix. 
    if ( aLex.Peek() == KPENumberPlus ) 
        { 
        aLex.Inc(); 
        } 

    // And the rest of number. 
    while ( ( aLex.Peek().IsDigit() ) ||  
            ( aLex.Peek() == KPENumberAsterisk ) || 
            ( aLex.Peek() == KPENumberHash ) ) 
        {
        aLex.Inc(); 
        }

    TPtrC mainpart( aLex.MarkedToken( start ) );
    const TInt length = mainpart.Length();
    if ( length <= KPEPhoneNumberMaxLength )
        {
        aNumberPart.Copy( mainpart );
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::EqualsLeft
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::EqualsLeft( 
        const TDesC& aString, 
        const TDesC& aPrefix )
    {
    TBool result = EFalse;

    if ( aPrefix.Length() <= aString.Length() )
        {
        TPtrC part( aString.Left( aPrefix.Length() ) );

        result = ( part == aPrefix );
        }

    return result;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleReplaceActive
// -----------------------------------------------------------------------------
// 
TInt CPEMessageHandler::HandleReplaceActive()
    {
    return iCallHandling.ReplaceActive();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsActiveVideo
// Checks if there are any connected video calls
// -----------------------------------------------------------------------------
// 
TBool CPEMessageHandler::IsActiveVideo()
    {
    TBool activeVideoCall( EFalse );
    
    TInt callId = iCallHandling.GetCallIdByState( EPEStateConnected );
    if ( callId > ECCPErrorNotFound && iDataStore.CallType( callId ) == EPECallTypeVideo )
        {
        activeVideoCall = ETrue;
        }
    return activeVideoCall;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleServiceEnabled
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleServiceEnabled()
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleServiceEnabled ");

    
    return iVoipNumberHandler->ContinueVoipDial();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleRemotePartyInfoChanged
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleRemotePartyInfoChanged( const TInt aCallId )
    {        
    UpdateRemotePartyInfo(); 
        
    }


// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleUnattendedTransferRequestResponse
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleUnattendedTransferRequestResponse( 
        TBool aAcceptRequest )
    {
    TEFLOGSTRING( KTAINT, 
        "PE CPEMessageHandler::HandleUnattendedTransferRequestResponse" );
    
    if ( aAcceptRequest )
        {
        return iCallHandling.AcceptUnattendedTransfer();
        }
    else
        {
        return iCallHandling.RejectUnattendedTransfer();
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleUnattendedTransfer
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::HandleUnattendedTransfer()
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleUnattendedTransfer ");
    TInt errorCode = iCallHandling.DoUnattendedTransfer( 
            iDataStore.TransferTargetCommand() );
     
    iDataStore.SetErrorCode( errorCode );
    
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::ForwardCallToAddress
// -----------------------------------------------------------------------------
//
TInt CPEMessageHandler::ForwardCallToAddress()
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::ForwardCallToAddress ");
    TInt errorCode = iCallHandling.ForwardCallToAddress( 
            iDataStore.ForwardAddressIndex() );
     
    return errorCode;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::HandleDisableService
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::HandleDisableService()
    {
    TEFLOGSTRING( KTAINT, "PE CPEMessageHandler::HandleDisableService ");
    iServiceHandling.DisableService();
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::IsValidDtmfString
// -----------------------------------------------------------------------------
//
TBool CPEMessageHandler::IsValidDtmfString( TDes& aString )
    { 
    TBool validDtmf = ETrue;

    for( TInt i = 0; i < aString.Length(); i++ )
        {
        if ( KErrNotFound == KValidDtmfChars().Locate( aString[i] ) )
            {
            validDtmf = EFalse;
            break;
            }      
        }
    return validDtmf;
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::UpdateRemotePartyInfo
// -----------------------------------------------------------------------------
//
void CPEMessageHandler::UpdateRemotePartyInfo( )
    { 
    CPERemotePartyInfoMediator* mediatorUpdater = iModel.MediatorCommunicationHandler();
    if ( mediatorUpdater ) 
        {
        mediatorUpdater->UpdateRemotePartyInfo();
        }
    }

// -----------------------------------------------------------------------------
// CPEMessageHandler::AddSIMRejectedMoCsCallToLog
// -----------------------------------------------------------------------------
//	
TInt CPEMessageHandler::AddSIMRejectedMoCsCallToLog( const TInt aCallId )
    {
    TInt errorCode( ECCPErrorGeneral );
    
    errorCode = iCallHandling.GetCallInfo( *iCallInfo, aCallId );
    
    if ( errorCode == ECCPErrorNone )
        {
        TPEState callState;
        callState = iCallHandling.GetCallState( aCallId );
        TPECallType callType;
		callType = iDataStore.CallType( aCallId );

	    errorCode = ECCPErrorNotFound;
	            
        if ( EPEStateIdle == callState 
             && EPECallTypeCSVoice == callType )
            {
            SetPhoneNumberForCallLogging( aCallId );
            
            errorCode = UpdateClientInfo( aCallId );       
            
            // Calls have to log also without a contact (ECCPErrorNotFound).
            if ( errorCode == ECCPErrorNone || errorCode == ECCPErrorNotFound )
                {
                // Save the rest of information to EngineInfo.
                SetLoggingInfo( aCallId, callState );
                errorCode = iLogHandling.SaveCallEntry( aCallId );
                }
            }
        }
    return errorCode;
    }
//  End of File  
