//
//  Translate White Balance into a "current value".
//
ULONG
CHardwareSimulation::
GetCurrentWhiteBalance()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    ULONG   Value = 0;

    if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
    {
        Value = (ULONG) GetRandom( pSettings->WhiteBalanceSetting.Min, pSettings->WhiteBalanceSetting.Max );
    }

    if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Value = pSettings->WhiteBalanceSetting.VideoProc.Value.ul;
    }

    //  Locked just reports the last value set...
    if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
    {
        Value = m_LastReportedWhiteBalance;
    }

    m_LastReportedWhiteBalance= Value;
    return Value;
}
BOOLEAN
CImageHardwareSimulation::
IsPhotoConfirmationNeeded()
/*++

Routine Description:

    Check flags for photo confirmation and return
    whether driver should issue confirmation.

--*/
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();

    return pSettings ? pSettings->bPhotoConfirmation : FALSE;
}
//
//  Translate Exposure Mode to an Exif Exposure Program value
//
USHORT
CHardwareSimulation::
GetExposureProgram()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    USHORT   Value = 0;  // Undefined.

    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Value = 1;  // Manual
    }
    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
    {
        Value = 2;  // Normal
    }

    //  TODO: Extend SceneMode to ISP settings so I can use it here to capture Portrait mode, etc.
    return Value;
}
//
//  Translate Exposure settings into a "current value".
//
LONGLONG
CHardwareSimulation::
GetCurrentExposureTime()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    LONGLONG   Value = 0;
    LPCSTR      Mode = "[UNKNOWN]";

    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
    {
        //  Get random value in global setting's bound (LONG)
        //  I'm abandoning the reported min/max and using something more reasonable.
        Value = GetRandom( MIN_EXPOSURE_TIME*5, DEF_EXPOSURE_TIME*5 );
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO";
    }

    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Value = pSettings->ExposureSetting.VideoProc.Value.ll;
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL";
    }

    //  Locked just reports the last value set...
    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
    {
        Value = m_LastReportedExposureTime;
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK";
    }

    DBG_TRACE("ExposureMode=0x%016llX (%s), Time=%llu00ns, LastReported=%llu00ns",
              pSettings->ExposureMode, Mode, Value, m_LastReportedExposureTime );

    m_LastReportedExposureTime = Value;
    return Value;
}
//
//  Translate ISO settings into a "current value".
//
ULONG
CHardwareSimulation::
GetCurrentISOSpeed()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    ULONG   Value = 0;

    if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_AUTO )
    {
        Value = GetRandom( (ULONG) 50, (ULONG) 3200 );
    }
    else if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_MANUAL )
    {
        Value = pSettings->ISOValue;
    }
    else
    {
        Value =             //  Try converting any legacy presets to a manual value.
            IsoPreset2Value( pSettings->ISOMode );
    }
    return Value;
}
//
//  Helper function that collects current settings into our metadata structure.
//
METADATA_IMAGEAGGREGATION
CImageHardwareSimulation::
GetMetadata()
{
    PAGED_CODE();

    METADATA_IMAGEAGGREGATION Metadata;
    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();

    //  Wipe the metadata so all settings will default to "Not Set".
    RtlZeroMemory( &Metadata, sizeof(Metadata) );

    //  Identify the current PFS frame number.
    //  If PFS not active, then this item is not present.
    Metadata.FrameId.Set = IsPfsActive();
    Metadata.FrameId.Value = (ULONG) m_PfsFrameNumber;
    DBG_TRACE("Metadata.FrameId.Set=%s, Metadata.FrameId.Value=%d",
              (Metadata.FrameId.Set?"Yes":"No"), Metadata.FrameId.Value);

    //  Just reflect the exposure time from the setting.
    //Metadata.ExposureTime.Set = TRUE;
    //Metadata.ExposureTime.Value = GetCurrentExposureTime();

    //  Just reflect the ISO Speed from the setting.
    Metadata.ISOSpeed = CMetadataLong(GetCurrentISOSpeed());
    DBG_TRACE("ISO=%d, ISO Flags=0x%016llX", Metadata.ISOSpeed.Value, pSettings->ISOMode);

    //  TODO: Do we need to bracket this by whether or not a flash has been taken?
    //  Report the current flash mode.
    Metadata.FlashOn = CMetadataLong((ULONG) pSettings->FlashMode);

    //  Report the current flash power.
    Metadata.FlashPower = CMetadataLong(pSettings->FlashValue);

    //  Set the White Balance lock state.
    Metadata.WhiteBalanceLocked = CMetadataLong(
                                      ( (pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK)
                                        == KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) );

    //  Set the Exposure lock state.
    Metadata.ExposureLocked = CMetadataLong(
                                  ( (pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK)
                                    == KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) );

    Metadata.ExposureTime =
        //CMetadataRational(GetCurrentExposureTime(), 10000000);
        CMetadataLongLong( GetCurrentExposureTime() );

    Metadata.LensPosition = CMetadataLong( pSettings->FocusSetting.VideoProc.Value.ul );

    Metadata.SceneMode = CMetadataULongLong(KSCAMERA_EXTENDEDPROP_SCENEMODE_AUTO);   //TODO: Need to fill in real value from CCaptureFilter::m_SceneMode

    Metadata.WhiteBalanceMode = CMetadataLong((ULONG) pSettings->WhiteBalanceMode);

    CExtendedVidProcSetting Zoom;
    m_Sensor->GetZoom( &Zoom );
    Metadata.ZoomFactor = CMetadataLong(Zoom.GetLONG());  //TODO: Fill in a real value from zoom simulation.

    Metadata.FocusLocked = CMetadataLong(FALSE);    //TODO: Fill in a real value when we complete the focus changes.

    //  Add EVCompensation metadata...
    Metadata.EVCompensation = CMetadataEVCompensation(pSettings->EVCompensation.Mode, pSettings->EVCompensation.Value);

    Metadata.Orientation = CMetadataShort(Metadata_Orientation_TopBottomLeftRight); //TODO: Randomize?

    {
        LARGE_INTEGER   SystemTime;
        LARGE_INTEGER   LocalTime;

        KeQuerySystemTimePrecise( &SystemTime );
        ExSystemTimeToLocalTime( &SystemTime, &LocalTime );
        RtlTimeToTimeFields( &LocalTime, &Metadata.LocalTime.Time );
        Metadata.LocalTime.Set = TRUE;
    }

    Metadata.Make = CMetadataShortString("Make: Microsoft SOC Camera");
    Metadata.Model = CMetadataShortString( "Model: AvsCam" );
    Metadata.Software = CMetadataShortString( "Software: Microsoft Camera Sim" );

    Metadata.ColorSpace.Set = TRUE;
    Metadata.ColorSpace.Value = 0xFFFF; // 0xFFFF Means "uncalibrated".  Use this value for all non-RGB formats.

    Metadata.Gamma = CMetadataRational();

    Metadata.MakerNote = CMetadataShortString( "Maker's Note..." );

    //  Just reflect the exposure time from the setting.
    //Metadata.ExposureTime =
    //    CMetadataRational( GetCurrentExposureTime(), 1000 );    // report exposure time as milliseconds.

    Metadata.FNumber = CMetadataRational(4);   // Fake an FNumber of 4. // TODO: It looks like we might be able to calculate this.

    Metadata.ExposureProgram.Set = TRUE;
    Metadata.ExposureProgram.Value = GetExposureProgram();

    Metadata.ShutterSpeedValue = CMetadataSRational();   // TODO: Calculate this from the ExposureTime.  ***
    Metadata.Aperture = CMetadataRational(4);   // TODO: Calculate this from the F-Number. (We're currently faking the FNumber.)
    Metadata.Brightness = CMetadataSRational(0);    // TODO: Find a more reasonable brightness value.
    Metadata.ExposureBias = CMetadataSRational(0);  // TODO: More reasonable?
    Metadata.SubjectDistance = CMetadataRational(0xFFFFFFFF);   // Distance in meters.  Infinity.  (Anything better?)

    Metadata.MeteringMode.Set = TRUE;
    Metadata.MeteringMode.Value = (USHORT) GetRandom( (ULONG) 1, (ULONG) 6);    // Pick a number ... any number.

    Metadata.LightSource.Set = TRUE;
    Metadata.LightSource.Value = 1;     // TODO: Pick a random value; but override when a flash occurs.

    Metadata.Flash.Set = TRUE;
    Metadata.Flash.Value = (UINT16) pSettings->FlashMode;    // We assume that the flash fires when requested!
    DBG_TRACE("FlashMode=0x%016llX, FlashPower=%d", pSettings->FlashMode, pSettings->FlashValue);

    Metadata.FocalLength = CMetadataRational(); //  TODO: Calculate?
    Metadata.FocalPlaneXResolution = CMetadataRational();   //  TODO: Calculate?
    Metadata.FocalPlaneYResolution = CMetadataRational();   //  TODO: Calculate?
    Metadata.ExposureIndex = CMetadataRational();           //  TODO: Calculate?

    Metadata.ExposureMode.Set = TRUE;
    Metadata.ExposureMode.Value = 0 ;   // Assume Auto exposure.
    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Metadata.ExposureMode.Value = 0 ;   // Manual exposure.
    }

    Metadata.WhiteBalance.Set = TRUE;
    Metadata.WhiteBalance.Value = 0 ;   // Assume Auto white balance.
    if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Metadata.WhiteBalance.Value = 0 ;   // Manual while balance.
    }

    Metadata.DigitalZoomRatio = CMetadataRational(1);

    Metadata.FocalLengthIn35mmFilm = CMetadataShort(0);
    Metadata.SceneCaptureType = CMetadataShort(0);
    Metadata.GainControl = CMetadataRational();
    Metadata.Contrast = CMetadataShort(0);
    Metadata.Saturation = CMetadataShort(0);
    Metadata.Sharpness = CMetadataShort(0);
    Metadata.SubjectDistanceRange = CMetadataShort(0);

    //  Report (optional) focus state.
    KSCAMERA_EXTENDEDPROP_FOCUSSTATE    State = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_UNINITIALIZED;
    if( NT_SUCCESS(m_Sensor->GetFocusState( &State )) )
    {
        Metadata.FocusState = CMetadataLong((UINT32)State);
    }

    return Metadata;
}