Imports System.Collections.ObjectModel
Imports System.ComponentModel.Composition
Imports System.Globalization
Imports System.Reflection
Imports System.Windows.Threading
Imports Newtonsoft.Json.Linq
Imports Effector.Plugin.StoneCut.Variable
Imports Effector.Plugin.Interface
Imports Effector.Plugin.Lib

Public Class MachinePageVM
   Inherits VMBase

   Private m_DoorOnMachineList As New ObservableCollection(Of Door)
   Public ReadOnly Property DoorOnMachineList As ObservableCollection(Of Door)
      Get
         Return m_DoorOnMachineList
      End Get
   End Property

   Private m_VarTimer As New DispatcherTimer

   Private m_VariableList As ObservableCollection(Of Variable)
   Public ReadOnly Property VariableList As ObservableCollection(Of Variable)
      Get
         Return m_VariableList
      End Get
   End Property

   Private m_sMachineImagePath As String
   Public ReadOnly Property sMachineImagePath As String
      Get
         Return m_sMachineImagePath
      End Get
   End Property

   Private m_nDDfCalcState As Integer = -1
   Public ReadOnly Property nDDfCalcState As Integer
      Get
         Return m_nDDfCalcState
      End Get
   End Property
   Private Sub SetDDfCalcState(nState As Integer)
      m_nDDfCalcState = nState
      NotifyPropertyChanged(NameOf(nDDfCalcState))
   End Sub

   Private m_dDdfCalcValue As Double = 0
   Public ReadOnly Property dDdfCalcValue As Double
      Get
         Return m_dDdfCalcValue
      End Get
   End Property

   Private m_nNewDoorState As Integer = -1
   Public ReadOnly Property nNewDoorState As Integer
      Get
         Return m_nNewDoorState
      End Get
   End Property
   Private Sub SetNewDoorState(nState As Integer)
      m_nNewDoorState = nState
      NotifyPropertyChanged(NameOf(nNewDoorState))
   End Sub

   'Private m_DoorOnMachineArray(8) As LuaDoor
   'Public ReadOnly Property DoorOnMachineArray As LuaDoor()
   '   Get
   '      Return m_DoorOnMachineArray
   '   End Get
   'End Property

   Private m_DoorOnMachineArray As New ObservableCollection(Of LuaDoor)
   Public ReadOnly Property DoorOnMachineArray As ObservableCollection(Of LuaDoor)
      Get
         Return m_DoorOnMachineArray
      End Get
   End Property

   Private m_LuaDoorList As New ObservableCollection(Of LuaDoor)
   Public ReadOnly Property LuaDoorList As ObservableCollection(Of LuaDoor)
      Get
         Return m_LuaDoorList
      End Get
   End Property

   Private m_bErrorReset As Boolean = False
   Public ReadOnly Property bErrorReset As Boolean
      Get
         Return m_bErrorReset
      End Get
   End Property

   Public ReadOnly Property VariableList_Visibility As Visibility
      Get
         Return If(GetPluginPrivateProfileInt(S_DEBUG, K_VARIABLELIST, 0) <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property VariableOnDraw_Visibility As Visibility
      Get
         Return If(GetPluginPrivateProfileInt(S_DEBUG, K_VARIABLEONDRAW, 0) <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property MachineCommands_Visibility As Visibility
      Get
         Return If(GetPluginPrivateProfileInt(S_DEBUG, K_MACHINECOMMANDS, 0) <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property DoorCircList_Visibility As Visibility
      Get
         Return If(GetPluginPrivateProfileInt(S_DEBUG, K_DOORCIRCLIST, 0) <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   ' Definizione comandi
   Private m_cmdWriteVariable As ICommand
   Private m_cmdMoveVariable As ICommand
   Private m_cmdManageMachining As ICommand

   Sub New()
      ' imposto riferimento in Map
      Map.SetRefMachinePageVM(Me)
      'm_VariableList = New ObservableCollection(Of Variable)({New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_00", "980", 1),
      '                                                        New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_01", "981", 1),
      '                                                        New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_02", "982", 1),
      '                                                        New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_03", "983", 1),
      '                                                        New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_04", "984", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@DOORN_S0", "1360", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@DOORN_S1", "1361", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@DOORN_S2", "1362", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@DOORN_S3", "1363", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@DOORN_S4", "1364", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@SENT_1", "1350", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@SENT_2", "1351", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@STATE", "1352", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@RESET_ON", "1365", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@MAST_OK", "1366", 1),
      '                                                        New Variable(Variable.VariableTypes.INTEGER, "@START_OK", "1367", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF00", "901.0", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF01", "901.1", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF02", "901.2", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF03", "901.3", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF04", "901.4", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF05", "901.5", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF06", "901.6", 1),
      '                                                        New Variable(Variable.VariableTypes.BOOLEAN, "@BF07", "901.7", 1)})
      m_VariableList = New ObservableCollection(Of Variable)({New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_01", "981", 1),
                                                              New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_02", "982", 1),
                                                              New Variable(Variable.VariableTypes.DOUBLE, "@WP_PR_03", "983", 1),
                                                              New Variable(Variable.VariableTypes.INTEGER, "@SENT_1", "1350", 1),
                                                              New Variable(Variable.VariableTypes.INTEGER, "@SENT_2", "1351", 1),
                                                              New Variable(Variable.VariableTypes.INTEGER, "@STATE", "1352", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF01", "901.1", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF02", "901.2", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF03", "901.3", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF04", "901.4", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF05", "901.5", 1),
                                                              New Variable(Variable.VariableTypes.BOOLEAN, "@BF06", "901.6", 1),
                                                              New Variable(Variable.VariableTypes.INTEGER, "@P1000_END", "1353", 1),
                                                              New Variable(Variable.VariableTypes.INTEGER, "@P2000_END", "1354", 1)})
      AddHandler m_VarTimer.Tick, AddressOf VarTimer_Tick
      m_VarTimer.Interval = New TimeSpan(100)
      m_VarTimer.Start()
      Dim sResourcesDirPath As String = ""
      GetPluginPrivateProfileString(S_GENERAL, K_RESOURCESDIR, "", sResourcesDirPath)
      m_sMachineImagePath = sResourcesDirPath & "\Machine.png"
      ' creo posti in lista descrizioni
      For nIndex As Integer = 0 To 8
         m_DoorOnMachineArray.Add(Nothing)
      Next
   End Sub

   Friend Sub VarTimer_Tick()
      '' leggo variabile ErrorReset da lua
      'LuaGetGlobVar("ERROR_RESET", m_bErrorReset)
      'NotifyPropertyChanged(NameOf(bErrorReset))
      '' leggo variabili da macchina
      'For nVarIndex As Integer = 0 To m_VariableList.Count - 1
      '   Dim Var As Variable = m_VariableList(nVarIndex)
      '   Select Case Var.Type
      '      Case Variable.VariableTypes.INTEGER
      '         Dim nIndex As Integer = 0
      '         Integer.TryParse(Var.sIndex, nIndex)
      '         Dim nValue As Integer = 0
      '         If Map.refSupervisorFunction.ComReadShortVar(nIndex, nValue, Var.nMachine) Then
      '            Var.SetValue(nValue)
      '         Else
      '            Map.refSupervisorFunction.PlgOutLog("Error! Reading Variable " & Var.sIndex & " on machine " & Var.nMachine & "failed!")
      '         End If
      '      Case Variable.VariableTypes.DOUBLE
      '         Dim nIndex As Integer = 0
      '         Integer.TryParse(Var.sIndex, nIndex)
      '         Dim dValue As Double = 0
      '         If Map.refSupervisorFunction.ComReadDoubleVar(nIndex, dValue, Var.nMachine) Then
      '            Var.SetValue(dValue)
      '         Else
      '            Map.refSupervisorFunction.PlgOutLog("Error! Reading Variable " & Var.sIndex & " on machine " & Var.nMachine & "failed!")
      '         End If
      '      Case Variable.VariableTypes.BOOLEAN
      '         Dim nIndex As Integer = 0
      '         Dim nBit As Integer = 0
      '         Dim sIndexSplit() As String = Var.sIndex.Split("."c)
      '         Integer.TryParse(sIndexSplit(0), nIndex)
      '         Integer.TryParse(sIndexSplit(1), nBit)
      '         Dim bValue As Boolean = 0
      '         If Map.refSupervisorFunction.ComReadBitVar(nIndex, nBit, bValue, Var.nMachine) Then
      '            Var.SetValue(bValue)
      '         Else
      '            Map.refSupervisorFunction.PlgOutLog("Error! Reading Variable " & Var.sIndex & " on machine " & Var.nMachine & "failed!")
      '         End If
      '   End Select
      'Next
      '' se in simulazione
      'If Map.refSupervisorFunction.PlgGetPrivateProfileInt(S_NC, K_NC_SIMULATE, 0) Then
      '   ' aggiorno stato porta in macchina da 1 a 2 se in stazione di lavorazione
      '   For nMachineIndex = 1 To 2
      '      Dim nMachineId As Integer = nMachineIndex
      '      Dim Machine1Var As Variable = m_VariableList.FirstOrDefault(Function(x) x.sName = "@WP_PR_02" AndAlso x.nMachine = nMachineId)
      '      If Not IsNothing(Machine1Var) AndAlso Machine1Var.dValue = 1 Then
      '         Dim nIndex As Integer = -1
      '         Integer.TryParse(Machine1Var.sIndex, nIndex)
      '         Map.refSupervisorFunction.ComWriteDoubleVar(nIndex, 2, Machine1Var.nMachine)
      '      End If
      '   Next
      'End If
      '' leggo stato calcolo da lua
      'Dim nState As Integer = -1
      'If LuaGetGlobVar("MACHINE1.DDfCalcState", nState) Then
      '   SetDDfCalcState(nState)
      '   If nState = 1 Then
      '      m_dDdfCalcValue += 100 / 250
      '      m_dDdfCalcValue = Math.Min(100, m_dDdfCalcValue)
      '   ElseIf m_dDdfCalcValue <> 0 Then
      '      m_dDdfCalcValue = 0
      '   End If
      '   NotifyPropertyChanged(NameOf(dDdfCalcValue))
      '   NotifyPropertyChanged(NameOf(nDDfCalcState))
      'End If
      'If LuaGetGlobVar("MACHINE1.NewDoorState", nState) Then
      '   SetNewDoorState(nState)
      'End If
      'm_LuaDoorList.Clear()
      'For nDoorIndex = 1 To 10
      '   Dim nId As Integer = -1
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nId", nId)
      '   Dim nCircIndex As Integer = -1
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nCircIndex", nCircIndex)
      '   Dim nDoorState As Integer = -1
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nState", nDoorState)
      '   Dim sDoorCode As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sDoorCode", sDoorCode)
      '   Dim sDoorDescription As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sDoorDescription", sDoorDescription)
      '   Dim sDDFName As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sDDFName", sDDFName)
      '   Dim sCSVName As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sCSVName", sCSVName)
      '   Dim sM1CNPath As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sM1CNPath", sM1CNPath)
      '   Dim sM2CNPath As String = ""
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".sM2CNPath", sM2CNPath)
      '   Dim lLoadTime As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nLoadTime", lLoadTime)
      '   Dim lMachining1Start As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nMachining1Start", lMachining1Start)
      '   Dim lMachining1End As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nMachining1End", lMachining1End)
      '   Dim lMachining2Start As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nMachining2Start", lMachining2Start)
      '   Dim lMachining2End As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nMachining2End", lMachining2End)
      '   Dim lUnloadTime As Long = 0
      '   LuaGetGlobVar("ListaCircPorte." & nDoorIndex & ".nUnloadTime", lUnloadTime)
      '   m_LuaDoorList.Add(New LuaDoor(nId, nCircIndex, nDoorState, sDoorCode, sDoorDescription, sDDFName, sCSVName, sM1CNPath, sM2CNPath, lLoadTime, lMachining1Start, lMachining1End, lMachining2Start, lMachining2End, lUnloadTime))
      '   If nId > 0 Then
      '      ' aggiorno dati in lista porte
      '      Dim Door As Door = Map.refDoorListPageVM.DoorList.FirstOrDefault(Function(x) x.nId = nId)
      '      If Not IsNothing(Door) AndAlso nDoorState <> Door.nProdState Then
      '         Door.SetProdState(nDoorState)
      '         If lLoadTime > 0 Then Door.SetLoadTime(lLoadTime)
      '         If lMachining1Start > 0 Then Door.SetMachiningStart(lMachining1Start)
      '         If lMachining1End > 0 Then Door.SetMachining1End(lMachining1End)
      '         If lMachining2Start > 0 Then Door.SetMachining2Start(lMachining2Start)
      '         If lMachining2End > 0 Then Door.SetMachining2End(lMachining2End)
      '         If lUnloadTime > 0 Then Door.SetUnloadTime(lUnloadTime)
      '      End If
      '   End If
      'Next
      'For nVarIndex As Integer = 0 To m_VariableList.Count - 1
      '   Dim Var As Variable = m_VariableList(nVarIndex)
      '   If nVarIndex >= 5 AndAlso nVarIndex <= 9 Then
      '      Dim nId As Integer = -1
      '      If Var.nValue > 0 Then
      '         m_DoorOnMachineArray(nVarIndex - 5) = m_LuaDoorList(Var.nValue - 1)
      '      Else
      '         m_DoorOnMachineArray(nVarIndex - 5) = Nothing
      '      End If
      '   End If
      '   If nVarIndex >= 30 AndAlso nVarIndex <= 33 Then
      '      Dim nId As Integer = -1
      '      If Var.nValue > 0 Then
      '         m_DoorOnMachineArray(nVarIndex - 25) = m_LuaDoorList(Var.nValue - 1)
      '      Else
      '         m_DoorOnMachineArray(nVarIndex - 25) = Nothing
      '      End If
      '   End If
      'Next
      'NotifyPropertyChanged(NameOf(DoorOnMachineArray))
   End Sub

#Region "COMMANDS"

#Region "WriteVariable"

   Public ReadOnly Property WriteVariable_Command As ICommand
      Get
         If m_cmdWriteVariable Is Nothing Then
            m_cmdWriteVariable = New Command(AddressOf WriteVariable)
         End If
         Return m_cmdWriteVariable
      End Get
   End Property

   Public Sub WriteVariable(sVariable As String)
      Dim sVariables As String() = sVariable.Split(";"c)
      For nVariableIndex As Integer = 0 To sVariables.Count - 1
         Dim sVariableArgs As String() = sVariables(nVariableIndex).Split(","c)
         Dim nMachineIndex As Integer = -1
         Integer.TryParse(sVariableArgs(0), nMachineIndex)
         Dim nVariableType As Integer = -1
         Integer.TryParse(sVariableArgs(1), nVariableType)
         Select Case nVariableType
            Case 1
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVariableArgs(2), nVarAddress)
               Dim nVarValue As Integer = -1
               Integer.TryParse(sVariableArgs(3), nVarValue)
               Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, nVarValue, nMachineIndex)
            Case 2
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVariableArgs(2), nVarAddress)
               Dim dVarValue As Double = -1
               StringToDouble(sVariableArgs(3), dVarValue)
               Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, dVarValue, nMachineIndex)
            Case 3
               Dim sVarAddress As String() = sVariableArgs(2).Split("."c)
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVarAddress(0), nVarAddress)
               Dim nBit As Integer = -1
               Integer.TryParse(sVarAddress(1), nBit)
               Dim nVarValue As Integer = -1
               Integer.TryParse(sVariableArgs(3), nVarValue)
               Map.refSupervisorFunction.ComWriteBitVar(nVarAddress, nBit, nVarValue <> 0, nMachineIndex)
         End Select
      Next
   End Sub

