// EIKALSUP.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "eikalsup.h"
#include "eiksrv.pan"
#include <t32alm.h>
#include "eikalmct.h"
#include <eikenv.h>
#include <eiksrv.h>

const TInt KAlarmMaxSnooze=60;
const TInt KAlarmMinuteInMicroSeconds=60000000;

CEikAlmControlSupervisor::CEikAlmControlSupervisor()
//
//	Constructor
//
	{
	__DECLARE_NAME(_S("CEikAlmControlSupervisor"));
	}

CEikAlmControlSupervisor::~CEikAlmControlSupervisor()
//
//	Destructor
//
	{
	delete(iMinuteCountDown);
	delete(iAlarmAlert);
	}

void CEikAlmControlSupervisor::ConstructL()
//
//	Deferred construction
//
	{
	iMinuteCountDown=CPeriodic::NewL(ESnoozeCountDownPriority);
	CEikServAppUi* appUi=STATIC_CAST(CEikServAppUi*, CEikonEnv::Static()->EikAppUi());
	iAlarmAlert=new(ELeave) CEikAlarmControl(this, appUi);
	iAlarmAlert->ConstructL();
//	CEikonEnv::Static()->AddSleepingDialogToStackL(iAlarmAlert);
	iAlarmAlert->DrawableWindow()->SetPointerCapture(RWindowBase::TCaptureFlagEnabled); // ie not all groups
	}

void CEikAlmControlSupervisor::ServiceL(const RMessage &aMessage)
//
//	Service requests from the alert server.
//
	{  
	iAlarmControlState|=EShouldCompleteMessage;
	switch (aMessage.Function())
		{
    case EAlmOpCodeLogon:
		__ASSERT_ALWAYS(!(iAlarmControlState&EHasMessageLogon),Panic(EEsPanicAlarmAlert));
		iAlarmControlState|=EHasMessageLogon;
		iLogonPtr=aMessage.MessagePtr();
		iAlarmControlState&=~EShouldCompleteMessage;
		break;
    case EAlmOpCodeNotify:
		__ASSERT_ALWAYS(!(iAlarmControlState&EHasMessageRequest),Panic(EEsPanicAlarmAlert));
		iMsgPtr=aMessage.MessagePtr();
		iAlarmControlState|=EHasMessageRequest;
		iAlarmControlState&=~EShouldCompleteMessage;
		break;
    case EAlmOpCodeCancel:
		if ((iAlarmControlState&EHasMessageRequest))
			{
			iAlarmControlState&=~EHasMessageRequest;
			iMsgPtr.Complete(KErrCancel);
			}
		break;
	case EAlmOpCodeVisible:
		__ASSERT_DEBUG(iAlarmAlert,Panic(EEsPanicAlarmAlert));
		(aMessage.Int0())? iAlarmAlert->ShowAlarm() : iAlarmAlert->HideAlarm();
		break;
    case EAlmOpCodeSetState:
		SetAlertState(aMessage.Int0());		
		break;
    case EAlmOpCodeSetAlarm:
		UpdateAlarmInfo(aMessage);
		break;
	case EAlmOpCodeGetUserTime:
		ReturnTimeToSnooze(aMessage);
		break;
	case EAlmOpCodeSetDeferTime:
		UpdateSoundDeferTime(aMessage);
		break;
	default:
		aMessage.Complete(KErrNotSupported);
		}
	if (iAlarmControlState&EShouldCompleteMessage)
		aMessage.Complete(KErrNone);
	}

void CEikAlmControlSupervisor::CancelTimeCountDown()
//
//	Cancel the current snoozing.
//
	{
	iMinuteCountDown->Cancel();
	}

TInt CEikAlmControlSupervisor::CallbackSnoozeDecrement(TAny *aAlarmControl)
//
//	CallBack for the countdown timer
//
	{
	__ASSERT_ALWAYS(aAlarmControl,Panic(EEsPanicAlarmAlert));
	((CEikAlmControlSupervisor*)aAlarmControl)->DecrementSnoozeMinutes();
	return(KErrNone);
	}

void CEikAlmControlSupervisor::DecrementSnoozeMinutes()
//
//	Decrement the alarm alerts idea of minutes left to snooze.
//
	{
	iPauseSoundMinutes--;
	iAlarmAlert->UpdateSoundPauseTimeInterval(iPauseSoundMinutes);
	if (iPauseSoundMinutes<=0)
		CancelTimeCountDown();
	}

void CEikAlmControlSupervisor::StartTimeCountDown()
//
//	Start the snoozing process.
//
	{
	TCallBack callback(&CallbackSnoozeDecrement,this);
	CancelTimeCountDown();
	iMinuteCountDown->Start(KAlarmMinuteInMicroSeconds,KAlarmMinuteInMicroSeconds,callback);
	iAlarmAlert->UpdateSoundPauseTimeInterval(iPauseSoundMinutes); 
	}

