// APGTASK.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "apgtask.h"
#include "apgwgnam.h"
#include <w32std.h>

//
// class TApatask
//

EXPORT_C TApaTask::TApaTask(RWsSession& aWsSession)
	: iWsSession(aWsSession)
	{
	}

EXPORT_C void TApaTask::SetWgId(TInt aWgId)
	{
	iWgId=aWgId;
	}

EXPORT_C TInt TApaTask::WgId() const
	{
	return iWgId;
	}

EXPORT_C TBool TApaTask::Exists() const
	{
	return(iWgId>0);
	}

EXPORT_C TThreadId TApaTask::ThreadId() const
	{ // !! what to do about the failure case?
	TThreadId threadId;
	iWsSession.GetWindowGroupClientThreadId(iWgId,threadId);
	return(threadId);
	}

EXPORT_C void TApaTask::BringToForeground()
	{
	iWsSession.SetWindowGroupOrdinalPosition(iWgId,0);
	}

EXPORT_C void TApaTask::SendToBackground()
	{
	iWsSession.SetWindowGroupOrdinalPosition(iWgId,-1);
	}

EXPORT_C void TApaTask::EndTask()
	{
	SendSystemEvent(EApaSystemEventShutdown);
	}

EXPORT_C void TApaTask::KillTask()
	{
	RThread thread;
	TInt err=thread.Open(ThreadId());
	if (!err)
		{
#if  defined(__WINS__)
		thread.Terminate(0);
#else
		RProcess process;
		thread.Process(process);
		process.Terminate(0);
		process.Close();
#endif
		thread.Close();
		}
	}

EXPORT_C TInt TApaTask::SwitchOpenFile(const TDesC& aFilename)
	{
	TInt err=CheckSwitchFile();
	if (!err)
#if defined(_UNICODE)
		{
		TPtrC8 messageBuffer((TUint8*) aFilename.Ptr(),aFilename.Length()<<1);
		err=SendMessage(KUidApaMessageSwitchOpenFile,messageBuffer);
		}
#else
		err=SendMessage(KUidApaMessageSwitchOpenFile,aFilename);
#endif
	return err;
	}

EXPORT_C TInt TApaTask::SwitchCreateFile(const TDesC& aFilename)
	{
	TInt err=CheckSwitchFile();
	if (!err)
#if defined(_UNICODE)
		{
		TPtrC8 messageBuffer((TUint8*) aFilename.Ptr(),aFilename.Length()<<1);
		err=SendMessage(KUidApaMessageSwitchCreateFile,messageBuffer);
		}
#else
		err=SendMessage(KUidApaMessageSwitchCreateFile,aFilename);
#endif
	return err;
	}

TInt TApaTask::CheckSwitchFile() const
	//
	// private - checks whether the task will respond to a switch files event
	//
	{
	HBufC* buf=HBufC::NewMax(CApaWindowGroupName::EMaxLength);
	if (!buf)
		return KErrNoMemory;
	TInt err=KErrNone;
	TPtr des=buf->Des();
	err=iWsSession.GetWindowGroupNameFromIdentifier(iWgId, des);
	if (!err)
		{
		CApaWindowGroupName* wgName=CApaWindowGroupName::New(iWsSession, buf); // takes ownership (if it succeeds)
		if (!wgName)
			{
			delete buf;
			return KErrNoMemory;
			}
		if (wgName->IsBusy())
			err=KErrNotReady;
		if (!(wgName->RespondsToSwitchFilesEvent()))
			err=KErrNotSupported;
		delete wgName;
		}
	else
		delete buf;
	return err;   
	}

EXPORT_C TInt TApaTask::SendMessage(TUid aUid,const TDesC8& aParams)
	{
	return iWsSession.SendMessageToWindowGroup(iWgId,aUid,aParams);
	}

EXPORT_C void TApaTask::SendKey(TInt aKeyCode,TInt aModifiers)
	{
	TKeyEvent key;
	key.iCode=aKeyCode;
	key.iModifiers=aModifiers;
	SendKey(key);
	}

EXPORT_C void TApaTask::SendKey(const TKeyEvent& aKey)
	{
	TWsEvent event;
	event.SetType(EEventKey);
	*event.Key()=aKey;
	event.SetTimeNow();
	iWsSession.SendEventToWindowGroup(iWgId,event);
	}

