'****************************************************************************
'* Archie Jacobs
'* Manufacturing Automation, LLC
'* ajacobs@mfgcontrol.com
'* 12-JUN-11
'*
'* Copyright 2011 Archie Jacobs
'*
'* Distributed under the GNU General Public License (www.gnu.org)
'*
'* This program is free software; you can redistribute it and/or
'* as published by the Free Software Foundation; either version 2
'* of the License, or (at your option) any later version.
'*
'* This program is distributed in the hope that it will be useful,
'* but WITHOUT ANY WARRANTY; without even the implied warranty of
'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'* GNU General Public License for more details.

'* You should have received a copy of the GNU General Public License
'* along with this program; if not, write to the Free Software
'* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
'*
'* 12-JUN-11 Created
'****************************************************************************
Public Class MomentaryButton
    Inherits MfgControl.AdvancedHMI.Controls.IndustrialButton

#Region "PLC Related Properties"
    '*****************************************************
    '* Property - Component to communicate to PLC through
    '*****************************************************
    Private _CommComponent As ICommComponent
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property CommComponent() As ICommComponent
        Get
            Return _CommComponent
        End Get
        Set(ByVal value As ICommComponent)
            _CommComponent = value
        End Set
    End Property


    '*****************************************
    '* Property - Address in PLC to Link to
    '*****************************************
    Private m_PLCaddressClick As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressClick() As String
        Get
            Return m_PLCaddressClick
        End Get
        Set(ByVal value As String)
            m_PLCaddressClick = value
        End Set
    End Property

    '*****************************************
    '* Property - Address in PLC to Link to
    '*****************************************
    Private NotificationIDVisibility As Integer
    Private m_PLCaddressVisibility As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressVisibility() As String
        Get
            Return m_PLCaddressVisibility
        End Get
        Set(ByVal value As String)
            m_PLCaddressVisibility = value
        End Set
    End Property
#End Region