void CEikAlmControlSupervisor::SynchronizeCountDownTimer()
	//
	// Recalculate the snooze time and synchronize the count down timer
	//
	{
	TCallBack callback(&CallbackSnoozeDecrement,this);
	CancelTimeCountDown();
	TTime now;
	now.HomeTime();
	if (iPauseSoundDueTime>now)
		{
		// sychronise timer (needed when machine has been turned off during snooze)
		TTimeIntervalSeconds seconds;
		iPauseSoundDueTime.SecondsFrom(now, seconds);
		TInt delay=((seconds.Int())%60)*1000000; // pity there's no TTime::MicroSeconds32From :-(
		iPauseSoundMinutes=(seconds.Int()/60)+1; // +1 because will be called back in less than a minute
		iMinuteCountDown->Start(delay,KAlarmMinuteInMicroSeconds,callback);
		}
	else 
		iPauseSoundMinutes=0;
	TInt alarmServerState=iAlarmAlert->CurrentServerState();
	if (!((alarmServerState&(EAlmSvrQuietPeriod|EAlmSvrSoundOff|EAlmSvrNoSoundToPlay)) && (iPauseSoundMinutes==0)))
		iAlarmAlert->UpdateSoundPauseTimeInterval(iPauseSoundMinutes); 
	}

void CEikAlmControlSupervisor::SetAlertState(TInt aAlarmServerStateFlags)
//
//	Update the alarm alerts information on the server state.
//
	{
	iAlarmAlert->UpdateForAlarmServerState(aAlarmServerStateFlags);
	}

void CEikAlmControlSupervisor::NotifyClient(TAlmAlertResponse aFlag)
//
//	Notify the alarm server of a change.
//
	{
	if (!(iAlarmControlState&EHasMessageRequest))
		return; // !! maybe should panic here
	iMsgPtr.Complete(aFlag);
	iAlarmControlState&=~EHasMessageRequest;
	}

void CEikAlmControlSupervisor::UpdateAlarmInfo(const RMessage& aMessage)
//
//	Update the alerts information on the current alarm.
//
	{
	iPauseSoundMinutes=0;
	iMinuteCountDown->Cancel();
	iPauseSoundDueTime.HomeTime();
	TFullName owner;
	TAlarmInfo alarm;
	TPckg<TAlarmInfo> pAlarm(alarm);
	aMessage.ReadL(aMessage.Ptr0(),pAlarm);
	aMessage.ReadL(aMessage.Ptr1(),owner);
	iAlarmAlert->UpdateAlarmInfo(alarm,owner);
	iAlarmAlert->UpdateForAlarmServerState(iAlarmAlert->CurrentServerState());
	}

void CEikAlmControlSupervisor::ReturnTimeToSnooze(const RMessage& aMessage) 
//
//	Return the time the user entered to snooze.
//
	{
	if (iPauseSoundMinutes<=0)
		iPauseSoundMinutes=KAlarmSnoozeIncrement;
	iPauseSoundDueTime.HomeTime();
	iPauseSoundDueTime+=TTimeIntervalMinutes(iPauseSoundMinutes);
	TPtrC8 pTime((TUint8*) &iPauseSoundDueTime,sizeof(TTime));
	aMessage.WriteL(aMessage.Ptr0(),pTime);
	StartTimeCountDown();
	}

void CEikAlmControlSupervisor::UpdateSoundDeferTime(const RMessage& aMessage)
//
//	Update the alerts information on the sound deferal time (quiet period).
//
	{
	TPtr8 pTime((TUint8*) &iQuietPeriodEndTime,sizeof(TTime));
	aMessage.ReadL(aMessage.Ptr0(),pTime);
	}

void CEikAlmControlSupervisor::CmdAcknowledgeAlarm()
//
//	The callbacks of the alarm server will reset the display
//
	{
	NotifyClient(EAlertResponseClear);
	}

void CEikAlmControlSupervisor::CmdPauseAlarmSound(TInt aNumMinutes)
//
//	The callbacks of the alarm server will reset the display
//
	{
	if (iPauseSoundMinutes+aNumMinutes<=0)
		return;
	iPauseSoundMinutes+=aNumMinutes;
	if (iPauseSoundMinutes>KAlarmMaxSnooze)
		{
		User::Beep(440, -25000);
		iPauseSoundMinutes-=KAlarmMaxSnooze;
		}
	NotifyClient(EAlertResponsePauseSound);
	}

void CEikAlmControlSupervisor::CmdSilenceAlarmSound()
//
//	The callbacks of the alarm server will reset the display
//
	{
	NotifyClient(EAlertResponseSilence);
	}

TBool CEikAlmControlSupervisor::CmdTaskAwayFromAlarm()
//
//	The callbacks of the alarm server will reset the display
//	and the alert state.
//
	{
	if (iAlarmAlert->CurrentServerState()&EAlmSvrNoSnoozeMemory)
		return(EFalse);
	NotifyClient(EAlertResponseSnooze); // Snooze in the alarm server sense
	return(ETrue);
	}

