/*
* Copyright (c) 2004 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:  Parser for DM 1.2 formatted alert message
*
*/


#include <centralrepository.h>
#include <DevManInternalCRKeys.h>
#include <e32property.h>
#include <nsmldmconst.h>
#include "NSmlAlertQueue.h"
#include "nsmldebug.h" 
// ---------------------------------------------------------
// CNSmlDSAlertParser11(CSmlAlertInfo& aAlertInfo, CSyncMLHistoryPushMsg& aHistoryInfo )
// Returns pointer to the buffer
// ---------------------------------------------------------
//
CNSmlDMAlertParser11::CNSmlDMAlertParser11( CSmlAlertInfo& aAlertInfo, CSyncMLHistoryPushMsg& aHistoryInfo )
: CNSmlMessageParserBase( aAlertInfo, aHistoryInfo )
	{_DBG_FILE("CNSmlDMAlertParser11::CNSmlDMAlertParser11 begin!");
	}

// ---------------------------------------------------------
// CNSmlDMAlertParser11::~CNSmlDMAlertParser11()
// Destructor
// ---------------------------------------------------------
//
CNSmlDMAlertParser11::~CNSmlDMAlertParser11()
	{_DBG_FILE("CNSmlDMAlertParser11::~CNSmlDMAlertParser11 End");
	}	

// ---------------------------------------------------------
// CNSmlDMAlertParser11::ParseMessageL()
// Parses the aler message
// ---------------------------------------------------------
//	
void CNSmlDMAlertParser11::ParseMessageL()
	{
    _DBG_FILE("CNSmlDMAlertParser11::ParseMessageL begin!");

	//digest
	CheckLengthL( KNSmlAlertVersionPos + 1 );
	iHistoryInfo.SetMsgDigest( Message().Left( KNSmlAlertVersionPos ) );

	//version
	TInt version;
	version = ((TUint8) Message()[ KNSmlAlertVersionPos ]) << 8;
	version |= (TUint8) Message()[ KNSmlAlertVersionPos + 1 ];
	version = version >> 6;
	
	//ui interaction mode
	TInt uiMode = (TUint8) Message()[ KNSmlAlertVersionPos + 1 ] & KUiModeMask; 
	uiMode = uiMode >> 4;
	DBG_FILE_CODE(uiMode, _S8("CNSmlDMAlertParser11::ParseMessageL() : ui mode "));
	TInt SanSupport( KErrNone );
	CRepository* centrep = NULL;
    TRAPD( err, centrep = CRepository::NewL( KCRUidDeviceManagementInternalKeys) );    
    if( err == KErrNone )
       {
    centrep->Get( KDevManSANUIBitVariation, SanSupport );
       }
    delete centrep;
	if( SanSupport == 1 )
   	{
	if(uiMode == ESilent) //silent
	    {
        static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
        static _LIT_SECURITY_POLICY_C1(KAllowWriteDeviceDataPolicy, ECapabilityWriteDeviceData);
        RProperty::Define(KPSUidNSmlSOSServerKey,KNSmlDMSilentJob,RProperty::EInt,KAllowAllPolicy,KAllowWriteDeviceDataPolicy);
        TInt r2=RProperty::Set(KPSUidNSmlSOSServerKey,KNSmlDMSilentJob,ESilent);
        DBG_FILE_CODE( r2, _S8("CNSmlDMAlertParser11::ParseMessageL() KNSmlDMSilentJob set error code") );
	    }
    iAlertInfo.SetUimode(uiMode);
   	}	
	if (uiMode == 0)
		{
		uiMode = CSmlAlertInfo::ECreateJob;
		}
		
	iAlertInfo.SetJobControl((CSmlAlertInfo::TJobControl) uiMode);
		
	//initiator
	TInt initiator = (TUint8) Message()[ KNSmlAlertVersionPos + 1 ] & KInitiatorMask; 
	initiator = initiator >> 3;
	
	//reserved
	TInt futNum = (TUint8) Message()[ KNSmlAlertVersionPos + 1 ] & KMaskUpperFuture;
	
	//session id
	CheckLengthL( KNSmlAlertSession + 1 );
	TInt sessionId;
	sessionId = ((TUint8) Message()[ KNSmlAlertSession ]) << 8;
	sessionId |= (TUint8) Message()[ KNSmlAlertSession + 1 ];
	iAlertInfo.SetSessionId( sessionId );
	
	//server id length
	CheckLengthL( KNSmlAlertServerIdLength );
	TInt serverIdLength;
	serverIdLength = (TUint8) Message()[ KNSmlAlertServerIdLength ];
	
	//server id
	CheckLengthL( KNSmlAlertServerIdLenPos + serverIdLength );
	HBufC8* hostAddress = HBufC8::NewLC( serverIdLength );
	hostAddress->Des().Copy( Message().Mid(KNSmlAlertServerIdLenPos, serverIdLength));
		
	//Try to find profile before accessing content types
	SearchProfileL( *hostAddress );
	
	if ( iFoundProfiles.Count() == 0 )
		{
		iAlertInfo.SetProfileId( KNSmlNullId );
		User::Leave(KErrNotFound);
		}

	CleanupStack::PopAndDestroy(); //hostAddress
	
	TRAPD(error, CheckLengthL( KNSmlAlertServerIdLenPos + serverIdLength + 1 ) );
	
	if ( error == KErrNone )
		{
		TInt fut = (TUint8) Message()[ KNSmlAlertServerIdLenPos + serverIdLength] & KFutureMask;
		}
		
	TInt firstBytePlace = KNSmlAlertServerIdLenPos + serverIdLength + 1;
	
	if ( Message().Length() - firstBytePlace > 0 )
		{
		//vendor-info
		HBufC8* vendorInfo = HBufC8::NewLC( Message().Length() - firstBytePlace );
		vendorInfo->Des().Copy( Message().Mid( firstBytePlace, Message().Length() - firstBytePlace ));
		iAlertInfo.SetVendorSpecificInfoL( vendorInfo->Des() );
		CleanupStack::PopAndDestroy(); //vendorInfo
		}
	else
		{
		iAlertInfo.SetVendorSpecificInfoL( KNullDesC8() );
		}
	
	ResolveProfileL(0);
	_DBG_FILE("CNSmlDMAlertParser11::ParseMessageL End");
	}