#End Region ' WriteVariable

#Region "MoveVariable"

   Public ReadOnly Property MoveVariable_Command As ICommand
      Get
         If m_cmdMoveVariable Is Nothing Then
            m_cmdMoveVariable = New Command(AddressOf MoveVariable)
         End If
         Return m_cmdMoveVariable
      End Get
   End Property

   Public Sub MoveVariable(sVariableToMove As String)
      Dim sVariableToMoveArgs As String() = sVariableToMove.Split({"->"}, StringSplitOptions.None)
      Dim sFromAndPresenceVariables As String() = sVariableToMoveArgs(0).Split("/"c)
      ' verifico presenza da variabile di partenza
      Dim sVerifyFromVariables As String() = sFromAndPresenceVariables(0).Split(";"c)
      Dim sVerifyFromVariableArgs As String() = sVerifyFromVariables(0).Split(","c)
      Dim nVerifyFromMachineIndex As Integer = -1
      Integer.TryParse(sVerifyFromVariableArgs(0), nVerifyFromMachineIndex)
      Dim nVerifyFromVarAddress As Integer = -1
      Integer.TryParse(sVerifyFromVariableArgs(2), nVerifyFromVarAddress)
      Dim dVerifyFromVarValue As Double = -1
      Map.refSupervisorFunction.ComReadShortVar(nVerifyFromVarAddress, dVerifyFromVarValue, nVerifyFromMachineIndex)
      If dVerifyFromVarValue < 1 Then Return
      ' verifco se variabile di carico, che la macchina abbia iniziato a lavorare
      If nVerifyFromVarAddress = 1360 Then
         Dim MachineStateVar As Variable = VariableList.FirstOrDefault(Function(x) x.nMachine = nVerifyFromMachineIndex AndAlso x.sName = "@STATE")
         Dim Sent1Var As Variable = VariableList.FirstOrDefault(Function(x) x.nMachine = nVerifyFromMachineIndex AndAlso x.sName = "@SENT_1")
         Dim Sent2Var As Variable = VariableList.FirstOrDefault(Function(x) x.nMachine = nVerifyFromMachineIndex AndAlso x.sName = "@SENT_2")
         If (MachineStateVar.nValue <> 2 AndAlso MachineStateVar.nValue <> 4) OrElse
            Sent1Var.nValue <> 0 OrElse Sent2Var.nValue <> 0 Then Return
      End If
      ' verifco se variabile tavolo di lavoro, che la macchina abbia finito di lavorare
      If nVerifyFromVarAddress = 1362 Then
         Dim MachineStateVar As Variable = VariableList.FirstOrDefault(Function(x) x.nMachine = nVerifyFromMachineIndex AndAlso x.sName = "@STATE")
         If MachineStateVar.nValue <> 3 AndAlso MachineStateVar.nValue <> 5 Then Return
      End If
      ' verifico che stazione di destinazione non sia gia' occupata
      Dim sToAndPresenceVariables As String() = sVariableToMoveArgs(1).Split("/"c)
      Dim sVerifyToVariables As String() = sToAndPresenceVariables(1).Split(";"c)
      Dim sVerifyToVariableArgs As String() = sVerifyToVariables(0).Split(","c)
      Dim nVerifyToMachineIndex As Integer = -1
      Integer.TryParse(sVerifyToVariableArgs(0), nVerifyToMachineIndex)
      Dim nVerifyToVarAddress As Integer = -1
      Integer.TryParse(sVerifyToVariableArgs(2), nVerifyToVarAddress)
      Dim dVerifyToVarValue As Double = -1
      Map.refSupervisorFunction.ComReadDoubleVar(nVerifyToVarAddress, dVerifyToVarValue, nVerifyToMachineIndex)
      If dVerifyToVarValue > 0 Then Return
      ' leggo variabili di partenza
      Dim sFromVariables As String() = sFromAndPresenceVariables(0).Split(";"c)
      Dim sFromVariableArgs As String() = sFromVariables(0).Split(","c)
      Dim nFromMachineIndex As Integer = -1
      Integer.TryParse(sFromVariableArgs(0), nFromMachineIndex)
      Dim nFromVariableType As Integer = -1
      Integer.TryParse(sFromVariableArgs(1), nFromVariableType)
      Dim nVarValue As Integer = -1
      Dim dVarValue As Double = -1
      Dim bVarValue As Boolean = False
      Select Case nFromVariableType
         Case 1
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sFromVariableArgs(2), nVarAddress)
            Map.refSupervisorFunction.ComReadShortVar(nVarAddress, nVarValue, nFromMachineIndex)
         Case 2
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sFromVariableArgs(2), nVarAddress)
            Map.refSupervisorFunction.ComReadDoubleVar(nVarAddress, dVarValue, nFromMachineIndex)
         Case 3
            Dim sVarAddress As String() = sFromVariableArgs(2).Split("."c)
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sVarAddress(0), nVarAddress)
            Dim nBit As Integer = -1
            Integer.TryParse(sVarAddress(1), nBit)
            Map.refSupervisorFunction.ComReadBitVar(nVarAddress, nBit, bVarValue, nFromMachineIndex)
      End Select
      ' scrivo valore in variabili di arrivo
      Dim sToVariables As String() = sToAndPresenceVariables(0).Split(";"c)
      For nToVariableIndex As Integer = 0 To sToVariables.Count - 1
         Dim sToVariableArgs As String() = sToVariables(nToVariableIndex).Split(","c)
         Dim nToMachineIndex As Integer = -1
         Integer.TryParse(sToVariableArgs(0), nToMachineIndex)
         Dim nToVariableType As Integer = -1
         Integer.TryParse(sToVariableArgs(1), nToVariableType)
         Select Case nToVariableType
            Case 1
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sToVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, nVarValue, nToMachineIndex)
            Case 2
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sToVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, dVarValue, nToMachineIndex)
            Case 3
               Dim sVarAddress As String() = sToVariableArgs(2).Split("."c)
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVarAddress(0), nVarAddress)
               Dim nBit As Integer = -1
               Integer.TryParse(sVarAddress(1), nBit)
               Map.refSupervisorFunction.ComWriteBitVar(nVarAddress, nBit, nVarValue <> 0, nToMachineIndex)
         End Select
      Next
      ' cancello valore da variabili di partenza
      Select Case nFromVariableType
         Case 1
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sFromVariableArgs(2), nVarAddress)
            Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, 0, nFromMachineIndex)
         Case 2
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sFromVariableArgs(2), nVarAddress)
            Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, 0, nFromMachineIndex)
         Case 3
            Dim sVarAddress As String() = sFromVariableArgs(2).Split("."c)
            Dim nVarAddress As Integer = -1
            Integer.TryParse(sVarAddress(0), nVarAddress)
            Dim nBit As Integer = -1
            Integer.TryParse(sVarAddress(1), nBit)
            Map.refSupervisorFunction.ComWriteBitVar(nVarAddress, nBit, False, nFromMachineIndex)
      End Select
      For nFromVariableIndex As Integer = 1 To sFromVariables.Count - 1
         sFromVariableArgs = sFromVariables(nFromVariableIndex).Split(","c)
         Integer.TryParse(sFromVariableArgs(0), nFromMachineIndex)
         Integer.TryParse(sFromVariableArgs(1), nFromVariableType)
         Select Case nFromVariableType
            Case 1
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sFromVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, 0, nFromMachineIndex)
            Case 2
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sFromVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, 0, nFromMachineIndex)
            Case 3
               Dim sVarAddress As String() = sFromVariableArgs(2).Split("."c)
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVarAddress(0), nVarAddress)
               Dim nBit As Integer = -1
               Integer.TryParse(sVarAddress(1), nBit)
               Map.refSupervisorFunction.ComWriteBitVar(nVarAddress, nBit, False, nFromMachineIndex)
         End Select
      Next
      ' resetto presenza da variabili di partenza
      Dim sFromPresenceVariables As String() = sFromAndPresenceVariables(1).Split(";"c)
      For nFromPresenceVariableIndex As Integer = 0 To sFromPresenceVariables.Count - 1
         Dim sFromPresenceVariableArgs As String() = sFromPresenceVariables(nFromPresenceVariableIndex).Split(","c)
         Dim nFromPresenceMachineIndex As Integer = -1
         Integer.TryParse(sFromPresenceVariableArgs(0), nFromPresenceMachineIndex)
         Dim nFromPresenceVariableType As Integer = -1
         Integer.TryParse(sFromPresenceVariableArgs(1), nFromPresenceVariableType)
         Select Case nFromPresenceVariableType
            Case 1
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sFromPresenceVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComReadShortVar(nVarAddress, nVarValue, nFromPresenceMachineIndex)
               Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, 0, nFromPresenceMachineIndex)
            Case 2
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sFromPresenceVariableArgs(2), nVarAddress)
               Map.refSupervisorFunction.ComReadDoubleVar(nVarAddress, dVarValue, nFromPresenceMachineIndex)
               Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, 0, nFromPresenceMachineIndex)
            Case 3
               Dim sVarAddress As String() = sFromPresenceVariableArgs(2).Split("."c)
               Dim nVarAddress As Integer = -1
               Integer.TryParse(sVarAddress(0), nVarAddress)
               Dim nBit As Integer = -1
               Integer.TryParse(sVarAddress(1), nBit)
               Map.refSupervisorFunction.ComReadBitVar(nVarAddress, nBit, bVarValue, nFromPresenceMachineIndex)
               Map.refSupervisorFunction.ComWriteBitVar(nVarAddress, nBit, False, nFromPresenceMachineIndex)
         End Select
      Next
      ' imposto presenza in variabili di arrivo
      Dim sToPresenceVariables As String() = sToAndPresenceVariables(1).Split(";"c)
      For nToPresenceVariableIndex As Integer = 0 To sToPresenceVariables.Count - 1
         Dim sToPresenceVariableArgs As String() = sToPresenceVariables(nToPresenceVariableIndex).Split(","c)
         Dim nToPresenceMachineIndex As Integer = -1
         Integer.TryParse(sToPresenceVariableArgs(0), nToPresenceMachineIndex)
         Dim nVarAddress As Integer = -1
         Integer.TryParse(sToPresenceVariableArgs(2), nVarAddress)
         Map.refSupervisorFunction.ComWriteDoubleVar(nVarAddress, dVarValue, nToPresenceMachineIndex)
      Next
   End Sub

