/*
* Copyright (c) 2010 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: 
*
*/


#include "cserviceinfo.h"

const TUint KCacheRecords = 4;
const TUint KGranularity = 2;
const TUint KDefaultTtl = 4500;
const TUint KQueryFactor = 0.2;



CServiceInfo* CServiceInfo::NewL()
	{
	CServiceInfo* self = CServiceInfo::NewLC();
	CleanupStack::Pop(self);
	return self;
	}

CServiceInfo* CServiceInfo::NewLC()
	{
	CServiceInfo* self = new (ELeave)CServiceInfo();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CServiceInfo::CServiceInfo():iEntryTime(KCacheRecords),iExpiryTime(KCacheRecords),iAddressRecord(NULL),iServiceRecord(NULL),iPtrRecord(NULL),iTxtRecord(NULL)
	{
	iEntryExpired = EFalse;
	}

CServiceInfo::~CServiceInfo()
	{
	delete iAddressRecord;
	delete iServiceRecord;
	delete iPtrRecord;
	delete iTxtRecord;
	iEntryTime.Close();
	iExpiryTime.Close();
	iKey.Close();
	
	}

void CServiceInfo::ConstructL()
	{
	TTime currentTime;
	currentTime.UniversalTime();
	TTimeIntervalSeconds ttl = KDefaultTtl;
	
	//Set default Entry time
	for(TInt count=0;count<KCacheRecords;count++ )
		{
		iEntryTime.AppendL(currentTime);
		}
		
	
	//Set default Expiry time	
	for(TInt count=0;count<KCacheRecords;count++ )
		{
		iExpiryTime.AppendL(currentTime + ttl);
		}		
	
	}

TBool CServiceInfo::IsAuthoritative()const
	{
	return iAuthoritative;
	}

void CServiceInfo::SetAuthoritative(TBool aAuthoritative)
	{
	iAuthoritative = aAuthoritative;
	}

const TTime& CServiceInfo::LastAccessTime()const
	{
	return iLastAccessTime;
	}

void CServiceInfo::SetAccessTime(TTime aTime)
	{
	iLastAccessTime = aTime;
	}

TUint32 CServiceInfo::SessionId()const
	{
	return iSessionId;
	}
	
void CServiceInfo::SetSessionId(TUint32 aSessionId)
	{
	iSessionId = aSessionId;
	}

void CServiceInfo::SetAddressRecord(CRdTypeA* aAddressRecord)
	{

	SetEntryTime(ECacheEntryAddr);
	iAddressRecord = aAddressRecord;
	SetExpiryTime(ECacheEntryAddr);	

	}
	
void CServiceInfo::SetServiceRecord(CRdTypeSrv* aServiceRecord)
	{

	SetEntryTime(ECacheEntrySrv);
	iServiceRecord = aServiceRecord;
	SetExpiryTime(ECacheEntrySrv);	

	}
	
void CServiceInfo::SetPtrRecord(CRdTypePtr* aPtrRecord)
	{

	SetEntryTime(ECacheEntryPtr);
	iPtrRecord = aPtrRecord;
	SetExpiryTime(ECacheEntryPtr);	
	
	}

void CServiceInfo::SetTxtRecord(CRdTypeTxt* aTxtRecord)
	{

	SetEntryTime(ECacheEntryTxt);
	iTxtRecord = aTxtRecord;
	SetExpiryTime(ECacheEntryTxt);		

	}
	

CRdTypeA* CServiceInfo::AddressRecord()const
	{
	return iAddressRecord;
	}

CRdTypeSrv* CServiceInfo::ServiceRecord()const
	{
	return iServiceRecord;
	}

CRdTypePtr* CServiceInfo::PtrRecord()const
	{
	return iPtrRecord;
	}

CRdTypeTxt* CServiceInfo::TxtRecord()const
	{
	return iTxtRecord;
	}
	
void CServiceInfo::SetKeyL(const TDesC8& aKey)
	{
	iKey.Close();
	iKey.CreateL(aKey);
	iKey.LowerCase();
	}
	
const TDesC8& CServiceInfo::Key()const
	{	
	return iKey;
	}

void CServiceInfo::SetEntryTime(TCacheEntryType aType)
	{
	TTime currentTime;
	currentTime.UniversalTime();

	//Set the Entry Time when the record data is obtained for 
	//the first time
	
	switch(aType)
		{
		case ECacheEntryAddr:
		//if(!AddressRecord())
			{			
			iEntryTime.Insert(currentTime,ECacheEntryAddr);
			}
		break;
		
		
		case ECacheEntryPtr:
		//if(!PtrRecord())
			{
			iEntryTime.Insert(currentTime,ECacheEntryPtr);
			}		
		break;
		
		
		case ECacheEntrySrv:
		//if(!ServiceRecord())
			{
			iEntryTime.Insert(currentTime,ECacheEntrySrv);
			}
		break;
		
		case ECacheEntryTxt:
		//if(!TxtRecord())
			{
			iEntryTime.Insert(currentTime,ECacheEntryTxt);
			}
		break;
		}
	
	}
	

void CServiceInfo::SetExpiryTime(TCacheEntryType aType)
	{
	TTimeIntervalSeconds ttl;
	
	//Set/Update  the Expiry time
	switch(aType)
		{
		case ECacheEntryAddr:
		ttl = AddressRecord()->Ttl();
		break;
		
		
		case ECacheEntryPtr:
		ttl = PtrRecord()->Ttl();		
		break;
		
		
		case ECacheEntrySrv:
		ttl = ServiceRecord()->Ttl();
		break;
		
		case ECacheEntryTxt:
		ttl = TxtRecord()->Ttl();
		break;
		}
	
	//Set the Expiry Time	
	TTime expiryTime = iEntryTime[aType] + ttl;
	iExpiryTime.Insert(expiryTime,aType);
	}
	
	
TBool CServiceInfo::EntryExpired()
	{
	TTime currentTime;
	currentTime.UniversalTime();
	
	if(AddressRecord())
		{
		if(iExpiryTime[ECacheEntryAddr] <= currentTime)
			{
			iEntryExpired = ETrue;
			return iEntryExpired;
			}
		}
		
	if(PtrRecord())
		{
		if(iExpiryTime[ECacheEntryPtr] <= currentTime)
			{
			iEntryExpired = ETrue;
			return iEntryExpired;
			}
		}
		
		
	if(ServiceRecord())
		{
		if(iExpiryTime[ECacheEntrySrv] <= currentTime)
			{
			iEntryExpired = ETrue;
			return iEntryExpired;
			}
		}
		
		
	if(TxtRecord())
		{
		if(iExpiryTime[ECacheEntryTxt] <= currentTime)
			{
			iEntryExpired = ETrue;
			return iEntryExpired;
			}
		}
	
	return EFalse;
	}


// This Clone funtion returns back what is necessary. 

CServiceInfo* CServiceInfo::CloneL()const
    {
    CServiceInfo* serviceInfo = CServiceInfo::NewL();

    if(iAddressRecord)
        {
        serviceInfo->SetAddressRecord(static_cast<CRdTypeA*>(iAddressRecord->CloneL()));
        }
    if(iServiceRecord)
        {
        serviceInfo->SetServiceRecord(static_cast<CRdTypeSrv*>(iServiceRecord->CloneL()));
        }
    if(iPtrRecord)
        {
        serviceInfo->SetPtrRecord(static_cast<CRdTypePtr*>(iPtrRecord->CloneL()));
        }
    if(iTxtRecord)
        {
        serviceInfo->SetTxtRecord(static_cast<CRdTypeTxt*>(iTxtRecord->CloneL()));
        }

    serviceInfo->SetKeyL(iKey);
    serviceInfo->SetSessionId(iSessionId);
    
    return serviceInfo;
    }

TBool CServiceInfo::EntryToBeQueried()
	{
	//Check if any record in the entry has exceeded 80% ttl, if yes, Query!
	
	TTime currentTime;
	currentTime.UniversalTime();
	
	
	if(AddressRecord())
		{
		TInt64 addExpiryTime = iExpiryTime[ECacheEntryAddr].Int64();		
		TInt64 current = currentTime.Int64();
		//Converted to seconds
		TUint64 addExpiryFactor = (addExpiryTime - current) / 1000000;
		if( addExpiryFactor < (0.2)*(AddressRecord()->Ttl()))
			{
			return ETrue;
			}
		}
		
	if(PtrRecord())
		{				
		TInt64 ptrExpiryTime = iExpiryTime[ECacheEntryPtr].Int64();
		TInt64 current = currentTime.Int64();
		//Converted to seconds
		TUint64 ptrExpiryFactor = (ptrExpiryTime - current) / 1000000;
		if( ptrExpiryFactor < (0.2)*(PtrRecord()->Ttl()))
			{
			return ETrue;
			}
		}
		
		
	if(ServiceRecord())
		{
		TInt64 srvExpiryTime = iExpiryTime[ECacheEntrySrv].Int64();		
		TInt64 current = currentTime.Int64();
		//Converted to seconds
		TUint64 srvExpiryFactor = (srvExpiryTime - current) / 1000000;
		if( srvExpiryFactor < (0.2)*(ServiceRecord()->Ttl()))
			{
			return ETrue;
			}
		}
		
		
	if(TxtRecord())
		{
		TInt64 txtExpiryTime = iExpiryTime[ECacheEntryTxt].Int64();		
		TInt64 current = currentTime.Int64();
		//Converted to seconds
		TUint64 txtExpiryFactor = (txtExpiryTime - current) / 1000000;
		if( txtExpiryFactor < (0.2)*(TxtRecord()->Ttl()))
			{
			return ETrue;
			}
		}
	
	return EFalse;
	}


TBool CServiceInfo::StaleEntry()
	{
	return iEntryExpired;
	}