#Region "Events"
    '****************************
    '* Event - Mouse Down
    '****************************
    Private Sub MomentaryButton_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        If m_PLCaddressClick <> "" And Enabled Then
            Try
                Select Case MyBase.OutputType
                    Case OutputTypes.MomentarySet : _CommComponent.WriteData(m_PLCaddressClick, 1)
                    Case OutputTypes.MomentaryReset : _CommComponent.WriteData(m_PLCaddressClick, 0)
                    Case OutputTypes.SetTrue : _CommComponent.WriteData(m_PLCaddressClick, 1)
                    Case OutputTypes.SetFalse : _CommComponent.WriteData(m_PLCaddressClick, 0)
                    Case OutputTypes.Toggle
                        Dim CurrentValue As Boolean
                        CurrentValue = _CommComponent.ReadAny(m_PLCaddressClick)
                        If CurrentValue Then
                            _CommComponent.WriteData(m_PLCaddressClick, 0)
                        Else
                            _CommComponent.WriteData(m_PLCaddressClick, 1)
                        End If
                End Select
            Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                If ex.ErrorCode = 1808 Then
                    DisplayError("""" & m_PLCaddressClick & """ PLC Address not found")
                Else
                    DisplayError(ex.Message)
                End If
            End Try
        End If
    End Sub


    '****************************
    '* Event - Mouse Up
    '****************************
    Private Sub MomentaryButton_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        If m_PLCaddressClick <> "" And Enabled Then
            Try
                Select Case MyBase.OutputType
                    Case OutputTypes.MomentarySet : _CommComponent.WriteData(m_PLCaddressClick, 0)
                    Case OutputTypes.MomentaryReset : _CommComponent.WriteData(m_PLCaddressClick, 1)
                End Select
            Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                If ex.ErrorCode = 1808 Then
                    DisplayError("""" & m_PLCaddressClick & """ PLC Address not found")
                Else
                    DisplayError(ex.Message)
                End If
            End Try
        End If
    End Sub

    '********************************************************************
    '* When an instance is added to the form, set the comm component
    '* property. If a comm component does not exist, add one to the form
    '********************************************************************
    Protected Overrides Sub OnCreateControl()
        MyBase.OnCreateControl()


        If Me.DesignMode Then
            '********************************************************
            '* Search for ICommComponent component in parent form
            '* If one exists, set the client of this component to it
            '********************************************************
            Dim i = 0
            Dim j As Integer = Me.Parent.Site.Container.Components.Count - 1
            While _CommComponent Is Nothing And i < j
                If Me.Parent.Site.Container.Components(i).GetType.GetInterface("ICommComponent") IsNot Nothing Then _CommComponent = Me.Parent.Site.Container.Components(i)
                i += 1
            End While

            '************************************************
            '* If no comm component was found, then add one and
            '* point the CommComponent property to it
            '*********************************************
            If _CommComponent Is Nothing Then
                Me.Parent.Site.Container.Add(New TwinCATComm)
                _CommComponent = Me.Parent.Site.Container.Components(Me.Parent.Site.Container.Components.Count - 1)
            End If
        Else
            SubscribeToCommDriver()
        End If
    End Sub
#End Region

#Region "Subscribing and PLC data receiving"
    '**************************************************
    '* Subscribe to addresses in the Comm(PLC) Driver
    '**************************************************
    Private SubscribedPLCAddressVisibility As String
    Private Sub SubscribeToCommDriver()
        If Not DesignMode And IsHandleCreated Then
            '*************************
            '* Visbility Subscription
            '*************************
            '* If already subscribed, but address is changed, then unsubscribe first
            If NotificationIDVisibility > 0 And SubscribedPLCAddressVisibility <> m_PLCaddressVisibility Then
                _CommComponent.UnSubscribe(NotificationIDVisibility)
            End If
            '* Is there an address to subscribe to?
            If m_PLCaddressVisibility <> "" Then
                Try
                    'NotificationIDVisibility = _CommComponent.Subscribe(m_PLCaddressVisibility, 250, AddressOf PolledDataReturnedVisibility)
                    NotificationIDVisibility = _CommComponent.Subscribe(m_PLCaddressVisibility, 250, AddressOf PolledDataReturnedVisibility, " ", 0)
                Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                    If ex.ErrorCode = 1808 Then
                        DisplayError("""" & m_PLCaddressVisibility & """ PLC Address not found")
                    Else
                        DisplayError(ex.Message)
                    End If

                    '* If it is not a Symbol Not Found error, then retry
                    'If ex.ErrorCode <> 1808 Then
                    If SubscribeRetryTimer Is Nothing Then
                        SubscribeRetryTimer = New Windows.Forms.Timer
                        SubscribeRetryTimer.Interval = 10000
                        AddHandler SubscribeRetryTimer.Tick, AddressOf Retry_Tick
                    End If

                    SubscribeRetryTimer.Enabled = True
                    Exit Sub
                    'End If
                End Try
                SubscribedPLCAddressVisibility = m_PLCaddressVisibility
                If SubscribeRetryTimer IsNot Nothing Then
                    SubscribeRetryTimer.Enabled = False
                    SubscribeRetryTimer.Dispose()
                End If
            End If
        End If
    End Sub

    Private SubscribeRetryTimer As Windows.Forms.Timer
    Private Sub Retry_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        SubscribeToCommDriver()
    End Sub


    Private Sub PolledDataReturnedVisibility(ByVal Values() As String)
        Try
            MyBase.Visible = Values(0)
        Catch
            DisplayError("INVALID Visibilty VALUE RETURNED!")
        End Try
    End Sub
#End Region

#Region "Error Display"
    '********************************************************
    '* Show an error via the text property for a short time
    '********************************************************
    Private OriginalText As String
    Private WithEvents ErrorDisplayTime As System.Windows.Forms.Timer
    Private Sub DisplayError(ByVal ErrorMessage As String)
        If ErrorDisplayTime Is Nothing Then
            ErrorDisplayTime = New System.Windows.Forms.Timer
            AddHandler ErrorDisplayTime.Tick, AddressOf ErrorDisplay_Tick
            ErrorDisplayTime.Interval = 5000
        End If

        '* Save the text to return to
        If Not ErrorDisplayTime.Enabled Then
            OriginalText = Me.Text
        End If

        ErrorDisplayTime.Enabled = True

        Me.Text = ErrorMessage
    End Sub


    '**************************************************************************************
    '* Return the text back to its original after displaying the error for a few seconds.
    '**************************************************************************************
    Private Sub ErrorDisplay_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ErrorDisplayTime.Tick
        Text = OriginalText

        If ErrorDisplayTime IsNot Nothing Then
            ErrorDisplayTime.Enabled = False
            ErrorDisplayTime.Dispose()
            ErrorDisplayTime = Nothing
        End If
    End Sub
#End Region
End Class