#End Region ' MoveVariable

#Region "ManageMachining"

   Public ReadOnly Property ManageMachining_Command As ICommand
      Get
         If m_cmdManageMachining Is Nothing Then
            m_cmdManageMachining = New Command(AddressOf ManageMachining)
         End If
         Return m_cmdManageMachining
      End Get
   End Property

   Public Sub ManageMachining(sArg As String)
      Dim sArgs As String() = sArg.Split(","c)
      Dim nMachineIndex As Integer = -1
      Dim nStartStop As Integer = -1
      Integer.TryParse(sArgs(0), nMachineIndex)
      Integer.TryParse(sArgs(1), nStartStop)
      Dim nVarAddress As Integer
      If nMachineIndex = 1 Then
         nVarAddress = 1352
      ElseIf nMachineIndex = 2 Then
         nVarAddress = 1352
      Else Return
      End If
      Dim nState As Integer
      Dim StateVariable As Variable = m_VariableList.FirstOrDefault(Function(x) x.nMachine = nMachineIndex AndAlso x.sName = "@STATE")
      Dim Sent1 As Variable = m_VariableList.FirstOrDefault(Function(x) x.nMachine = nMachineIndex AndAlso x.sName = "@SENT_1")
      Dim Sent2 As Variable = m_VariableList.FirstOrDefault(Function(x) x.nMachine = nMachineIndex AndAlso x.sName = "@SENT_2")
      Dim StartDoorPresence As Variable = m_VariableList.FirstOrDefault(Function(x) x.nMachine = nMachineIndex AndAlso x.sName = "@WP_PR_03")
      Dim EndDoorPresence As Variable = m_VariableList.FirstOrDefault(Function(x) x.nMachine = nMachineIndex AndAlso x.sName = "@WP_PR_01")
      If StateVariable.nValue < 1 OrElse StateVariable.nValue > 5 Then Return
      Select Case StateVariable.nValue
         Case 0
            Return
         Case 1
            'If nStartStop = 1 AndAlso StartDoorPresence.dValue = 1 AndAlso Sent1.nValue = 1 Then
            If nStartStop = 1 AndAlso Sent1.nValue = 1 Then
               nState = 2
               Map.refSupervisorFunction.ComWriteShortVar(Sent1.sIndex, 0, nMachineIndex)
            Else Return
            End If
         Case 2
            'If nStartStop = 2 AndAlso EndDoorPresence.dValue = 2 Then
            If nStartStop = 2 Then
               nState = 3
            Else Return
            End If
         Case 3
            'If nStartStop = 1 AndAlso StartDoorPresence.dValue = 1 AndAlso Sent2.nValue = 1 Then
            If nStartStop = 1 AndAlso Sent2.nValue = 1 Then
               nState = 4
               Map.refSupervisorFunction.ComWriteShortVar(Sent2.sIndex, 0, nMachineIndex)
            Else Return
            End If
         Case 4
            'If nStartStop = 2 AndAlso EndDoorPresence.dValue = 2 Then
            If nStartStop = 2 Then
               nState = 5
            Else Return
            End If
         Case 5
            'If nStartStop = 1 AndAlso StartDoorPresence.dValue = 1 AndAlso Sent1.nValue = 1 Then
            If nStartStop = 1 AndAlso Sent1.nValue = 1 Then
               nState = 2
               Map.refSupervisorFunction.ComWriteShortVar(Sent1.sIndex, 0, nMachineIndex)
            Else Return
            End If
      End Select
      Map.refSupervisorFunction.ComWriteShortVar(nVarAddress, nState, nMachineIndex)
   End Sub

