// Copyright (c) 2004-2009 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:
//

/**
@SYMPREQ                  PREQ1187
@SYMComponent             app-engines_cntmodel
@SYMAuthor                Simon Mellor, JamesCl
@SYMTestStatus            Implemented
@SYMTestType              CT

@SYMTestCaseDesc          Tests the performance of an initial sync to an empty contacts database
						  by importing a corporate-profile database of 1000 contacts from a vcard
						  file. The test mimics the way the SyncML code performs and initial sync.

@SYMTestActions           Measures the time taken to import a vcard file of the 1000 contacts, 
						  using the following calls on the contacts database:
						  -- CContactDatabase::DatabaseBeginL()
						  -- CContactDatabase::DatabaseCommitL()
						  -- CContactDatabase::ImportContactsL()
						  -- CContactDatabase::CompactL()

@SYMTestExpectedResults   Test case will run without leaving and will output timing information.

*/

#include "T_PerfInitialSync.h"
#include "../T_UTILS.H"
#include <cntvcard.h>
#include <cntitem.h>
#include <f32file.h>
#include <e32svr.h>
#include <coreappstest/testserver.h>

_LIT(KDbPathName,"c:\\private\\10003A73\\Contacts.cdb");
_LIT(KDatabaseName, "c:Contacts.cdb");
_LIT(KOutputFormat,"Initial Sync of %d contacts took: %d s %03d \n");

// After how many imports a CompactL() be called 
const TInt KCompactResolution = 32; // matches the SyncML code

CAddBench::CAddBench()
	{
	} 

CAddBench::~CAddBench()
	{
	delete iDb;
	iFs.Close();
	}  

CAddBench* CAddBench::NewLC(RTest& aTest)
	{
	CAddBench* self = new (ELeave) CAddBench();
	CleanupStack::PushL(self);
	self->ConstructL(aTest);
	return(self);
	}  

void CAddBench::ConstructL(RTest& aTest)
	{
	iTest = &aTest;
	User::LeaveIfError(iFs.Connect());

	_LIT(KInitialSyncTestTitle, "\nBeginning Initial Sync testing...\n");
	iTest->Printf(KInitialSyncTestTitle);
	
	RPIMTestServer serv;
	CleanupClosePushL(serv);
    User::LeaveIfError(serv.Connect());
    TRAPD (KErr, serv.DeleteFileL(KDbPathName));
    
	if (!( ((KErr == KErrNotFound) || (KErr == KErrNone)) || (KErr == KErrPathNotFound)))
		{
		User::Leave(KErr);
		}
	CleanupStack::PopAndDestroy(&serv);	
		
	CreateEmptyDBL();
	} 
	
/**
	This routine mimics calls made by CSmlContactsDba::ImportContactL v2 (called 
	from CSmlContactsDba::AddItemL).  
	The routine simluates single VCards being added one at a time.
*/
void CAddBench::ImportFileL(const TDesC& aFilename, TInt aNumEntries)
	{
	iNumContacts = aNumEntries;
	RFileReadStream aReadStream;
	CleanupClosePushL(aReadStream);
	
	User::LeaveIfError(aReadStream.Open(iFs,aFilename,EFileRead));

	iDb->DatabaseBeginL(EFalse);

	for (TInt counter = 0; counter < aNumEntries; ++counter)
		{		
		TBool importOK = ETrue;		
				
		// import one contact from the file
		CArrayPtr<CContactItem>* entryArray = iDb->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl),
																	aReadStream,
																	importOK,
															    	(CContactVCardConverter::EImportSingleContact | 
															    		CContactVCardConverter::EConnectWhitespace | 
															    		CContactVCardConverter::EIgnoreUid));

		CleanupStack::PushL(TCleanupItem(CleanupPtrArray, entryArray));

		if (!importOK)
			{			
 				User::Leave(KErrNotFound);
			}
			
									
		if ((counter > 0) && ((counter % KCompactResolution) == 0) )
			{	
			iDb->DatabaseCommitL(EFalse);
			iDb->CompactL();
			iDb->DatabaseBeginL(EFalse);
			}
		CContactItem* contact = entryArray->At(0);
		iTime = contact->LastModified();					
		CleanupStack::PopAndDestroy(entryArray);			
		}

	iDb->DatabaseCommitL(EFalse);

	CleanupStack::PopAndDestroy(&aReadStream);	
	aReadStream.Close();
	}
	
/**
	Static convenience cleanup method copied from CSmlContactsDba  
*/
void CAddBench::CleanupPtrArray(TAny* aCArrayPtr)
	{ 
	CArrayPtr<CContactItem>* array = reinterpret_cast<CArrayPtr<CContactItem>*>(aCArrayPtr);
	array->ResetAndDestroy();
	delete array;
	}

/** 
	Replace the current db with an empty one - ie start from scratch
*/
void CAddBench::CreateEmptyDBL()
	{
	delete iDb;
	iDb = NULL;
	iDb = CContactDatabase::ReplaceL(KDatabaseName);
	}

void CAddBench::DoSyncL(TInt aEntryCount, const TDesC& aVCardLoc )
	{
	TFileName path;
	path.Append(aVCardLoc);	
	
	TCntPerfTimer timer;
	timer.StartTimer();	
	ImportFileL(aVCardLoc, aEntryCount);
	timer.StopTimer();	

	TInt result = timer.Result();	
	TBuf<64> formattable;
	formattable.Format(KOutputFormat, iNumContacts, result / 1000000, (result / 1000) % 1000);
	iTest->Printf(formattable);
	}
