// APSSCAN.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

//
// AppArc recognizer and application scanning
//

#include "apsscan.h"

// A FsMonitor checks for any changes to the file entries (ENotifyEntry)
// If a change is detected, a CallBack function is called after a short pause.
// If there are further changes, the CallBack is not called again until after 3 secs have elapsed.

const TInt KApaFsMonitorPause=250000;			// Wait 0.25s before calling CallBack
const TInt KApaFsMonitorPeriod=3000000;			// Don't call CallBack again before 3s have elapsed

//
// Class CApaFsMonitor
//

EXPORT_C CApaFsMonitor::~CApaFsMonitor()
	{
	Cancel();
	delete iFsTimer;
	}

CApaFsMonitor::CApaFsMonitor(RFs& aFs, const TDesC& aLocation, TCallBack aCallBack)
	: CActive(EPriorityIdle),
	iFs(aFs),
	iCallBack(aCallBack),
	iLocation(aLocation)
	{
	CActiveScheduler::Add(this);
	}

EXPORT_C CApaFsMonitor* CApaFsMonitor::NewL(RFs& aFs,const TDesC& aLocation, TCallBack aCallBack)
	{
	CApaFsMonitor* self=new(ELeave) CApaFsMonitor(aFs,aLocation,aCallBack);
	CleanupStack::PushL(self);
	self->iFsTimer=CPeriodic::NewL(CActive::EPriorityIdle);
	CleanupStack::Pop();
	return self;
	}

void CApaFsMonitor::DoCancel()
	{
	iFs.NotifyChangeCancel(iStatus);
	iFsTimer->Cancel();
	}

void CApaFsMonitor::RunL()
	{
	iFsHasChanged=ETrue;
	if (!iIsBlocked && !iFsTimer->IsActive())
		iFsTimer->Start(KApaFsMonitorPause,KApaFsMonitorPeriod,TCallBack(TimerCallBack,this));
	}

EXPORT_C void CApaFsMonitor::Start(TNotifyType aNotifyType)
	{
	iNotifyType=aNotifyType;
	DoCancel();
	DoStart();
	}

void CApaFsMonitor::DoStart()
	{
	if (iLocation.Length())
		iFs.NotifyChange(iNotifyType,iStatus,iLocation);
	else
		iFs.NotifyChange(iNotifyType,iStatus);
	SetActive();
	}

EXPORT_C TNotifyType CApaFsMonitor::NotifyType() const
	{
	return iNotifyType;
	}

EXPORT_C void CApaFsMonitor::SetBlocked(TBool aIsBlocked)
	{
	iIsBlocked=aIsBlocked;
	if (iIsBlocked==EFalse)		// If end of a blocked period, notify if a change was detected
		{
		if (iFsHasChanged && !iFsTimer->IsActive())
			{
			iFsTimer->Start(KApaFsMonitorPause,KApaFsMonitorPeriod,TCallBack(TimerCallBack,this));
			}
		}
	}

TInt CApaFsMonitor::TimerCallBack(TAny* aObject)
	{
	CApaFsMonitor* self=(CApaFsMonitor*)aObject;
	if (self->iFsHasChanged && !self->iIsBlocked)
		{
		self->iFsHasChanged=EFalse;
		self->DoStart();
		self->iCallBack.CallBack();		// Should not leave, but if it does, it's OK
		}
	else
		self->iFsTimer->Cancel();
	return KErrNone;
	}