#End Region ' ManageMachining

#End Region    ' COMMANDS

End Class

Public Class Variable
   Inherits VMBase

   Public Enum VariableTypes As Integer
      [INTEGER] = 1
      [DOUBLE] = 2
      [BOOLEAN] = 3
   End Enum

   Private m_Type As VariableTypes
   Public ReadOnly Property Type As Integer
      Get
         Return m_Type
      End Get
   End Property

   Private m_sName As String
   Public ReadOnly Property sName As String
      Get
         Return m_sName
      End Get
   End Property

   Private m_sIndex As String
   Public ReadOnly Property sIndex As String
      Get
         Return m_sIndex
      End Get
   End Property

   Private m_nMachine As Integer
   Public ReadOnly Property nMachine As Integer
      Get
         Return m_nMachine
      End Get
   End Property

   Private m_nValue As Integer
   Friend ReadOnly Property nValue As Integer
      Get
         Return m_nValue
      End Get
   End Property
   Private m_dValue As Double
   Friend ReadOnly Property dValue As Integer
      Get
         Return m_dValue
      End Get
   End Property
   Private m_bValue As Boolean
   Public Property sValue As String
      Get
         Select Case Type
            Case VariableTypes.INTEGER
               Return m_nValue.ToString()
            Case VariableTypes.DOUBLE
               Return DoubleToString(m_dValue, 2)
            Case VariableTypes.BOOLEAN
               Return If(m_bValue, 1, 0)
         End Select
      End Get
      Set(value As String)
         Select Case Type
            Case VariableTypes.INTEGER
               If Not Integer.TryParse(value, m_nValue) Then
                  NotifyPropertyChanged(NameOf(sValue))
               End If
            Case VariableTypes.DOUBLE
               If Not StringToDouble(value, m_dValue) Then
                  NotifyPropertyChanged(NameOf(sValue))
               End If
            Case VariableTypes.BOOLEAN
               Dim nBoolean As Integer = 0
               If Integer.TryParse(value, nBoolean) Then
                  m_bValue = If(nBoolean > 0, 1, 0)
               Else
                  NotifyPropertyChanged(NameOf(sValue))
               End If
         End Select
         m_nValue = value
      End Set
   End Property
   Friend Sub SetValue(value As Integer)
      m_nValue = value
      NotifyPropertyChanged(NameOf(sValue))
   End Sub
   Friend Sub SetValue(value As Double)
      m_dValue = value
      NotifyPropertyChanged(NameOf(sValue))
   End Sub
   Friend Sub SetValue(value As Boolean)
      m_bValue = value
      NotifyPropertyChanged(NameOf(sValue))
   End Sub

   Sub New(Type As VariableTypes, sName As String, sIndex As String, nMachine As Integer)
      m_Type = Type
      m_sName = sName
      m_sIndex = sIndex
      m_nMachine = nMachine
   End Sub

