// T_MDR.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <f32file.h>
#include <s32std.h> 
#include <s32stor.h> 
#include <s32file.h> 
#include <s32mem.h>
#include <fbs.h>
//
#include <apamdr.h>
#include <apffndr.h>
#include <apgdoor.h>
#include "tstapp.h"
//
#include <e32test.h>


const TInt KTestCleanupStack=0x40;
LOCAL_D TFullName tempPath=_L("c:\\system\\temp\\");
LOCAL_D TFileName dllname=_L("tstapp.app");
#define KTestAppId TApaAppIdentifier(KUidTestApp,dllname)
const TUid KTestSourceId={458};

LOCAL_D RTest test(_L("T_Mdr"));
LOCAL_D CTrapCleanup* TheTrapCleanup;
LOCAL_D CApaProcess* TheProcess;
LOCAL_D RFs TheFs;


/////////////////////////////////

class CTestModelHeader : public CApaModelHeader
	{
public:
	void RestoreL(const CStreamStore& aStore,const CStreamDictionary& aDict);
	void StoreL(CStreamStore& aStore,CStreamDictionary& aDict) const;
	void DetachFromStoreL(CPicture::TDetach aDetach);
	TApaAppIdentifier AppId()const;
public:
	TInt iData;
	};


TApaAppIdentifier CTestModelHeader::AppId()const
	{
	return KTestAppId;
	}


void CTestModelHeader::StoreL(CStreamStore& aStore,CStreamDictionary& aDict) const
	{
	// write out some data
	RStoreWriteStream stream;
	TStreamId id=stream.CreateLC(aStore);
	stream.WriteInt32L(iData);
	stream.WriteInt32L(0); // hack of testapp doc format - no subdocuments
	stream.CommitL();
	aDict.AssignL(KUidTestAppHeadStream,id);
	CleanupStack::PopAndDestroy(); // stream
	}


void CTestModelHeader::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aDict)
	{
	// read in some data
	RStoreReadStream stream;
	stream.OpenLC(aStore,aDict.At(KUidTestAppHeadStream));
	iData = stream.ReadInt32L();
	CleanupStack::PopAndDestroy(); // stream
	}


void CTestModelHeader::DetachFromStoreL(CPicture::TDetach /*aDetach*/)
	{}


/////////////////////////////////


class TTestModelHeaderFactory : public MApaModelHeaderFactory
	{
public:
	CApaModelHeader* NewHeaderL(const CStreamStore& aStore,const CStreamDictionary& aDict,const TApaAppIdentifier& aAppId)const;
	};


CApaModelHeader* TTestModelHeaderFactory::NewHeaderL(const CStreamStore& aStore,const CStreamDictionary& aDict,
													 const TApaAppIdentifier& aAppId)const
	{
	if (aAppId.iAppUid!=KTestAppId.iAppUid)
		User::Leave(KErrNotSupported);
	CTestModelHeader* header = new(ELeave) CTestModelHeader();
	CleanupStack::PushL(header);
	header->RestoreL(aStore,aDict);
	CleanupStack::Pop(); // header
	return header;
	}


/////////////////////////////////


LOCAL_C void testModelDoorL()
	{
	test.Next(_L("Creating a model door"));
	//
	// create a model header
	CTestModelHeader* header = new CTestModelHeader();
		test(header!=NULL);
	header->iData = 7;
	//
	// embed the header in a door
	CApaModelDoor* door=NULL;
	TRAPD(ret, door=CApaModelDoor::NewL(header) );
		test(ret==KErrNone);
	//
	// set the source
	door->SetSource(KTestSourceId);
	//
	// create an in-memory store
	CBufStore* store=NULL;
	TRAP(ret, store=CBufStore::NewL(2) );
		test(ret==KErrNone);
	//
	// store the door
	test.Next(_L("Storing the model door"));
	TStreamId id;
	TRAP(ret, id=door->StoreL(*store) );
		test(ret==KErrNone);
	delete door; // deletes header also
	//
	// restore the door
	test.Next(_L("Restoring the model door"));
	TTestModelHeaderFactory factory;
	TRAP(ret, door=CApaModelDoor::NewL(*store,id,&factory) );
		test(ret==KErrNone);
		test( ((CTestModelHeader*)door->ModelHeader())->iData==7 );
		test(door->Source()==KTestSourceId);
	delete door;
	delete store;
	}



