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

#include "rundump.h"
#include <e32base.h>
#include <e32std.h>
#include <e32cons.h>			// Console

#include <coredumpserverapi.h>
#include <e32property.h>
#include <crashdatasave.h>



//  Constants

_LIT(KTextConsoleTitle, "Console");
_LIT(KTextFailed, " failed, leave code = %d");
_LIT(KTextPressAnyKey, " [press any key]\n");
_LIT(KCrashAppFileName,"Z:\\sys\\bin\\crashapp.exe");

//  Global Variables

LOCAL_D CConsoleBase* console;  // write all messages to this


//  Local Functions

LOCAL_C void MainL()
	{
	TUid SELF_UID_V2 = { 0x102836bb };
	TUid WRITER_UID = { 0x102831E4 };
	TUid CDS_UID  = { 0x10282FE5 };
	TUid UTRACE_UID = { 0x102836BA };
	TUid DEXC_UID = { 0x102832C5 };
	
	RCoreDumpSession cdsSess;
	CleanupClosePushL(cdsSess);
	cdsSess.Connect();	
	
	//
	// add your program code here, example code below
	//
	console->Write(_L("Starting megadump\n"));
	console->Write(_L("SELF or UTRACE or DEXC? (s/u/d)"));
	TChar inp = console->Getch();	

	//Load plugins	
	TPluginRequest req;
	req.iPluginType = TPluginRequest::EFormatter;
	req.iLoad = ETrue;
	
	switch(inp)
	{
	case('s'):
		{
		req.iUid = SELF_UID_V2;
		console->Write(_L("\nLoading SELF formatter V2\n"));
		break;
		}
	case('u'):
		{
		req.iUid = UTRACE_UID;
		console->Write(_L("\nLoading UTRACE formatter\n"));
		break;
		}
	case('d'):
		{
		req.iUid = DEXC_UID;
		console->Write(_L("\nLoading DEXC Formatter"));
		return;
		}
	default:
		{
		console->Write(_L("\nNot an option"));
		return;
		}
		
	}
	
	TBuf<10> crashAppParam; 
	console->Write(_L("Should crashapp write trace data? (y/n)\n"));
	inp = console->Getch();
	switch(inp)
	{
	case('y'):
		{
		console->Write(_L("Crashapp will write trace data\n"));
		crashAppParam.Append(_L("-d1 -t"));
		break;
		}
	default:
		{
		console->Write(_L("Crashapp will not write any trace data\n"));
		crashAppParam.Append(_L("-d1"));
		break;
		}
	}
	
	//Start the process that we intend to crash....
	RProcess crashProcess;
	CleanupClosePushL(crashProcess);
	crashProcess.Create( KCrashAppFileName, crashAppParam);
	
    cdsSess.PluginRequestL( req );
    
    TPluginRequest req2;
    req2.iUid = WRITER_UID;
    req2.iPluginType = TPluginRequest::EWriter;
    req2.iLoad = ETrue;
	
    console->Write(_L("Loading File writer\n"));
	cdsSess.PluginRequestL( req2 );
	
	_LIT( KPostCrashEventActionPrompt, "Action After Crash:\n  0-None,\n  1-Resume Thread,\n  2-Resume Process,\n  4-Kill Process" );
	_LIT( KFilePathPrompt, "not_important" );
	_LIT( KCrashFileName, "e:\\file");
	
	console->Write(_L("Configuring CDS\n"));
	DoConfigureL(2, CDS_UID.iUid, COptionConfig::ECoreDumpServer, COptionConfig::ETUInt, KPostCrashEventActionPrompt,
			 1, KNullDesC, 4, KNullDesC, 0, cdsSess);
	
	console->Write(_L("Configuring Writer\n"));
	DoConfigureL((TInt)(CCrashDataSave::ECoreFilePath), WRITER_UID.iUid, COptionConfig::EWriterPlugin, COptionConfig::ETFileName,
		    KFilePathPrompt, 1, KNullDesC, 0, KCrashFileName, 0, cdsSess);
	
/*	if(trace)
		{
		console->Write(_L("Configuring Trace\n"));
		DoConfigureL(0, UTRACE_UID.iUid, COptionConfig::EFormatterPlugin, COptionConfig::ETInt,
		    KFilePathPrompt, 1, KNullDesC, 1, KCrashFileName, 0, cdsSess);
		}*/
	
	console->Write(_L("Observing\n"));
	cdsSess.ObservationRequestL( KCrashAppFileName, KCrashAppFileName, ETrue) ;
	
	console->Write(_L("Starting process\n"));
	crashProcess.Resume();
	CleanupStack::PopAndDestroy(&crashProcess);
	CleanupStack::PopAndDestroy(&cdsSess);
	
	console->Write(_L("Any key to exit...."));
	console->Getch();
	
	}

void DoConfigureL(const TUint32& aIndex, 
 	     const TUint32& aUID, 
        const COptionConfig::TParameterSource& aSource, 
        const COptionConfig::TOptionType& aType, 
        const TDesC& aPrompt, 
        const TUint32& aNumOptions,
        const TDesC& aOptions,
        const TInt32& aVal, 
        const TDesC& aStrValue,
        const TUint aInstance,
        const RCoreDumpSession &aSess)
/**
* @return void
* @param aIndex Internal index to the component that owns the object
* @param aUID UID of the component that owns the object
* @param aSource Type of component that owns the object
* @param aType Type of parameter
* @param aPrompt Prompt to present to user 
* @param aNumOptions Number of options that the parameter can be set to. Only applies if type is ETMultiEntryEnum.
* @param aOptions Comma separated list of options. Applies to ETMultiEntryEnum and ETBool
* @param aVal Integer value. Applies to ETInt, ETUInt, ETBool
* @param aStrValue String value. Applies to ETString, ETFileName, ETMultiEntry, ETBool
*/
	{
	COptionConfig * config;	
	
	config = COptionConfig::NewL( aIndex,
		aUID,
		aSource,
		aType,
		aPrompt,
		aNumOptions,
		aOptions,
		aVal,
		aStrValue);
	
	CleanupStack::PushL(config);
	
	config->Instance(aInstance);
	
	//Configure now...
	aSess.SetConfigParameterL(*config);	
	
	CleanupStack::PopAndDestroy(config);
	}


LOCAL_C void DoStartL()
	{
	// Create active scheduler (to run active objects)
	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
	CleanupStack::PushL(scheduler);
	CActiveScheduler::Install(scheduler);

	TRAPD(err, MainL());
	
	if(err != KErrNone)
		{
		console->Printf(_L("All is not well in the land of megadump. Error = %d\n"), err);
		}

	// Delete active scheduler
	CleanupStack::PopAndDestroy(scheduler);
	}


//  Global Functions

GLDEF_C TInt E32Main()
	{
	// Create cleanup stack
	__UHEAP_MARK;
	CTrapCleanup* cleanup = CTrapCleanup::New();

	// Create output console
	TRAPD(createError, console = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)));
	if (createError)
		return createError;

	// Run application code inside TRAP harness, wait keypress when terminated
	TRAPD(mainError, DoStartL());
	if (mainError)
		console->Printf(KTextFailed, mainError);
	console->Printf(KTextPressAnyKey);
	console->Getch();
	
	delete console;
	delete cleanup;
	__UHEAP_MARKEND;
	return KErrNone;
	}