End Class

Public Class LuaDoor
   Inherits VMBase

   Private m_nId As Integer = -1
   Public ReadOnly Property nId As Integer
      Get
         Return m_nId
      End Get
   End Property

   Private m_nCircIndex As Integer = -1
   Public ReadOnly Property nCircIndex As Integer
      Get
         Return m_nCircIndex
      End Get
   End Property

   Private m_nState As Integer = 0
   Public ReadOnly Property nState As Integer
      Get
         Return m_nState
      End Get
   End Property

   Private m_sDoorCode As String = ""
   Public ReadOnly Property sDoorCode As String
      Get
         Return m_sDoorCode
      End Get
   End Property

   Private m_sDoorDescription As String = ""
   Public ReadOnly Property sDoorDescription As String
      Get
         Return m_sDoorDescription
      End Get
   End Property

   Private m_sDDFName As String = ""
   Public ReadOnly Property sDDFName As String
      Get
         Return m_sDDFName
      End Get
   End Property

   Private m_sCSVName As String = ""
   Public ReadOnly Property sCSVName As String
      Get
         Return m_sCSVName
      End Get
   End Property

   Private m_sM1CNPath As String = ""
   Public ReadOnly Property sM1CNPath As String
      Get
         Return m_sM1CNPath
      End Get
   End Property

   Private m_sM2CNPath As String = ""
   Public ReadOnly Property sM2CNPath As String
      Get
         Return m_sM2CNPath
      End Get
   End Property

   Private m_dtLoadTime As DateTime
   Public ReadOnly Property sLoadTime As String
      Get
         Return ConvertDateTimeToString(m_dtLoadTime)
      End Get
   End Property

   Private m_dtMachining1Start As DateTime
   Public ReadOnly Property sMachining1Start As String
      Get
         Return ConvertDateTimeToString(m_dtMachining1Start)
      End Get
   End Property

   Private m_dtMachining1End As DateTime
   Public ReadOnly Property sMachining1End As String
      Get
         Return ConvertDateTimeToString(m_dtMachining1End)
      End Get
   End Property

   Private m_dtMachining2Start As DateTime
   Public ReadOnly Property sMachining2Start As String
      Get
         Return ConvertDateTimeToString(m_dtMachining2Start)
      End Get
   End Property

   Private m_dtMachining2End As DateTime
   Public ReadOnly Property sMachining2End As String
      Get
         Return ConvertDateTimeToString(m_dtMachining2End)
      End Get
   End Property

   Private m_dtUnloadTime As DateTime
   Public ReadOnly Property sUnloadTime As String
      Get
         Return ConvertDateTimeToString(m_dtUnloadTime)
      End Get
   End Property

   Sub New(nId As Integer, nCircIndex As Integer, nState As Integer, sDoorCode As String, sDoorDescription As String, sDDFName As String, sCSVName As String,
           sM1CNPath As String, sM2CNPath As String, lLoadTime As Long, lMachining1Start As Long, lMachining1End As Long, lMachining2Start As Long, lMachining2End As Long, lUnloadTime As Long)
      m_nId = nId
      m_nCircIndex = nCircIndex
      m_nState = nState
      m_sDoorCode = sDoorCode
      m_sDoorDescription = sDoorDescription
      m_sDDFName = sDDFName
      m_sCSVName = sCSVName
      m_sM1CNPath = sM1CNPath
      m_sM2CNPath = sM2CNPath
      m_dtLoadTime = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lLoadTime).ToLocalTime()
      m_dtMachining1Start = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lMachining1Start).ToLocalTime()
      m_dtMachining1End = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lMachining1End).ToLocalTime()
      m_dtMachining2Start = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lMachining2Start).ToLocalTime()
      m_dtMachining2End = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lMachining2End).ToLocalTime()
      m_dtUnloadTime = New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(lUnloadTime).ToLocalTime()
   End Sub

