/** Calculates a difference between the system UTC time and the GPS based UTC time.
Accuracy of the calculations is affected by:
   - time required to process the satellite information in the GPS HW
   - time required to transfer the information over a HW link from the GPS HW to a mobile phone
   - time required to receive the information by a Symbian OS drivers and decode by the AGPS
     integration module

@param aSatInfo A satellite information with the GPS based UTC time
@param aTimeCorr A time correction that must be applied to the System UTC time. Not valid if the method returns an error.
@return KErrNone if sucedded. 
        KErrNotSupported if the satellite (GPS based UTC time) or the position 
        reception time is not present (0).
@see TPositionSatelliteInfo
@internalComponent
*/
TInt CAutoClockAdjust::CalculateTimeCorrection(const TPositionSatelliteInfo &aSatInfo, TTimeIntervalMicroSeconds &aTimeCorr)
	{
	LBSLOG(ELogP1, "CAutoClockAdjust::CalculateTimeCorrection()\n");
	// The System UTC time when the location has been received from a GPS
	TTime recTime;
	// GPS based UTC time (satellite time)
	TTime satTime;

	TPosition pos;
	TInt err = KErrNone;
		
	aSatInfo.GetPosition(pos);
	recTime = pos.Time();
	satTime = aSatInfo.SatelliteTime();
	
	if ((recTime == 0) || (satTime == 0))
		{
		err = KErrNotSupported;
		}
	else
		{
		aTimeCorr = satTime.MicroSecondsFrom(recTime);
		}
	
	return err;
	}
/** Adjusts system time if required. The decision whether the adjustment is needed or not
is based on the following criterias:
 - satellite time must be present in the location update
 - time threshold must be exceeded
 - time from a last adjustment is greater than a defined interval.
 
@param aStatus An error code.
@param TPositionSatelliteInfo Position and time information. 
							  If clock adjustment takes place the TPosition::iTime is 
							  re-set to the satellite time.
@see CLbsAdmin
@see TPositionSatelliteInfo
*/
void CAutoClockAdjust::LocationUpdate(TInt aStatus, TPositionSatelliteInfo& aPosInfo)
	{
	LBSLOG(ELogP1, "CAutoClockAdjust::LocationUpdate()\n");
	TTimeIntervalMicroSeconds timeCorr;
	TTime sysTime;
	TInt err;
	
	// If adjustment on, no error, and satellite information present
	if ((iClockAdjustSetting == CLbsAdmin::EClockAdjustOn) && (aStatus == KErrNone) &&
	    ((aPosInfo.PositionClassType() & EPositionSatelliteInfoClass) == EPositionSatelliteInfoClass))
		{
		// Is is time do do another time adjustment?
		sysTime.UniversalTime();
		if (Abs(sysTime.MicroSecondsFrom(iLastAdjustment).Int64()) > (1000*iAdjustInterval))
			{
			const TPositionSatelliteInfo& satInfo = static_cast<const TPositionSatelliteInfo&>(aPosInfo);
			err = CalculateTimeCorrection(satInfo, timeCorr);
			if (err == KErrNone)
				{
				// Is threshold exceeded? 
				if (Abs(timeCorr.Int64()) > (1000*iAdjustThreshold))
					{
					sysTime.UniversalTime();
					sysTime += timeCorr;
					LBSLOG(ELogP9, "->S CGpsSetClockBase::SetUTCTime() ClockModule\n");
					LBSLOG5(ELogP9, "  > TTime sysTime  = %02d:%02d:%02d.%06d\n", sysTime.DateTime().Hour(), 
																				sysTime.DateTime().Minute(),
																				sysTime.DateTime().Second(),
																				sysTime.DateTime().MicroSecond());

					err = iSetClockImpl->SetUTCTime(sysTime);
					LBSLOG2(ELogP9, "  Return  = %d\n", err);

					if (err == KErrNone)
						{				
						// Sync the position time with the satellite time
						// to avoid re-adjusting the system time by the manual clock adjustment component.
						TPosition pos;
						aPosInfo.GetPosition(pos);
						pos.SetTime(aPosInfo.SatelliteTime());
						aPosInfo.SetPosition(pos);
						LBSLOG2(ELogP2, "ACTION: Clock Adjusted by %ld\n", timeCorr.Int64());
						}
					}
					
				if (err == KErrNone)
					{				
					// Remember the current time even if threshold not exceeded
					iLastAdjustment = sysTime;
					}
				else
					{
					LBSLOG_WARN2(ELogP3, "Clock Adjustment failed. Error: %d\n", err);
					}
				}
			}
		}
	}