LOCAL_C void testConversionL()
	{
	// set things up
	CApaAppFinder* finder=CApaScanningAppFinder::NewL(TheFs);
	TRAPD(ret,TheProcess = CApaProcess::NewL(TheFs,*finder));
	CBufStore* store=NULL;
	//
	// create a door
	test.Next(_L("Restoring a full door as a model door"));
	CApaDocument* doc=NULL;
	TRAP(ret, doc=TheProcess->AddNewDocumentL(dllname) );
		test(ret==KErrNone);
	doc->EditL(NULL); // increments value to 1
	CApaDoor* door=NULL;
	TRAP(ret, door=CApaDoor::NewL(*doc,TSize(1000,1000)) );
		test(ret==KErrNone);
	//
	// set the source
	door->SetSource(KTestSourceId);
	//
	// create an in-memory store
	TRAP(ret, store=CBufStore::NewL(2) );
		test(ret==KErrNone);
	//
	// store the door
	TStreamId id;
	TRAP(ret, id=door->StoreL(*store) );
		test(ret==KErrNone);
	delete door; // deletes doc also
	door = NULL;
	doc = NULL;
	//
	// restore the door into a model door
	TTestModelHeaderFactory factory;
	CApaModelDoor* modelDoor=NULL;
	TRAP(ret, modelDoor=CApaModelDoor::NewL(*store,id,&factory) );
		test(ret==KErrNone);
		test( ((CTestModelHeader*)modelDoor->ModelHeader())->iData==1 );
		test(modelDoor->Format()==CApaDoorBase::EIconic);
		test(modelDoor->Source()==KTestSourceId);
	TSize size;
	modelDoor->GetSizeInTwips(size);
		test(size==TSize(1000,1000));
	//
	// store the model door
	test.Next(_L("Restoring a model door as a full door"));
	delete store;
	store = NULL;
	TRAP(ret, store=CBufStore::NewL(2) );
		test(ret==KErrNone);
	TRAP(ret, id=modelDoor->StoreL(*store) );
		test(ret==KErrNone);
	//delete modelDoor; // deletes header also
	//modelDoor = NULL;
	//
	// restore the model door into a full door
	TRAP(ret, door=CApaDoor::NewL(*store,id,*TheProcess) );	
		test(ret==KErrNone);
	delete door;
	door = NULL;
	delete store;
	store = NULL;
	//
	// change the model door format to glass & store it
	TRAP(ret, store=CBufStore::NewL(2) );
		test(ret==KErrNone);
	modelDoor->SetFormat(CApaDoorBase::EGlassDoor);
	modelDoor->SetSizeInTwips(TSize(2500,27));
	TRAP(ret, id=modelDoor->StoreL(*store) );
		test(ret==KErrNone);
	delete modelDoor; // deletes header also
	modelDoor = NULL;
	//
	// restore into a full door - this should switch the format to iconic and use the default icon size
	TRAP(ret, door=CApaDoor::NewL(*store,id,*TheProcess) );	
		test(ret==KErrNone);
		test(door->Format()==CApaDoorBase::EIconic);
		test(door->Source()==KTestSourceId);
	door->GetSizeInTwips(size);
		test(size==TSize(500,500));
	delete door;
	door = NULL;
	delete store;
	store = NULL;
	//
	delete TheProcess;
	}


LOCAL_C void setupCleanup()
//
// Initialise the cleanup stack.
//
    {
	TheTrapCleanup=CTrapCleanup::New();
	TRAPD(r,\
		{\
		for (TInt i=KTestCleanupStack;i>0;i--)\
			CleanupStack::PushL((TAny*)1);\
		test(r==KErrNone);\
		CleanupStack::Pop(KTestCleanupStack);\
		});
	}


GLDEF_C TInt E32Main()
	{
	setupCleanup();
	//
	test.Title();
	test.Start(_L("Testing model doors..."));
	//
	// set up an fbs
	FbsStartup();
	TInt ret=RFbsSession::Connect();
		test(!ret);
	//
	// set up the directory structure
	TheFs.Connect();
	//
	// run the testcode (inside an alloc heaven harness)

	__UHEAP_MARK;
	TRAPD(r,testModelDoorL());
		test(r==KErrNone);
	__UHEAP_MARKEND;

	__UHEAP_MARK;
	TRAP(r,testConversionL());
		test(r==KErrNone);
	__UHEAP_MARKEND;

 	test.End();
	test.Close();
	
	delete TheTrapCleanup;
	return KErrNone;
	}