End Class

Public Class StringToVisibilityConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is String OrElse String.IsNullOrWhiteSpace(value) Then Return Visibility.Collapsed
      Dim sValue As String = value
      Dim sLowerValue As String = sValue.ToLower()
      If sLowerValue = "true" Then Return Visibility.Visible
      If sLowerValue = "false" Then Return Visibility.Collapsed
      Dim nValue As Integer
      If Not Integer.TryParse(sValue, nValue) Then Return Visibility.Collapsed
      Return If(nValue <> 0, Visibility.Visible, Visibility.Collapsed)
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class StringToMachineStateConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is String OrElse String.IsNullOrWhiteSpace(value) Then Return Visibility.Collapsed
      Dim sValue As String = value
      Dim nValue As Integer
      If Not Integer.TryParse(sValue, nValue) Then Return ""
      Select Case nValue
         Case -1
            Return "Not Initialized"
         Case 0
            Return "Reset"
         Case 1
            Return "Initialized"
         Case 2
            Return "Start machining 1000"
         Case 3
            Return "End machining 1000"
         Case 4
            Return "Start machining 2000"
         Case 5
            Return "End machining 2000"
         Case Else
            Return "Unknown State"
      End Select
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class StringToDDFCalcStateConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is Integer Then Return value
      Dim sValue As String = value
      Dim nValue As Integer = value
      Select Case nValue
         Case 0
            Return "Null"
         Case 1
            Return "Running"
         Case 2
            Return "Result"
         Case Else
            Return value
      End Select
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class StringToNewDoorStateConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is Integer Then Return value
      Dim nValue As Integer = value
      Select Case nValue
         Case 0
            Return "Null"
         Case 1
            Return "Present"
         Case 2
            Return "Assigned"
         Case Else
            Return value
      End Select
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class StringToBooleanConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is String OrElse String.IsNullOrWhiteSpace(value) Then Return Nothing
      Dim sValue As String = value
      Dim nValue As Integer
      If Not Integer.TryParse(sValue, nValue) Then Return Nothing
      If nValue = -1 Then Return Nothing
      Return nValue <> 0
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class StringToBackgroundConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If Not TypeOf value Is String OrElse String.IsNullOrWhiteSpace(value) Then Return False
      Dim sValue As String = value
      Dim nValue As Integer
      If Not Integer.TryParse(sValue, nValue) Then Return Brushes.LightGray
      Return If(nValue <> 0, Brushes.Green, Brushes.LightGray)
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class DoorToVisibilityConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If IsNothing(value) OrElse (Not TypeOf value Is LuaDoor AndAlso Not TypeOf value Is RestartDoor) Then Return Visibility.Hidden
      Return Visibility.Visible
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class

Public Class BooleanToVisibilityConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
      If IsNothing(value) OrElse (Not TypeOf value Is Boolean) Then Return Visibility.Hidden
      Return If(value, Visibility.Visible, Visibility.Hidden)
   End Function

   Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class