void CT_LbsClientPosTp2::CheckPositionSatelliteInfoL(TPositionSatelliteInfo& aSatelliteInfo)
	{
	CheckPositionCourseInfoL(aSatelliteInfo);
	if((TUint)aSatelliteInfo.NumSatellitesUsed() != KNumberOfSatellitesUsed ||
	   aSatelliteInfo.SatelliteTime() != TTime(KSatelliteTime) ||
	   (TUint)aSatelliteInfo.NumSatellitesInView() != KNumberOfSatellitesInView ||
	   aSatelliteInfo.HorizontalDoP() != KHorizontalDoPValue ||
	   aSatelliteInfo.VerticalDoP() != KVerticalDoPValue ||
	   aSatelliteInfo.TimeDoP() != KTimeDoPValue)
	   {
		_LIT(KErrBasicSat, "Basic satellite information not correct");
		LogErrorAndLeaveL(KErrBasicSat);
		}
		TInt sats = aSatelliteInfo.NumSatellitesInView();
	for (int i = 0; i < sats; i++)
		{
		TSatelliteData satelliteData;
		TInt err = aSatelliteInfo.GetSatelliteData(i,satelliteData);
		if (err != KErrNone)
			{
			_LIT(KErrGetSat, "Not possible to get satellite data, error code = %d");
			TBuf<100> buf;
			buf.Format(KErrGetSat, err);
			LogErrorAndLeaveL(buf);
			}
		if ( (i%2) == 0 )
			{
			if(	satelliteData.SatelliteId() != (KSatelliteId +i) ||
				satelliteData.Azimuth() != KAzimuth ||
				satelliteData.Elevation() != KElevation ||
				satelliteData.IsUsed() != KIsUsed ||
				satelliteData.SignalStrength() != KSignalStrength)
				{
				_LIT(KErrSatDataEven, "Incorrect satellite data on even satellites");
				LogErrorAndLeaveL(KErrSatDataEven);
				}
			}
		else
			{
			if(	satelliteData.SatelliteId() != (KSatelliteId +i) ||
				satelliteData.Azimuth() != KAzimuthOdd ||
				satelliteData.Elevation() != KElevationOdd ||
				satelliteData.IsUsed() != KIsUsedOdd ||
				satelliteData.SignalStrength() != KSignalStrengthOdd)
				{
				_LIT(KErrSatDataOdd, "Incorrect satellite data on odd satellites");
				LogErrorAndLeaveL(KErrSatDataOdd);
				}
			}

		}
	}
// ---------------------------------------------------------
// CPosPSYClearPositionDataTest::CheckSatelliteInfoClearsL
//
// (other items were commented in a header).
// ---------------------------------------------------------
//    
void CPosPSYClearPositionDataTest::CheckSatelliteInfoClearsL()
    {
    TBool allIsCleared = ETrue;
	TPositionSatelliteInfo* satInfo = static_cast<TPositionSatelliteInfo*> (iPosInfo);

	if (satInfo->SatelliteTime() == KSatelliteTime)
		{
		_LIT(KError, "Satellite Time was not cleared for TPositionSatelliteInfo.");
        AddTestResultL(KError, EErrorMessage);
		allIsCleared = EFalse;
		}
	if (!Math::IsNaN(satInfo->HorizontalDoP()))
		{
		if (satInfo->HorizontalDoP() == KSatelliteHorizontalDoP)
			{	
			_LIT(KError, "Horizontal DoP was not cleared for TPositionSatelliteInfo.");
			AddTestResultL(KError, EErrorMessage);
			allIsCleared = EFalse;
			}
		}
	if (!Math::IsNaN(satInfo->VerticalDoP()))
		{
		if (satInfo->VerticalDoP() == KSatelliteVerticalDoP)
			{
			_LIT(KError, "Vertical DoP was not cleared for TPositionSatelliteInfo.");
			AddTestResultL(KError, EErrorMessage);
			allIsCleared = EFalse;
			}
		}
	if (!Math::IsNaN(satInfo->TimeDoP()))
		{
		if (satInfo->TimeDoP() == KSatelliteTimeDoP)
			{
			_LIT(KError, "Time DoP was not cleared for TPositionSatelliteInfo.");
			AddTestResultL(KError, EErrorMessage);
			allIsCleared = EFalse;
			}
		}

	TBool satelliteDataNotCleared = EFalse;
	for (TInt  i = 0; i < KSatelliteNumInView; i++)
		{
		TSatelliteData satellite;
		TInt error = satInfo->GetSatelliteData(i, satellite);
		if (error != KErrNotFound)
			{
			if (!Math::IsNaN(satellite.Azimuth()))
				{
				if (satellite.Azimuth() == KAzimuth)
					{
					satelliteDataNotCleared = ETrue;
					}
				}
			if (!Math::IsNaN(satellite.Elevation()))
				{
				if (satellite.Elevation() == KElevation)
					{
					satelliteDataNotCleared = ETrue;
					}
				}

			if (satellite.SatelliteId() == KSatelliteId ||
				satellite.SignalStrength() == KSignalStrength)
				{
				satelliteDataNotCleared = ETrue;
				}
			}
		}
	
	if (satelliteDataNotCleared)
		{
		_LIT(KError, "Satellite Data was not cleared for all satellites in TPositionSatelliteInfo.");
		AddTestResultL(KError, EErrorMessage);
		allIsCleared = EFalse;
		}

	if (allIsCleared)
		{
		_LIT(KInfo, "All fields were cleared for TPositionSatelliteInfo.");
		AddTestResultL(KInfo, EInfoMessage);
		}
    }