Imports EgtBEAMWALL.Core.ConstMachComm
Imports EgtBEAMWALL.Supervisor.CommVar
Imports EgtUILib
Imports EgtWPFLib5
Imports EgtBEAMWALL.Core
Imports ISOCNC.Remoting

Public Class RWVariableManager

   Private m_Tpa As TPAComm = Nothing
   Friend ReadOnly Property Tpa As TPAComm
      Get
         Return m_Tpa
      End Get
   End Property

   Private m_Proxy_VariableCommandExecutedEventHandler As New VariableCommandExecutedEventHandler(AddressOf RemoteObject_VariableCommandExecuted)

   ' lock per Synclock
   Private m_CopyLock As New Object
   Private m_ReadLock As New Object
   ' lista variabili in lettura
   Private Shared m_ReadingVars(19) As CommVar
   Public Shared ReadOnly Property ReadingVars As CommVar()
      Get
         Return m_ReadingVars
      End Get
   End Property

   ' lista variabili lette
   Public Shared m_ReadedVars(19) As String

   Protected Sub New()
   End Sub

   Friend Sub OnDispose()
      RemoveHandler m_Tpa.eventProxy.VariableCommandExecuted, m_Proxy_VariableCommandExecutedEventHandler
      'RemoveHandler m_Tpa.MachManaging.Timer.Tick, AddressOf Timer_Tick
   End Sub

   'Friend Sub Timer_Tick(sender As Object, e As EventArgs)
   '   ' leggo tutte le variabili
   '   RefreshAllVars()
   'End Sub

   Friend Shared Function CreateRWVariableManager(Tpa As TPAComm)
      Dim NewRWVariableManager As New RWVariableManager
      NewRWVariableManager.m_Tpa = Tpa
      AddHandler NewRWVariableManager.m_Tpa.eventProxy.VariableCommandExecuted, NewRWVariableManager.m_Proxy_VariableCommandExecutedEventHandler
      Return NewRWVariableManager
   End Function

   Public Sub RefreshAllVars()
      For Each Var In m_ReadingVars
         ' rileggo solo variabili continue
         If Not IsNothing(Var) AndAlso Var.nReadType = CommVar.ReadTypes.CONTINUOUS Then IntRefreshVar(Var.sAddress)
      Next
   End Sub

   Public Shared Function InitVar(Name As String, Address As String, Type As CommVar.ReadTypes) As Integer
      Dim Index As Integer = Array.IndexOf(m_ReadingVars, Nothing)
      m_ReadingVars(Index) = New CommVar(Name, Address, Type, CommVar.Types.NULL, CommVar.Paragraphs.NULL, "")
      Return Index
   End Function

   'Public Shared Function InitVar(nIndex As Integer) As CommVar
   '   Dim Index As Integer = Array.IndexOf(m_ReadingVars, Nothing)
   '   m_ReadingVars(Index) = GetPrivateProfileVariable(S_VARIABLES, nIndex, CurrentMachine.sMachIniFile)
   '   Return m_ReadingVars(Index)
   'End Function

   Public Shared Function InitVar(Variable As CommVar) As CommVar
      Dim Index As Integer = Array.IndexOf(m_ReadingVars, Nothing)
      m_ReadingVars(Index) = Variable
      Return m_ReadingVars(Index)
   End Function

   Private Shared Function GetPrivateProfileVariable(IpAppName As String, IpKeyName As String, IpFileName As String) As CommVar
      Dim sVariable As String = ""
      EgtUILib.GetPrivateProfileString(IpAppName, IpKeyName, "", sVariable, IpFileName)
      Dim sVariableValues() As String = sVariable.Split(","c)
      If Not sVariableValues.Count >= 3 Then Return Nothing
      For Index As Integer = 0 To sVariableValues.Count - 1
         sVariableValues(Index) = sVariableValues(Index).Trim()
      Next
      Dim Type As CommVar.ReadTypes
      Select Case sVariableValues(2).ToLower()
         Case "o"
            Type = CommVar.ReadTypes.ONETIME
         Case "c"
            Type = CommVar.ReadTypes.CONTINUOUS
         Case Else
            Type = CommVar.ReadTypes.NULL
      End Select
      Dim Paragraph As Paragraphs = Paragraphs.NULL
      Select Case IpAppName
         Case S_MAINVARIABLES
            Paragraph = Paragraphs.MAIN
         Case S_INPUTVARIABLES
            Paragraph = Paragraphs.INPUT
         Case S_OUTPUTVARIABLES
            Paragraph = Paragraphs.OUTPUT
      End Select
      Return New CommVar(sVariableValues(0), sVariableValues(1), Type, CommVar.Types.NULL, Paragraph, "")
   End Function

   Public Sub RefreshVar(Name As String)
      Dim Var As CommVar = GetReadVarFromName(Name)
      If Not IsNothing(Var) Then
         Var.ResetReading()
         IntRefreshVar(Var.sAddress)
      End If
   End Sub

   Public Sub WriteVarByName(Name As String, Value As String)
      IntWriteVar(GetReadVarFromName(Name).sAddress, Value)
   End Sub

   Public Sub WriteVarByAddress(Address As String, Value As String)
      IntWriteVar(Address, Value)
   End Sub

   Private Sub IntRefreshVar(Address As String)
      Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, Address, "")
   End Sub

   Private Sub IntWriteVar(Address As String, Value As String)
      Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.WriteVar, Address, Value)
   End Sub

   Public Sub ReadVar(Name As String, ByRef Value As String)
      Dim nIndex As Integer = GetIndexFromName(Name)
      If nIndex >= 0 Then
         Value = m_ReadedVars(nIndex)
      Else
         Value = ""
      End If
   End Sub
   Public Sub ReadVar(Name As String, ByRef Value As Integer)
      Dim nIndex As Integer = GetIndexFromName(Name)
      If nIndex >= 0 Then
         Integer.TryParse(m_ReadedVars(nIndex), Value)
      Else
         Value = -999999999
      End If
      Integer.TryParse(m_ReadedVars(GetIndexFromName(Name)), Value)
   End Sub
   Public Sub ReadVar(Name As String, ByRef Value As Double)
      Dim nIndex As Integer = GetIndexFromName(Name)
      If nIndex >= 0 Then
         Value = StringToDoubleAdv(m_ReadedVars(nIndex), 5)
      Else
         Value = -999999999
      End If
   End Sub

   Private Shared Function GetIndexFromName(Name As String) As Integer
      Return Array.FindIndex(m_ReadingVars, Function(x) If(Not IsNothing(x), x.sName = Name, False))
   End Function
   Friend Shared Function GetReadVarFromName(Name As String) As CommVar
      Dim nIndex As Integer = GetIndexFromName(Name)
      If nIndex >= 0 Then
         Return m_ReadingVars(nIndex)
      End If
      Return Nothing
   End Function
   Private Shared Function GetIndexFromAddress(Address As String) As Integer
      Return Array.FindIndex(m_ReadingVars, Function(x) If(Not IsNothing(x), x.sAddress = Address, False))
   End Function
   Friend Shared Function GetReadVarFromAddress(Address As String) As CommVar
      Dim nIndex As Integer = GetIndexFromAddress(Address)
      If nIndex >= 0 Then
         Return m_ReadingVars(nIndex)
      End If
      Return Nothing
   End Function
   Friend Shared Function GetReadVarNameFromAddress(Address As String) As String
      Dim Var As CommVar = m_ReadingVars.FirstOrDefault(Function(x) If(Not IsNothing(x), x.sAddress = Address, False))
      Return If(Not IsNothing(Var), Var.sName, "")
   End Function

   Private Sub UpdateContinuousVars()
      Dim bReaded As Boolean = True
      For Each Var In m_ReadingVars
         If Not IsNothing(Var) AndAlso Var.nReadType = CommVar.ReadTypes.CONTINUOUS AndAlso Not Var.bReaded Then
            bReaded = False
            Exit For
         End If
      Next
      ' se lette tutte
      If bReaded Then
         ' aggiorno variabili
         SyncLock m_CopyLock
            For VarIndex = 0 To m_ReadingVars.Count - 1
               If Not IsNothing(m_ReadingVars(VarIndex)) Then
                  m_ReadedVars(VarIndex) = m_ReadingVars(VarIndex).sValue
               End If
            Next
         End SyncLock
      End If
   End Sub

   Friend Sub UpdateVar(CommandExecutedCorrectly As Boolean, VarName As String, VarValue As String, VarType As Integer)
      If CommandExecutedCorrectly Then
         Dim Var As CommVar = GetReadVarFromAddress(VarName)
         If Not IsNothing(Var) Then
            'Dim bChangedVal As Boolean = ()
            Var.SetValue(VarValue)
            ' se variabile ripetitiva lancio update variabili ripetitive
            If Var.nReadType = CommVar.ReadTypes.CONTINUOUS Then
               EgtOutLog(CommandExecutedCorrectly & " . " & VarName & " . " & VarValue)
               EgtOutLog(Var.sName & " . " & Var.sAddress & " . " & Var.sValue & " . " & Var.bReaded)
               UpdateContinuousVars()
            Else
               m_ReadVarCallbackDlg(CommandExecutedCorrectly, VarName, VarValue, VarType)
            End If
         End If
      End If
   End Sub

   Private Sub RemoteObject_VariableCommandExecuted(ByVal executedCommand As Integer, ByVal commandExecutedCorrectly As Boolean, ByVal varName As String, ByVal varValue As String, ByVal varType As Integer)
      ' riporto valore variabile su array
      Select Case executedCommand
         Case VariableCommands.Error
         Case VariableCommands.NotExecuted
         Case VariableCommands.ReadVar
            UpdateVar(commandExecutedCorrectly, varName, varValue, varType)
         Case VariableCommands.WriteVar
            m_ResultCallbackDlg(CommandTypes.WRITE, CommandStates.OK, ResultTypes.RESULT, "")
         Case VariableCommands.ReadAxis
         Case VariableCommands.ReadAny
      End Select
   End Sub

