Option Strict On

Imports System.IO
Imports System.Drawing
Imports System.Delegate
Imports System.Text
Imports System.Threading
Imports System.Runtime.Serialization.Formatters.Binary

Imports Mbark.Threading
Imports Mbark.UI
Imports Mbark.SensorMessages

Imports AxLSCAPTURECTRLLib
Imports LSCAPTURECTRLLib

Namespace Mbark.Sensors
    Public Class SmithsHeimannLScanSensor
        Inherits BaseSensor

#Region " Windows Form Designer generated code "

        Public Sub New()
            MyBase.New()

            'This call is required by the Windows Form Designer.
            InitializeComponent()

            'Add any initialization after the InitializeComponent() call
            CreateNew()
        End Sub

        'UserControl overrides dispose to clean up the component list.
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        'Required by the Windows Form Designer
        Private components As System.ComponentModel.IContainer

        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.  
        'Do not modify it using the code editor.
        '        Friend WithEvents mSHB_LS2Ctrl As AxLSCAPTURECTRLLib.AxLsCaptureCtrl
        Friend WithEvents TimeOutCounter As System.Windows.Forms.Timer
        '        Friend WithEvents mSHB_LS2Ctrl As AxLSCAPTURECTRLLib.AxLsCaptureCtrl
        Friend WithEvents mSHBMessageCtrl As Syncfusion.Windows.Forms.Tools.GradientLabel
        Friend WithEvents mSHBLScanSingleCtrl As AxLSCAPTURECTRLLib.AxLsCaptureCtrl
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.components = New System.ComponentModel.Container
            Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(SmithsHeimannLScanSensor))
            Me.TimeOutCounter = New System.Windows.Forms.Timer(Me.components)
            Me.mSHBMessageCtrl = New Syncfusion.Windows.Forms.Tools.GradientLabel
            Me.mSHBLScanSingleCtrl = New AxLSCAPTURECTRLLib.AxLsCaptureCtrl
            Me.InnerPanel.SuspendLayout()
            Me.MainPanel.SuspendLayout()
            CType(Me.OuterPanel, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.OuterPanel.SuspendLayout()
            CType(Me.mSHBLScanSingleCtrl, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.SuspendLayout()
            '
            'TimeoutIndicator
            '
            Me.TimeoutIndicator.Name = "TimeoutIndicator"
            Me.TimeoutIndicator.Size = New System.Drawing.Size(638, 16)
            '
            'CancelSensorButton
            '
            Me.CancelSensorButton.Name = "CancelSensorButton"
            '
            'ActivateSensorButton
            '
            Me.ActivateSensorButton.Name = "ActivateSensorButton"
            '
            'InnerPanel
            '
            Me.InnerPanel.Name = "InnerPanel"
            Me.InnerPanel.Size = New System.Drawing.Size(638, 358)
            '
            'MainPanel
            '
            Me.MainPanel.Controls.Add(Me.mSHBLScanSingleCtrl)
            Me.MainPanel.Controls.Add(Me.mSHBMessageCtrl)
            Me.MainPanel.Name = "MainPanel"
            Me.MainPanel.Size = New System.Drawing.Size(816, 408)
            '
            'OuterPanel
            '
            Me.OuterPanel.Name = "OuterPanel"
            Me.OuterPanel.Size = New System.Drawing.Size(640, 440)
            '
            'mSHBMessageCtrl
            '
            Me.mSHBMessageCtrl.BackgroundColor = New Syncfusion.Drawing.BrushInfo(Syncfusion.Drawing.GradientStyle.Vertical, System.Drawing.Color.FromArgb(CType(237, Byte), CType(240, Byte), CType(247, Byte)), System.Drawing.SystemColors.ActiveCaptionText)
            Me.mSHBMessageCtrl.BorderSides = CType((((System.Windows.Forms.Border3DSide.Left Or System.Windows.Forms.Border3DSide.Top) _
                        Or System.Windows.Forms.Border3DSide.Right) _
                        Or System.Windows.Forms.Border3DSide.Bottom), System.Windows.Forms.Border3DSide)
            Me.mSHBMessageCtrl.BorderStyle = System.Windows.Forms.Border3DStyle.Flat
            Me.mSHBMessageCtrl.Dock = System.Windows.Forms.DockStyle.Fill
            Me.mSHBMessageCtrl.Font = New System.Drawing.Font("Microsoft Sans Serif", 14.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
            Me.mSHBMessageCtrl.Location = New System.Drawing.Point(0, 0)
            Me.mSHBMessageCtrl.Name = "mSHBMessageCtrl"
            Me.mSHBMessageCtrl.Size = New System.Drawing.Size(816, 408)
            Me.mSHBMessageCtrl.TabIndex = 0
            Me.mSHBMessageCtrl.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
            '
            'mSHBLScanSingleCtrl
            '
            Me.mSHBLScanSingleCtrl.ContainingControl = Me
            Me.mSHBLScanSingleCtrl.Enabled = True
            Me.mSHBLScanSingleCtrl.Location = New System.Drawing.Point(456, 272)
            Me.mSHBLScanSingleCtrl.Name = "mSHBLScanSingleCtrl"
            Me.mSHBLScanSingleCtrl.OcxState = CType(resources.GetObject("mSHBLScanSingleCtrl.OcxState"), System.Windows.Forms.AxHost.State)
            Me.mSHBLScanSingleCtrl.Size = New System.Drawing.Size(1280, 1024)
            Me.mSHBLScanSingleCtrl.TabIndex = 1
            Me.mSHBLScanSingleCtrl.Visible = False
            '
            'SmithsHeimannLScanSensor
            '
            Me.Name = "SmithsHeimannLScanSensor"
            Me.Size = New System.Drawing.Size(640, 440)
            Me.InnerPanel.ResumeLayout(False)
            Me.MainPanel.ResumeLayout(False)
            CType(Me.OuterPanel, System.ComponentModel.ISupportInitialize).EndInit()
            Me.OuterPanel.ResumeLayout(False)
            CType(Me.mSHBLScanSingleCtrl, System.ComponentModel.ISupportInitialize).EndInit()
            Me.ResumeLayout(False)

        End Sub

#End Region

        Private Const AspectRatio As Single = 1576.0! / 1572.0!
        Private ConfigurationDirectory As String = "Configurations"
        Private ConfigurationFilename As String = "LS_ILM.cfg"
        Private mConfigurationFileLocation As String
        Private mShowAllCapturedImagesAsThumbnail As Boolean

        Private Const mInitExpirationTime As Integer = 15000 'ms
        Private Const mConfigExpirationTime As Integer = 10000 'ms
        Private Const DownloadCommandExpirationTime As Integer = 5000 'ms

        Private mCaptureExpirationTime As Integer = 30000  'ms
        Private mCaptureCriticalTime As Integer

        Protected Delegate Function ProcessDelegate() As Object
        Protected Delegate Function CaptureDelegate(ByVal CmdGuid As Guid) As Object
        Protected Delegate Sub ConfigurationDelegate(ByVal config As SensorConfiguration)

        Private mModality As SensorModality = SensorModality.Fingerprint
        Public Overrides ReadOnly Property Modality() As SensorModality
            Get
                Return mModality
            End Get
        End Property
        Private mActive As Boolean = False
        Public Overrides ReadOnly Property IsActive() As Boolean
            Get
                Return mActive
            End Get
        End Property
        Private mName As String = "Smiths Heimann"
        Public Overrides ReadOnly Property FriendlyName() As String
            Get
                Return mName
            End Get
        End Property
        Private Sub CreateNew()
            MyBase.TimeoutIndicator.CriticalTime = mCaptureCriticalTime '5 * 1000
            MyBase.MainPanelAspectRatio = AspectRatio

            mConfigurationFileLocation = SmithsHeimannShareClass.GetSmithsHeimannConfigurationFile
            If mConfigurationFileLocation = String.Empty Then Throw New FileNotFoundException("Configuration file")

            WritableRequiresConfiguration = False
            WritableHasConfigurationClass = False
            'if Configuration Class exist, must set mConfigurationClassname

            AddHandler mSHBLScanSingleCtrl.FingerPollFlatPictureDone, AddressOf mSHBLScanSingleCtrl_FingerPollFlatPictureDone
        End Sub

#Region "   Initialization      "

        Public Overrides ReadOnly Property InitializationCommandTemplate() As Threading.AsyncCommandTemplate
            Get
                Static init As AsyncCommandTemplate
                If init Is Nothing Then
                    init = New AsyncCommandTemplate
                    With init
                        .TargetMethod = CreateDelegate(GetType(ProcessDelegate), Me, "Initialize")
                        .ExpirationTime = mInitExpirationTime
                        .IgnoreUnderlyingHandleOfTargetControl = True
                    End With
                End If
                Return init
            End Get
        End Property

        Private Function Initialize() As Object
            Dim errorCode As Integer

            Try
                errorCode = mSHBLScanSingleCtrl.ILM_MAIN_init(mConfigurationFileLocation, MainInitConstants.lcINIT_HIDE_INIDLG)
                Dim noError As Boolean = errorCode = 0
                Dim alreadyInitialized As Boolean = errorCode = IlmErrorConstants.lcILM_ERR_ALREADY_INITIALIZED
                Dim isDirty As Boolean = errorCode > 600
                If noError Or alreadyInitialized Or isDirty Then
                    If isDirty Then
                        Me.mSHBMessageCtrl.Text = "Platten is dirty or" & vbNewLine & "exposed to direct light"
                    End If
                    SensorProperties()
                    MarkAsOnline()
                Else
                    WRitableRequiresRecovery = True

                    MarkAsOffline()
                    Dim ife As New InitializationFailureException
                    ife.MachineNotes = SmithsHeimannShareClass.ErrorCodeToString(errorCode)
                    ife.Sensor = Me
                    Throw ife
                End If

            Catch ex As Exception
                WritableRequiresRecovery = True
                MarkAsOffline()
                Dim ife As New InitializationFailureException
                ife.MachineNotes = SmithsHeimannShareClass.ErrorCodeToString(errorCode)
                ife.Sensor = Me
                Throw ife
            End Try


        End Function

        Private mSensorProperties As New SensorProperties
        Private Sub SensorProperties()
            Dim manufacturer, modelname, serialnumber As String
            With mSHBLScanSingleCtrl
                .ILM_MAIN_systemCheck(MainSystemCheckConstants.lcST_ILM_GET_VENDOR, mSensorProperties.Manufacturer)
                .ILM_MAIN_systemCheck(MainSystemCheckConstants.lcST_ILM_GET_PNAME, mSensorProperties.ModelName)
                mName = "Smiths Heimann " & mSensorProperties.ModelName
                .ILM_MAIN_systemCheck(MainSystemCheckConstants.lcST_ILM_GET_SERNUM, mSensorProperties.SerialNumber)
                Dim versionObj As Object
                .ILM_MAIN_getVersion(versionObj)
                Dim version As String = CType(versionObj, String())(0)
                Dim VersionArr() As String = version.Split(" ".ToCharArray)
                mSensorProperties.VendorLibraryName = VersionArr(0)
                mSensorProperties.VendorLibraryVersion = VersionArr(4)
                mSensorProperties.Modality = Modality
            End With
        End Sub
#End Region

#Region "       Configuration         "

        Private mIsConfigured As Boolean = False
        Public Overrides ReadOnly Property ConfigurationCommandTemplate() As Threading.AsyncCommandTemplate
            Get
                Static config As AsyncCommandTemplate
                If config Is Nothing Then
                    config = New AsyncCommandTemplate
                    With config
                        .TargetMethod = CreateDelegate(GetType(ConfigurationDelegate), Me, "Configuration")
                        .ExpirationTime = mConfigExpirationTime
                        .IgnoreUnderlyingHandleOfTargetControl = True
                    End With
                End If
                Return config
            End Get
        End Property

        Public Sub Configuration(ByVal config As SensorConfiguration)
        End Sub
#End Region

#Region "       Uninitialization        "
        Public Overrides Sub Uninitialize()
            MBARKDebugger.Writeline("SH: UNINIT")
            mSHBLScanSingleCtrl.ILM_MAIN_exit()
            MyBase.Uninitialize()
        End Sub
#End Region

#Region "       Capture         "
        Protected Friend mCaptureDone As Boolean
        Private mliveWidth As Integer = 800
        Private mliveHeight As Integer = 800
        Private mCaptureCommandTemplate As AsyncCommandTemplate
        Public Overrides ReadOnly Property CaptureCommandTemplate() As Threading.AsyncCommandTemplate
            Get
                If mCaptureCommandTemplate Is Nothing Then
                    mCaptureCommandTemplate = New AsyncCommandTemplate
                    With mCaptureCommandTemplate
                        .TargetMethod = CreateDelegate(GetType(ProcessDelegate), Me, "CaptureImage")
                        .ExpirationTime = mCaptureExpirationTime
                        .IgnoreUnderlyingHandleOfTargetControl = True
                    End With
                End If
                Return mCaptureCommandTemplate
            End Get
        End Property

        Private Function CaptureImage() As Object
            Dim rc As Integer
            WritablePollingWasCanceled = False
            WritableLastCaptureSuccessful = False
            WritableLatestThumbnail = Nothing
            Dim CaptureResultArray As CaptureResultCollection

            RawImageArray = Nothing
            TimeStamps = Nothing
            Try
                If Not SmithsHeimannShareClass.Open(mSHBLScanSingleCtrl, SmithsHeimannShareClass.ImageType.SingleFPCapture) Then
                    MarkAsOffline()
                    Dim sce As New CaptureFailureException
                    sce.Sensor = Me
                    sce.MachineNotes = "Cannot open sensor for recording"
                    Throw sce
                End If

                DisplayInstruction(Messages.Polling & vbNewLine)

                Dim rect(3) As Object
                rect(0) = 0  ' left 
                rect(1) = 0   ' top 
                rect(2) = mliveWidth ' right 
                rect(3) = mliveHeight ' bottom

                rc = mSHBLScanSingleCtrl.ILM_FINGER_pollFlatPicture(True, rect, mCaptureExpirationTime)
                If rc <> CommonErrorConstants.lcOK Then
                    MarkAsOffLine()
                    Dim sce As New CaptureFailureException
                    sce.MachineNotes = "Cannot start auto capture."
                    sce.Sensor = Me
                    Throw sce
                End If

                mCaptureDone = False
                WritablePollingWasCanceled = False
                WritableIsTimeout = False
                While (Not mCaptureDone) AndAlso (Not PollingWasCanceled) AndAlso (Not IsTimeout)
                    WaitWithDoEvents(50, 10)
                End While

                'Must stop the CounterTimer soon after Capture returns from the reader
                StopCountdownTimerNow()

                If IsTimeout Or PollingWasCanceled Then
                    MarkasOnline()
                    If PollingWasCanceled Then
                        Dim pce As New PollingCanceledException
                        pce.Sensor = Me
                        pce.MachineNotes = "Polling cancelled"
                        Throw pce
                    End If
                    If IsTimeout Then
                        Dim cte As New CaptureTimeoutException
                        cte.Sensor = Me
                        cte.MachineNotes = "Capture timeout"
                        Throw cte
                    End If
                End If

                DisplayInstruction()

                Dim CaptureResult As New CaptureResult
                ReDim Preserve RawImageArray(1)
                ReDim Preserve TimeStamps(1)
                rc = mSHBLScanSingleCtrl.GetResultRawPicture(0, RawImageArray(0))
                Dim bm As Bitmap = (New Bitmap(SmithsHeimannShareClass.FullImageToBitmap(Me, EmptyPalette, RawImageArray(0))))
                CaptureResult.ImageProperties.Image = bm
                CaptureResult.ImageProperties.Timestamp = DateTime.UtcNow
                CaptureResult.SensorProperties = mSensorProperties
                Me.LastReviewImageAcceptable = True
                WritableLatestThumbnail = bm

                MarkAsOnline()
                CaptureResultArray = New CaptureResultCollection(1)
                CaptureResultArray(0) = CaptureResult
                Return CaptureResultArray

            Catch ex As ThreadInterruptedException
                DisplayInstruction()
                Dim cte As New CaptureTimeoutException
                cte.Sensor = Me
                cte.MachineNotes = "Capture timeout"
                Throw cte
            Finally
                mSHBLScanSingleCtrl.ClearResultPicture(0)
                MarkAsOnline()
                SmithsHeimannShareClass.Close(mSHBLScanSingleCtrl, SmithsHeimannShareClass.ImageType.SingleFPCapture)
            End Try

        End Function
        Dim RawImageArray() As Object
        Dim TimeStamps() As Object
        Private Sub mSHBLScanSingleCtrl_FingerPollFlatPictureDone(ByVal sender As Object, ByVal e As AxLSCAPTURECTRLLib.ILsCaptureCtrlEvents_FingerPollFlatPictureDoneEvent) 'Handles mSHBLScanSingleCtrl.FingerPollFlatPictureDone
            MBARKDebugger.Writeline("Finger Poll Flat Picture")
            If Not e.timeout Then
                mCaptureDone = True
            Else
                WRitableIsTimeout = True
            End If

        End Sub
#End Region

#Region "       Download      "
        Protected Overrides Function CreateDownloadCommand(ByVal id As Guid) As AsyncCommand
            Dim DownloadCommand As New AsyncCommand(DownloadCommandTemplate)
            DownloadCommand.TargetMethodArg(0) = id
            Return DownloadCommand
        End Function

        Public Overrides ReadOnly Property DownloadCommandTemplate() As Threading.AsyncCommandTemplate
            Get
                Static download As AsyncCommandTemplate
                If download Is Nothing Then
                    download = New AsyncCommandTemplate
                    With download
                        .TargetMethod = CreateDelegate(GetType(DownloadDelegate), Me, "DownloadImage")
                        Dim args As Object() = {Guid.Empty}
                        .TargetMethodArgs(args)
                        .ExpirationTime = 5000 ' 3mins
                        .IgnoreUnderlyingHandleOfTargetControl = True
                    End With
                End If
                Return download
            End Get
        End Property
        Private Delegate Function DownloadDelegate(ByVal id As Guid) As Object
        Private Function DownloadImage(ByVal id As Guid) As Object
        End Function
#End Region


        Private Sub CancelSensorButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles CancelSensorButton.Click
            WRitablePollingWasCanceled = True
        End Sub

        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            Me.mSHBMessageCtrl.Font = UI.GlobalUISettings.Defaults.Fonts.LargeBold
        End Sub

        Private Sub DisplayInstruction(Optional ByVal message As String = Nothing)
            mSHBMessageCtrl.Text = message
            Refresh()
        End Sub


    End Class

    '<Serializable()> Public Class SmithsHeimmanLScanConfiguration
    '    Inherits SensorConfiguration

    '    Public Overrides Function Clone() As Object
    '        Dim newConfiguration As New SmithsHeimmanLScanConfiguration
    '        Return newConfiguration
    '    End Function

    'End Class
End Namespace

