/*
* 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 the License "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 "drivewatcher.h"
#include "log.h"

namespace Swi
{
// CDriveWatcher
_LIT(KNotificationDirectory,"mediachange\\");

/*static*/ CDriveWatcher* CDriveWatcher::NewL(RFs& aFs, TInt aDrive, 
												MDriveObserver& aObserver,
							 					TInt aPriority)
	{
	CDriveWatcher* self=NewLC(aFs, aDrive, aObserver, aPriority);
	CleanupStack::Pop(self);
	return self;
	}
	
/*static*/ CDriveWatcher* CDriveWatcher::NewLC(RFs& aFs, TInt aDrive, 
												MDriveObserver& aObserver,
							 					TInt aPriority)
	{
	CDriveWatcher* self=new(ELeave) CDriveWatcher(aFs, aDrive, aObserver, aPriority);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;	
	}
	
CDriveWatcher::~CDriveWatcher()
	{
	Cancel();
	}

CDriveWatcher::CDriveWatcher(RFs& aFs, TInt aDrive, MDriveObserver& aObserver,
							 TInt aPriority)
	: CActive(aPriority), iFs(aFs), iDrive(aDrive), iObserver(aObserver)
	{
	CActiveScheduler::Add(this);
	}

void CDriveWatcher::ConstructL()
	{
	// Notify observer of media change since we're beginning from an unknown state
	NotifyMediaChange();
	
	// Start watching for changes
	WaitForChangeL();
	}

void CDriveWatcher::DoCancel()
	{
	iFs.NotifyChangeCancel(iStatus);
	}

TBool CDriveWatcher::IsMediaPresentL()
	{
	TVolumeInfo volumeInfo;
	TInt err=iFs.Volume(volumeInfo, iDrive);
	
	switch (err)
		{
		case KErrNotReady: // No Media present
			{
			return EFalse;	
			}
			
		case KErrNone: // Media Present
			{
			return ETrue;
			}
		}

	User::Leave(err);	
	return ETrue;	// Will never get here.
	}

void CDriveWatcher::NotifyMediaChange()
	{
	// Unsuccessful media change is not fatal, so handle here
	TRAPD(err,iObserver.MediaChangeL(iDrive, IsMediaPresentL() ? MDriveObserver::EMediaInserted : MDriveObserver::EMediaRemoved));

	if (err != KErrNone)
		{
	    DEBUG_PRINTF2(_L8("SWI Daemon - Media change notification failed with code %d"), err);
		}
	}
	
void CDriveWatcher::RunL()
	{
	NotifyMediaChange();
			
	WaitForChangeL();
	}

void CDriveWatcher::WaitForChangeL()
	{
	TChar drive;
	User::LeaveIfError(iFs.DriveToChar(iDrive, drive));
	TUint driveChar(drive); // Can't pass TChar to Format().
	
	TPath notificationPath;
	TPath privatePath;
	_LIT(KNotificationPathFormat,"%c:%S%S");
	User::LeaveIfError(iFs.PrivatePath(privatePath));

	notificationPath.Format(KNotificationPathFormat, driveChar, &privatePath, &KNotificationDirectory);	
	
	iFs.NotifyChange(ENotifyEntry, iStatus, notificationPath);

	SetActive();
	}
	
}