End Class

Public Class CommVar

   Public Enum Paragraphs As Integer
      NULL = 0
      MAIN = 1
      INPUT = 2
      OUTPUT = 3
   End Enum

   Public Event NewValue As EventHandler(Of NewValueEventArgs)

   Public Enum ReadTypes As Integer
      NULL = 0
      ONETIME = 1
      CONTINUOUS = 2
   End Enum

   Public Enum Types As Integer
      NULL = 0
      PLC = 1
      CN = 2
   End Enum

   Private m_sName As String
   Public Property sName As String
      Get
         Return m_sName
      End Get
      Set(value As String)
         m_sName = value
      End Set
   End Property

   Private m_sAddress As String
   Public Property sAddress As String
      Get
         Return m_sAddress
      End Get
      Set(value As String)
         m_sAddress = value
      End Set
   End Property

   Private m_nReadType As ReadTypes
   Public ReadOnly Property nReadType As ReadTypes
      Get
         Return m_nReadType
      End Get
   End Property

   Private m_nType As Types
   Public ReadOnly Property nType As Types
      Get
         Return m_nType
      End Get
   End Property

   Private m_sValue As String
   Public ReadOnly Property sValue As String
      Get
         Return m_sValue
      End Get
   End Property
   Public Sub SetValue(Value As String)
      Dim bNewValue As Boolean = m_sValue <> Value
      m_sValue = Value
      m_bReaded = True
      If CurrentMachine.NCType = NCTypes.NUM_FLEXIUM AndAlso (sName = MACHINDEX OrElse sName = TOOLINDEX OrElse sName = TOOLINDEX2) Then
         Map.refLeftPanelVM.NotifyPropertyChanged(NameOf(Map.refLeftPanelVM.sE80000))
         Map.refLeftPanelVM.NotifyPropertyChanged(NameOf(Map.refLeftPanelVM.sE80001))
         Map.refLeftPanelVM.NotifyPropertyChanged(NameOf(Map.refLeftPanelVM.sE80002))
      End If
      If bNewValue Then RaiseEvent NewValue(Me, New NewValueEventArgs(Value))
   End Sub

   Private m_sDescription As String
   Public ReadOnly Property sDescription As String
      Get
         Return m_sDescription
      End Get
   End Property

   Private m_bReaded As Boolean
   Public ReadOnly Property bReaded As Boolean
      Get
         Return m_bReaded
      End Get
   End Property

   ' paragrafo dell'ini macchina da cui arriva la variabile per attivarle solo su apertura pagine
   Private m_Paragraph As Paragraphs
   Public ReadOnly Property Paragraph As Paragraphs
      Get
         Return m_Paragraph
      End Get
   End Property

   ' indice usato in liste lettura NUM
   Friend Index As Integer = -1

   Sub New(Name As String, Address As String, ReadType As ReadTypes, Type As Types, Paragraph As Paragraphs, sDescription As String)
      m_sName = Name
      m_sAddress = Address
      m_nReadType = ReadType
      m_nType = Type
      m_Paragraph = Paragraph
      m_sDescription = sDescription
   End Sub

   Friend Sub ResetReading()
      m_bReaded = False
   End Sub

End Class