EXPORT_C void TApaTask::SendSystemEvent(TApaSystemEvent aEvent)
	{
	TWsEvent event;
	event.SetType(EEventUser);
	*(TApaSystemEvent*)(event.EventData())=aEvent;
	event.SetTimeNow();
	iWsSession.SendEventToWindowGroup(iWgId,event);
	}

//
// class TApaTaskList
//

EXPORT_C TApaTaskList::TApaTaskList(RWsSession& aWsSession)
	: iWsSession(aWsSession)
	{
	}

EXPORT_C TApaTask TApaTaskList::FindApp(const TDesC& aAppName)
	{
	TApaTask task(iWsSession);
	TInt wgId=0;
	TInt matchId=0;
	TInt fgWgId=FindByPos(0).WgId();
	CApaWindowGroupName::FindByCaption(aAppName, iWsSession, wgId);
	if (wgId==fgWgId)
		{
		while (wgId>=0)
			{
			matchId=wgId;
			CApaWindowGroupName::FindByCaption(aAppName, iWsSession, wgId);
			}
		}
	else 
		matchId=wgId;
	task.SetWgId(matchId);
	return(task);
	}

EXPORT_C TApaTask TApaTaskList::FindDoc(const TDesC& aDocName)
	{
	TInt wgId=0;
	CApaWindowGroupName::FindByDocName(aDocName, iWsSession, wgId);
	TApaTask task(iWsSession);
	task.SetWgId(wgId);
	return(task);
	}

EXPORT_C TApaTask TApaTaskList::FindByPos(TInt aPos)
	{
	TApaTask task(iWsSession);
	TInt wgId=0;
	const TInt count=iWsSession.NumWindowGroups(0);
	CArrayFixFlat<TInt>* array=new CArrayFixFlat<TInt>(count);
	if (array)
		{
		iWsSession.WindowGroupList(0,array); // priority 0 (normal apps)
		if (aPos>=count || aPos<0)
			aPos=count-1;
		if (aPos<array->Count())
			wgId=(*array)[aPos];
		delete array;
		}									
	task.SetWgId(wgId);
	return(task);
	}

EXPORT_C TApaTask TApaTaskList::FindApp(TUid aAppUid)
	{
	TApaTask task(iWsSession);
	TInt wgId=0;
	TInt matchId=0;
	TInt fgWgId=FindByPos(0).WgId();
	CApaWindowGroupName::FindByAppUid(aAppUid,iWsSession,wgId);
	if (wgId==fgWgId)
		{
		while (wgId>=0)
			{
			matchId=wgId;
			CApaWindowGroupName::FindByAppUid(aAppUid,iWsSession,wgId);
			}
		}
	else 
		matchId=wgId;
	task.SetWgId(matchId);
	return task;
	}

EXPORT_C TInt TApaTaskList::CycleTasks(TUid aAppUid,TCycleDirection aDirection)
// If at foreground, send to background and find next one and bring it to foreground
// If not at foreground, bring to foreground
// Return KErrNotFound if there is no task with aAppUid, otherwise KErrNone.
	{
	TInt sendToBgWgId=KErrNotFound;
	TInt wgId=0;
	TInt fgWgId=FindByPos(0).WgId();
	CApaWindowGroupName::FindByAppUid(aAppUid,iWsSession,wgId);
	TInt matchId=wgId;
	if (wgId==fgWgId)											// If first match is at foreground
		{
		if (aDirection==EBackwards)
			{
			while (wgId>=0)										// Go for last match
				{
				matchId=wgId;
				CApaWindowGroupName::FindByAppUid(aAppUid,iWsSession,wgId);
				}
			}
		else
			{
			CApaWindowGroupName::FindByAppUid(aAppUid,iWsSession,wgId);
			if (wgId<0)											// If no other match
				return KErrNone;
			sendToBgWgId=matchId;
			matchId=wgId;										// Go for second match
			}
		}
	if (matchId>=0)
		{
		iWsSession.SetWindowGroupOrdinalPosition(matchId,0);
		if (sendToBgWgId>=0)
			iWsSession.SetWindowGroupOrdinalPosition(sendToBgWgId,-1);	// Send it to background
		return KErrNone;
		}
	return KErrNotFound;
	}