// ---------------------------------------------------------
// CNSmlDMAlertParser11::SearchProfileL(TDesC8& aServerUri)
// Searches for the profile
// ---------------------------------------------------------
//
void CNSmlDMAlertParser11::SearchProfileL( TDesC8& aServerUri )
	{

	HBufC *serverId = HBufC::NewLC(aServerUri.Size());
	TPtr typePtr = serverId->Des();
	CnvUtfConverter::ConvertToUnicodeFromUtf8( typePtr, aServerUri);
	
	CNSmlDMSettings* settings = CNSmlDMSettings::NewLC();
	if ( settings->IsDMAllowedL() )
		{
		CNSmlDMProfileList* profileList = new( ELeave ) CArrayPtrFlat<CNSmlDMProfileListItem>(1);
    	CleanupStack::PushL( PtrArrCleanupItem( CNSmlDMProfileListItem, profileList ) );
		settings->GetProfileListL( profileList ); 
		for ( TInt i = 0; i < profileList->Count(); i++)
			{	
			TInt profileID = (*profileList)[i]->IntValue( TNSmlDMProfileData( EDSProfileId ) );
			CNSmlDMProfile* profile = settings->ProfileL( profileID );
			CleanupStack::PushL( profile );
			if ( profile->IntValue( TNSmlDMProfileData( EDMProfileServerAlertAction ) ) != ESmlDisableSync )
				{				
				if ( *serverId == profile->StrValue( EDMProfileServerId ) )
					{
					if ( iAlertInfo.Transport() == KUidNSmlMediumTypeInternet.iUid )
        			    {
        			    // accept only internet bearers
        			    if ( profile->IntValue(EDMProfileTransportId) == KUidNSmlMediumTypeInternet.iUid ) 
        			       
            				{
            				CNSmlAlertInfo* info = new (ELeave) CNSmlAlertInfo;
            				info->iProfileId = profile->IntValue( EDMProfileId );
            				info->iIAPId = profile->IntValue( EDMProfileIAPId );
            				iFoundProfiles.AppendL( info );
            				}        
        			    }
        			else
        			    {
        			    // accept only local bearers
        			    if ( profile->IntValue(EDMProfileTransportId) != KUidNSmlMediumTypeInternet.iUid )         			       
            				{
            				CNSmlAlertInfo* info = new (ELeave) CNSmlAlertInfo;
            				info->iProfileId = profile->IntValue( EDMProfileId );
            				info->iIAPId = profile->IntValue( EDMProfileIAPId );
            				iFoundProfiles.AppendL( info );
            				}        
        			    }
					}
				}
			CleanupStack::PopAndDestroy(); // profile
			}
		profileList->ResetAndDestroy();
		CleanupStack::PopAndDestroy(); //profileList	
		}
	CleanupStack::PopAndDestroy( 2 ); //settings, serverId
	
	if ( iAlertInfo.Transport() == KUidNSmlMediumTypeInternet.iUid )
	    {
    	if ( iFoundProfiles.Count() > 1 )
    	    {
    	    RArray<TInt> indexes;
            CleanupClosePushL( indexes );
            
            for (TInt j = 0; j < iFoundProfiles.Count(); j++ )
                {
                CNSmlAlertInfo* info = iFoundProfiles[j];
                if ( info->iIAPId == -1 )    
                    {
                    indexes.Append( j );    
                    }
                }
            
            if ( indexes.Count() < iFoundProfiles.Count() )
                {
                for ( TInt count(0); count < indexes.Count(); count++ )
                    {
                    CNSmlAlertInfo* temp = iFoundProfiles[indexes[count]];
                    iFoundProfiles.Remove( indexes[count] );
                    delete temp; 
                    temp = NULL;                 
                    }	        
                }
                
        	CleanupStack::PopAndDestroy( &indexes );    
    	    }
	    }
	}

// ---------------------------------------------------------
// CNSmlDMAlertParser11::ResolveProfileL(TInt aContentCount)
// Resolves profile
// ---------------------------------------------------------
//
void CNSmlDMAlertParser11::ResolveProfileL( TInt /*aContentCount*/ )
	{
	iAlertInfo.SetProfileId(iFoundProfiles[0]->iProfileId);
	}
