Imports System.Collections.ObjectModel
Imports System.Threading
Imports System.Windows.Threading
Imports EgtBEAMWALL.Core.ConstMachComm
Imports EgtBEAMWALL.Core
Imports EgtWPFLib5
Imports EgtUILib

Public Class MachCommandMessagePanelVM
   Inherits VMBase

   Public Enum NUM_ErrorTypes As Integer
      CNC_Boot_Message = 0
      CNC_System_Warning = 1
      CNC_Message = 2
      Drive_Error = 3
      Communication_Message = 5
      PLC_Message_Reaction_Class_1 = 6
      PLC_Message_Reaction_Class_2 = 7
      PLC_Message_Reaction_Class_3 = 8
      PLC_Message_Reaction_Class_4 = 9
      PLC_Message_Reaction_Class_5 = 10
      PLC_Message_Reaction_Class_6 = 11
      PLC_Message_Reaction_Class_7 = 12
      PLC_Message_Reaction_Class_8 = 13
      HMI_Message = 20
      User_Message = 21
      RTS_Message = 22
      Drive_Warning = 23
      SysInfo_Message = 24
      CNC_Warning = 25
      OperatorMsg = 30
   End Enum

   Private m_AlarmTimer As New DispatcherTimer

   Private m_MachManagingThread As Thread

   Public ReadOnly Property MachManagingThread As Thread
      Get
         Return m_MachManagingThread
      End Get
   End Property

   Private m_MainVariablesList As New List(Of Variable)
   Public ReadOnly Property MainVariablesList As List(Of Variable)
      Get
         Return m_MainVariablesList
      End Get
   End Property

   Private m_bPrinterLink As Boolean = False
   Public ReadOnly Property bPrinterLink As Boolean
      Get
         Return m_bPrinterLink
      End Get
   End Property

   Private _Connected As Boolean = False
   Public ReadOnly Property Connected As Boolean
      Get
         Return _Connected
      End Get
   End Property

   Public ReadOnly Property Connect_Background As SolidColorBrush
      Get
         Return (If(_Connected, Brushes.Green, Brushes.Red))
      End Get
   End Property

   Private _ProgramPath As String

   Public ReadOnly Property ProgramPath As String
      Get
         Return _ProgramPath
      End Get
   End Property

   Private _ProgramIndex As Integer = 0

   Public Property ProgramIndex As Integer
      Get
         Return _ProgramIndex
      End Get
      Set(ByVal value As Integer)
         _ProgramIndex = value
      End Set
   End Property

   Private _VarName As String

   Public Property VarName As String
      Get
         Return _VarName
      End Get
      Set(ByVal value As String)
         _VarName = value
      End Set
   End Property

   Private _VarValue As String = ""

   Public Property VarValue As String
      Get
         Return _VarValue
      End Get
      Set(ByVal value As String)
         _VarValue = value
      End Set
   End Property

   Public Sub SetVarValue(ByVal value As Object)
      _VarValue = CStr(value)
      NotifyPropertyChanged(NameOf(VarValue))
   End Sub

   'Private m_OPState As MachineOperatingState

   'Public ReadOnly Property OPState As MachineOperatingState
   '   Get
   '      Return m_OPState
   '   End Get
   'End Property

   'Public ReadOnly Property sOPState As String
   '   Get
   '      Select Case m_OPState
   '         Case MachineOperatingState.Start
   '            Return "START"
   '         Case MachineOperatingState.Stop
   '            Return "STOP"
   '         Case MachineOperatingState.End
   '            Return "RESET"
   '         Case MachineOperatingState.SetPoint
   '            Return "SETPOINT"
   '         Case MachineOperatingState.Pending
   '            Return "PENDING"
   '         Case Else
   '            Return "UNSPECIFIED"
   '      End Select
   '   End Get
   'End Property

   Friend bMsgTranslationActive As Boolean = False

   Private m_ErrCycle As New List(Of Alarm)
   Private m_ErrCycleCount As Integer = 0
   Public ReadOnly Property sErrCycle As String
      Get
         Dim ShownErr As Alarm = If(m_ErrCycleCount < m_ErrCycle.Count, m_ErrCycle(m_ErrCycleCount), Nothing)
         NotifyPropertyChanged(NameOf(ErrCycle_Foreground))
         Select Case CurrentMachine.NCType
            Case NCTypes.TPA
               Return If(Not IsNothing(ShownErr), ShownErr.sCode & ": " & ShownErr.sMessage, "")
            Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
               Return If(Not IsNothing(ShownErr), ShownErr.sMessage, "")
            Case Else
               Return ""
         End Select
      End Get
   End Property
   Public ReadOnly Property ErrCycle_Foreground As SolidColorBrush
      Get
         Return If(m_ErrCycle.Count > 0, Brushes.Red, Brushes.White)
      End Get
   End Property

   Private m_Iso As New List(Of Alarm)
   Private m_IsoCount As Integer = 0
   Public ReadOnly Property sIso As String
      Get
         Dim ShownErr As Alarm = If(m_IsoCount < m_Iso.Count, m_Iso(m_IsoCount), Nothing)
         NotifyPropertyChanged(NameOf(Iso_Foreground))
         Select Case CurrentMachine.NCType
            Case NCTypes.TPA
               Return If(Not IsNothing(ShownErr), ShownErr.sCode & ": " & ShownErr.sMessage, "")
            Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
               Return If(Not IsNothing(ShownErr), ShownErr.sMessage, "")
            Case Else
               Return ""
         End Select
      End Get
   End Property
   Public ReadOnly Property Iso_Foreground As SolidColorBrush
      Get
         Return If(m_Iso.Count > 0, Brushes.Yellow, Brushes.White)
      End Get
   End Property

   Private m_Message As New List(Of Alarm)
   Private m_MessageCount As Integer = 0
   Public ReadOnly Property sMessage As String
      Get
         Dim ShownErr As Alarm = If(m_MessageCount < m_Message.Count, m_Message(m_MessageCount), Nothing)
         NotifyPropertyChanged(NameOf(Message_Foreground))
         Select Case CurrentMachine.NCType
            Case NCTypes.TPA
               Return If(Not IsNothing(ShownErr), ShownErr.sCode & ": " & ShownErr.sMessage, "")
            Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
               Return If(Not IsNothing(ShownErr), ShownErr.sMessage, "")
            Case Else
               Return ""
         End Select
      End Get
   End Property
   Public ReadOnly Property Message_Foreground As SolidColorBrush
      Get
         Return If(m_Message.Count > 0, Brushes.Green, Brushes.White)
      End Get
   End Property

   Private m_ErrSystem As New List(Of Alarm)
   Private m_ErrSystemCount As Integer = 0
   Public ReadOnly Property sErrSystem As String
      Get
         Dim ShownErr As Alarm = If(m_ErrSystemCount < m_ErrSystem.Count, m_ErrSystem(m_ErrSystemCount), Nothing)
         NotifyPropertyChanged(NameOf(ErrSystem_Foreground))
         Select Case CurrentMachine.NCType
            Case NCTypes.TPA
               Return If(Not IsNothing(ShownErr), ShownErr.sCode & ": " & ShownErr.sMessage, "")
            Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
               Return If(Not IsNothing(ShownErr), ShownErr.sMessage, "")
            Case Else
               Return ""
         End Select
      End Get
   End Property
   Public ReadOnly Property ErrSystem_Foreground As SolidColorBrush
      Get
         Return If(m_ErrSystem.Count > 0, Brushes.Aqua, Brushes.White)
      End Get
   End Property

   Public ReadOnly Property DeleteAlarm_Visibility As Visibility
      Get
         Return If(CurrentMachine.NCType = NCTypes.TPA, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Private m_CommBtn_IsEnabled As Boolean = True
   Public ReadOnly Property CommBtn_IsEnabled As Boolean
      Get
         Return m_CommBtn_IsEnabled
      End Get
   End Property
   Friend Sub SetCommBtnIsEnabled(value As Boolean)
      m_CommBtn_IsEnabled = value
      NotifyPropertyChanged(NameOf(CommBtn_IsEnabled))
   End Sub

   ' definizione comandi
   Private m_cmdConnect As ICommand
   Private m_cmdDisconnect As ICommand
   Private m_cmdStart As ICommand
   Private m_cmdStop As ICommand
   Private m_cmdReset As ICommand
   Private m_cmdStep As ICommand
   Private m_cmdDeleteAlarms As ICommand
   Private m_cmdSetPoint As ICommand

   Public Sub New()
      Map.SetRefMachCommandMessagePanelVM(Me)
      ' impostazioni timer degli allarmi
      m_AlarmTimer.Interval = TimeSpan.FromMilliseconds(1500)
      AddHandler m_AlarmTimer.Tick, AddressOf AlarmTimer_Tick

      NotifyPropertyChanged(NameOf(Connect_Background))
   End Sub

   Private Sub AlarmTimer_Tick()
      If m_ErrCycle.Count = 0 AndAlso m_Iso.Count = 0 AndAlso m_Message.Count = 0 AndAlso m_ErrSystem.Count = 0 Then
         NotifyPropertyChanged(NameOf(sErrCycle))
         NotifyPropertyChanged(NameOf(sIso))
         NotifyPropertyChanged(NameOf(sMessage))
         NotifyPropertyChanged(NameOf(sErrSystem))
         Return
      End If
      If m_ErrCycle.Count > 0 Then
         If m_ErrCycleCount < m_ErrCycle.Count - 1 Then
            m_ErrCycleCount += 1
         Else
            m_ErrCycleCount = 0
         End If
      End If
      NotifyPropertyChanged(NameOf(sErrCycle))
      If m_Iso.Count > 0 Then
         If m_IsoCount < m_Iso.Count - 1 Then
            m_IsoCount += 1
         Else
            m_IsoCount = 0
         End If
      End If
      NotifyPropertyChanged(NameOf(sIso))
      If m_Message.Count > 0 Then
         If m_MessageCount < m_Message.Count - 1 Then
            m_MessageCount += 1
         Else
            m_MessageCount = 0
         End If
      End If
      NotifyPropertyChanged(NameOf(sMessage))
      If m_ErrSystem.Count > 0 Then
         If m_ErrSystemCount < m_ErrSystem.Count - 1 Then
            m_ErrSystemCount += 1
         Else
            m_ErrSystemCount = 0
         End If
      End If
      NotifyPropertyChanged(NameOf(sErrSystem))
   End Sub

   Public ReadOnly Property Connect_Command As ICommand
      Get
         If m_cmdConnect Is Nothing Then m_cmdConnect = New Command(AddressOf Connect)
         Return m_cmdConnect
      End Get
   End Property

   Public Sub Connect(ByVal param As Object)
      ' se gia' connesso, esco
      If Not IsNothing(m_MachManagingThread) Then Return
      ' creo thread gestione macchina
      m_MachManagingThread = New Thread(Sub()
                                           MachineCommThread.MachManagingThreadFunction(AddressOf ResultCallbackDlg, AddressOf CloseCallbackDlg,
                                                                                          AddressOf UpdateCallbackDlg, AddressOf TPAAlarmCallbackDlg, AddressOf NUMAlarmCallbackDlg,
                                                                                          AddressOf AxisCoordinatesCallbackDlg, AddressOf OpStateCallbackDlg,
                                                                                          AddressOf OpModeCallbackDlg, AddressOf ChannelCallbackDlg, AddressOf ReadVarCallbackDlg)
                                        End Sub)
      ' avvio thread di gestione della macchina che avvia la connessione
      m_MachManagingThread.Start()
   End Sub

   Private Sub Init()
      '' inizializzo tutte le variabili
      'RWVariableManager.InitVar(ASSE_X, "0.TESTA.AsseX.X", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_Y, "0.TESTA.AsseY.Y", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_Z, "0.TESTA.AsseZ.Z", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_B, "0.TESTA.AsseC.B", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(P_PROD, "0.FUNM.E81295", CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_MACHGROUP, "0.FUNM.E81296", CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_PART, "0.FUNM.E81297", CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_STATE, "0.FUNM.E81298", CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(RESET_STATE, "0.FUNM.E80048", CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(VPAR & "1", "0.ENTRATA.V01NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "2", "0.ENTRATA.V02NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "3", "0.ENTRATA.V03NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "4", "0.ENTRATA.V04NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "5", "0.ENTRATA.V05NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "6", "0.ENTRATA.V06NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "7", "0.ENTRATA.V07NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "8", "0.ENTRATA.V08NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "9", "0.ENTRATA.V09NextPiece", CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "10", "0.ENTRATA.V10NextPiece", CommVar.CommVarTypes.ONETIME)


      ' inizializzo valori assi leggendoli da variabili (non funziona nessuna combinazione)
      'MachManaging.CommandList.Add(ThreadCommand.CreateCommand(CommandTypes.READ, ASSE_X))
      'MachManaging.CommandList.Add(ThreadCommand.CreateCommand(CommandTypes.READ, ASSE_Y))
      'MachManaging.CommandList.Add(ThreadCommand.CreateCommand(CommandTypes.READ, ASSE_Z))
      'MachManaging.CommandList.Add(ThreadCommand.CreateCommand(CommandTypes.READ, ASSE_B))
      'MachManaging.CommandList.Add(ThreadCommand.CreateCommand(CommandTypes.READ, ASSE_C))
      'Dim t = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAny, "0.TESTA.X", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAny, "0.TESTA.Y", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAny, "0.TESTA.Z", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAny, "0.TESTA.C", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAny, "0.TESTA.B", "")
      'Dim t = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAxis, 0, "")
      ''t = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAxis, 1, "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAxis, 2, "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAxis, 3, "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadAxis, 4, "")
      'Dim t = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.AsseX.X", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.AsseY.Y", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.AsseZ.Z", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.AsseC.C", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.AsseB.B", "")
      'Dim t = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.X", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.Y", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.Z", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.C", "")
      't = Map.refMachManaging.Tpa.remObject.SetVariableCommand(ISOCNC.Remoting.VariableCommands.ReadVar, "0.TESTA.B", "")

      ' inizializzo le variabili principali
      Dim Index As Integer = 1
      Dim CommVariable As CommVar = MachManaging.InitVar(S_MAINVARIABLES, Index)
      While Not IsNothing(CommVariable)
         m_MainVariablesList.Add(New Variable(CommVariable))
         Index += 1
         CommVariable = MachManaging.InitVar(S_MAINVARIABLES, Index)
      End While

      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 1)))
      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 2)))
      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 3)))
      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 4)))
      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 5)))
      'm_MainVariablesList.Add(New Variable(MachManaging.InitVar(S_MAINVARIABLES, 6)))

      'RWVariableManager.InitVar(ASSE_X, GetVarPathByName(ASSE_X), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_Y, GetVarPathByName(ASSE_Y), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_Z, GetVarPathByName(ASSE_Z), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(ASSE_B, GetVarPathByName(ASSE_B), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(P_PROD, GetVarPathByName(P_PROD), CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_MACHGROUP, GetVarPathByName(P_MACHGROUP), CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_PART, GetVarPathByName(P_PART), CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(P_STATE, GetVarPathByName(P_STATE), CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(RESET_STATE, GetVarPathByName(RESET_STATE), CommVar.CommVarTypes.CONTINUOUS)
      'RWVariableManager.InitVar(VPAR & "1", GetVarPathByName(VPAR & "1"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "2", GetVarPathByName(VPAR & "2"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "3", GetVarPathByName(VPAR & "3"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "4", GetVarPathByName(VPAR & "4"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "5", GetVarPathByName(VPAR & "5"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "6", GetVarPathByName(VPAR & "6"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "7", GetVarPathByName(VPAR & "7"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "8", GetVarPathByName(VPAR & "8"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "9", GetVarPathByName(VPAR & "9"), CommVar.CommVarTypes.ONETIME)
      'RWVariableManager.InitVar(VPAR & "10", GetVarPathByName(VPAR & "10"), CommVar.CommVarTypes.ONETIME)

   End Sub

   Public ReadOnly Property Disconnect_Command As ICommand
      Get
         If m_cmdDisconnect Is Nothing Then m_cmdDisconnect = New Command(AddressOf Disconnect)
         Return m_cmdDisconnect
      End Get
   End Property

   Public Sub Disconnect()
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.DISCONNECT))
   End Sub

   Public Sub SetOPState(OpState As Integer)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.SETOPMODE))
   End Sub

   Public ReadOnly Property Start_Command As ICommand
      Get
         If m_cmdStart Is Nothing Then m_cmdStart = New Command(AddressOf Start)
         Return m_cmdStart
      End Get
   End Property

   Public Sub Start(ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.START))
   End Sub

   Public ReadOnly Property Stop_Command As ICommand
      Get
         If m_cmdStop Is Nothing Then m_cmdStop = New Command(AddressOf [Stop])
         Return m_cmdStop
      End Get
   End Property

   Public Sub [Stop](ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.STOP_))
   End Sub

   Public ReadOnly Property Reset_Command As ICommand
      Get
         If m_cmdReset Is Nothing Then m_cmdReset = New Command(AddressOf Reset)
         Return m_cmdReset
      End Get
   End Property

   Public Sub Reset(ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.RESET))
      ' annullo stato di pronto ad essere lavorato di tutti i programmi
      If Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then Map.refProjectVM.SupervisorMachGroupPanelVM.ResetAllMachGroups()
      ' rifaccio sort lista grezzi
      ' lancio sort custom
      Map.refSupervisorMachGroupPanelVM.RefreshMachGroupVMSort()
   End Sub

   Public ReadOnly Property Step_Command As ICommand
      Get
         If m_cmdStep Is Nothing Then m_cmdStep = New Command(AddressOf [Step])
         Return m_cmdStep
      End Get
   End Property

   Public Sub [Step](ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.STEP_))
   End Sub

   Public ReadOnly Property SetPoint_Command As ICommand
      Get
         If m_cmdSetPoint Is Nothing Then m_cmdSetPoint = New Command(AddressOf SetPoint)
         Return m_cmdSetPoint
      End Get
   End Property

   Public Sub SetPoint(ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.SETPOINT))
   End Sub


   Public ReadOnly Property DeleteAlarms_Command As ICommand
      Get
         If m_cmdDeleteAlarms Is Nothing Then m_cmdDeleteAlarms = New Command(AddressOf DeleteAlarms)
         Return m_cmdDeleteAlarms
      End Get
   End Property

   Public Sub DeleteAlarms(ByVal param As Object)
      MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.DELETEALARMS))
   End Sub

   Public Function GetVarPathByName(Name As String) As String
      Dim VarStr As String = Nothing
      Dim VarIndex As Integer = 1
      While EgtUILib.GetPrivateProfileString(S_VARIABLES, VarIndex, String.Empty, VarStr, CurrentMachine.sMachIniFile)
         Dim sVariableValues() As String = VarStr.Split(","c)
         ' verifico numero minimo di parametri
         If sVariableValues.Count >= 4 Then
            ' cancello spazi
            For Index = 0 To sVariableValues.Count - 1
               sVariableValues(Index) = sVariableValues(Index).Trim()
            Next
            ' ricavo i valori di Name e VarPath
            Dim sName As String = sVariableValues(0)
            Dim sVarPath As String = sVariableValues(1)
            If sName = Name Then Return sVarPath
         End If
         VarIndex += 1
      End While
      Return ""
   End Function

#Region "CALLBACKS"

   Friend Sub ResultCallbackDlg(CommandType As CommandTypes, CommandState As CommandStates, ResultType As ResultTypes, Params As String)
      Select Case CommandType
         Case CommandTypes.CONNECT
            If CommandState = CommandStates.OK Then
               _Connected = True
               NotifyPropertyChanged(NameOf(Connect_Background))
               If ResultType = ResultTypes.EXECUTED Then
                  ' avvio tick di comunicazione con la macchina
                  MachineCommThread.StartTick()
                  ' inizializzo variabili
                  Init()
                  If CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER Then
                     Map.refMachManaging.Num_Axium_APServer.GetGeneralFunctions()
                  End If
               End If
               ' scrivo evento programma attivato
               DbControllers.m_LogMachineController.Create(LogEvent.CreateMachCommandLog(LogEvent.MachineCommands.CONNECTION, "", 0, DbControllers.SupervisorId))
            End If
         Case CommandTypes.DISCONNECT
            If CommandState = CommandStates.OK Then
               _Connected = False
               NotifyPropertyChanged(NameOf(Connect_Background))
               ' scrivo evento programma attivato
               DbControllers.m_LogMachineController.Create(LogEvent.CreateMachCommandLog(LogEvent.MachineCommands.DISCONNECTION, "", 0, DbControllers.SupervisorId))
            End If
      End Select
      'DbControllers.m_LogMachineController.Create(MachLog.CreateResultLog(CommandType, CommandState, ResultType, Params))
   End Sub
   Friend Sub CloseCallbackDlg(ByRef bCancel As Boolean)
      ' serve?
   End Sub
   Friend Sub UpdateCallbackDlg(Param As String, Params As String)

   End Sub

   Friend Sub TPAAlarmCallbackDlg(ByVal AlarmOperation As Integer, ByVal AlarmType As Integer, ByVal AlarmMessage As String, ByVal AlarmCode As String, ByVal AlarmDateTime As String)
      ' se aggiungo allarme e non ce ne erano
      If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) AndAlso m_ErrCycle.Count = 0 AndAlso m_Iso.Count = 0 AndAlso m_Message.Count = 0 AndAlso m_ErrSystem.Count = 0 Then
         ' avvio il timer degli allarmi
         m_AlarmTimer.Start()
      End If
      ' analizzo errore
      Select Case AlarmType
         Case CInt(ISOCNC.Remoting.AlarmType.Cycle)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_Iso.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_Iso.RemoveAll(Function(x) x.sCode = AlarmCode)
               'Dim ToRemove As Alarm = m_ErrCycle.FirstOrDefault(Function(x) x.sCode = AlarmCode)
               'If Not IsNothing(ToRemove) Then
               '   m_ErrCycle.Remove(ToRemove)
               'End If
            End If
         Case CInt(ISOCNC.Remoting.AlarmType.ISO)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_ErrSystem.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_ErrSystem.RemoveAll(Function(x) x.sCode = AlarmCode)
               'Dim ToRemove As Alarm = m_Iso.FirstOrDefault(Function(x) x.sCode = AlarmCode)
               'If Not IsNothing(ToRemove) Then
               '   m_Iso.Remove(ToRemove)
               'End If
            End If
         Case CInt(ISOCNC.Remoting.AlarmType.Message)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_Message.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_Message.RemoveAll(Function(x) x.sCode = AlarmCode)
               'Dim ToRemove As Alarm = m_Message.FirstOrDefault(Function(x) x.sCode = AlarmCode)
               'If Not IsNothing(ToRemove) Then
               '   m_Message.Remove(ToRemove)
               'End If
            End If
         Case CInt(ISOCNC.Remoting.AlarmType.None)
         Case CInt(ISOCNC.Remoting.AlarmType.System)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_ErrCycle.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_ErrCycle.RemoveAll(Function(x) x.sCode = AlarmCode)
               'Dim ToRemove As Alarm = m_ErrSystem.FirstOrDefault(Function(x) x.sCode = AlarmCode)
               'If Not IsNothing(ToRemove) Then
               '   m_ErrSystem.Remove(ToRemove)
               'End If
            End If
         Case Else
      End Select
      ' forzo aggiornamento allarmi
      AlarmTimer_Tick()
      ' se non ci sono errori
      If m_ErrCycle.Count = 0 AndAlso m_Iso.Count = 0 AndAlso m_Message.Count = 0 AndAlso m_ErrSystem.Count = 0 Then
         ' fermo timer degli allarmi
         m_AlarmTimer.Stop()
      End If
      'DbControllers.m_LogMachineController.Create(MachLog.CreateAlarmLog(AlarmOperation, AlarmType, AlarmMessage, AlarmCode, AlarmDateTime))
      DbControllers.m_LogMachineController.Create(LogEvent.CreateAlarmLog(DateTime.Now(), AlarmOperation & LogEvent.cSeparator & AlarmType & LogEvent.cSeparator & AlarmMessage & LogEvent.cSeparator & AlarmCode & LogEvent.cSeparator & AlarmDateTime, DbControllers.m_SupervisorId))
   End Sub

   Friend Sub NUMAlarmCallbackDlg(ByVal CncNumber As Integer, ByVal AlarmOperation As Integer, ByVal ErrorTyp As String, ByVal ErrorIndex As String, ByVal ErrorNumber As String, ByVal ErrorLine As String, ByVal ErrorMessage As String, ByVal ErrorAdditional As String)

      ' se aggiungo allarme e non ce ne erano
      If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) AndAlso m_ErrCycle.Count = 0 AndAlso m_Iso.Count = 0 AndAlso m_Message.Count = 0 AndAlso m_ErrSystem.Count = 0 Then
         ' avvio il timer degli allarmi
         m_AlarmTimer.Start()
      End If
      Dim AlarmCode As String = ErrorTyp & " : " & ErrorIndex & " : " & ErrorNumber & " : " & ErrorLine
      Dim AlarmMessage As String = ErrorMessage & " : " & ErrorAdditional

      Dim nErrorIndex As Integer
      Dim nErrorNumber As Integer
      Dim nErrorExtNumber As Integer
      Dim nErrorTyp As Integer
      Dim nErrorLine As Integer
      Dim nErrorAdditional As Integer
      ' converto parametri messaggio in interi
      Integer.TryParse(ErrorIndex, nErrorIndex)
      Integer.TryParse(ErrorNumber, nErrorNumber)
      Integer.TryParse(ErrorTyp, nErrorTyp)
      Integer.TryParse(ErrorLine, nErrorLine)
      Integer.TryParse(ErrorAdditional, nErrorAdditional)

      Dim ErrorNumberMsg As String = "Number"
      Dim ErrorIndexMsg As String = "Index"
      Dim ErrorTypMsg As String = "Type"
      Dim ErrorLineMsg As String = "Line"
      Dim ErrorAdditionalMsg As String = "Additional"
      Dim ErrorExtNumberMsg As String = "Extended Number"

      ' costruisco messaggio errore in base al tipo
      Select Case ErrorTyp
         Case NUM_ErrorTypes.CNC_Boot_Message
         Case NUM_ErrorTypes.CNC_System_Warning
         Case NUM_ErrorTypes.CNC_Message
            ErrorIndexMsg = "CN"
            If Map.refMachManaging.Num_Flexium.IsFlexiumPlus Then
               nErrorExtNumber = Convert.ToInt32(ErrorNumber) >> 16
               nErrorNumber = Convert.ToInt32(ErrorNumber) And &HFFFF
               ErrorExtNumberMsg = "Ext"
               ErrorAdditionalMsg = "Line Number"
               ErrorNumberMsg = "CN:"
            End If
            Dim sErrorMessage As String = ErrorMessage
            If bMsgTranslationActive Then
               Dim sTranslatedMsg = MachMsg(MsgParagraphs.CNC, nErrorNumber)
               If Not String.IsNullOrWhiteSpace(sTranslatedMsg) Then
                  sErrorMessage = sTranslatedMsg
               End If
            End If
            ErrorLineMsg = "Number from the Cnc Block"
            AlarmMessage = If(nErrorNumber <> 0, ErrorNumberMsg & ": " & nErrorNumber & " - ", "") &
                           If(nErrorExtNumber <> 0, " - " & ErrorExtNumberMsg & ": " & nErrorExtNumber, "") &
                           " " & sErrorMessage
         Case NUM_ErrorTypes.Drive_Error
            ErrorIndexMsg = "Azionamento: Asse"
            ErrorNumberMsg = "Ext"
            ErrorExtNumberMsg = "Errore"
            nErrorExtNumber = Convert.ToInt32(ErrorNumber) >> 16
            nErrorNumber = Convert.ToInt32(ErrorNumber) And &HFFFF
            AlarmMessage = If(nErrorIndex <> 0, ErrorIndexMsg & ": " & nErrorIndex & " - ", "") &
                           If(nErrorExtNumber <> 0, " - " & ErrorExtNumberMsg & ": " & nErrorExtNumber, "") &
                           If(nErrorNumber <> 0, ErrorNumberMsg & ": " & nErrorNumber & " - ", "") &
                           If(nErrorLine <> 0, " - " & ErrorLineMsg & ": " & nErrorLine, "") &
                           " " & ErrorMessage & If(nErrorAdditional <> 0, " - " & ErrorAdditionalMsg & ": " & nErrorAdditional, "")
         Case NUM_ErrorTypes.Communication_Message
            AlarmMessage = "COMM: " & nErrorNumber & " " & ErrorMessage
         Case NUM_ErrorTypes.PLC_Message_Reaction_Class_1,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_2,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_3,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_4,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_5,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_6,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_7,
              NUM_ErrorTypes.PLC_Message_Reaction_Class_8
            Dim sErrorMessage As String = ErrorMessage
            If bMsgTranslationActive Then
               Dim sTranslatedMsg = MachMsg(MsgParagraphs.PLC, nErrorNumber)
               If Not String.IsNullOrWhiteSpace(sTranslatedMsg) Then
                  sErrorMessage = sTranslatedMsg
               End If
            End If
            ErrorNumberMsg = "PLC"
            ErrorTypMsg = "Classe"
            If CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT OrElse CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER Then
               AlarmMessage = If(nErrorNumber <> 0, ErrorNumberMsg & ": " & nErrorNumber & " - ", "") &
                              sErrorMessage
            Else
               AlarmMessage = If(nErrorIndex <> 0, ErrorIndexMsg & ": " & nErrorIndex & " - ", "") &
                              If(nErrorNumber <> 0, ErrorNumberMsg & ": " & nErrorNumber & " - ", "") &
                              If(nErrorExtNumber <> 0, " - " & ErrorExtNumberMsg & ": " & nErrorExtNumber, "") &
                              ErrorTypMsg & ": " & nErrorTyp - 5 &
                              If(nErrorLine <> 0, " - " & ErrorLineMsg & ": " & nErrorLine, "") &
                              " " & sErrorMessage & If(nErrorAdditional <> 0, " - " & ErrorAdditionalMsg & ": " & nErrorAdditional, "")
            End If
         Case NUM_ErrorTypes.HMI_Message
         Case NUM_ErrorTypes.RTS_Message
         Case NUM_ErrorTypes.Drive_Warning
            ErrorIndexMsg = "Drive Address"
         Case NUM_ErrorTypes.SysInfo_Message
         Case NUM_ErrorTypes.CNC_Warning
         Case NUM_ErrorTypes.OperatorMsg
            AlarmMessage = "OpMsg: " & ErrorMessage
      End Select
      AlarmCode = nErrorIndex & "." & nErrorNumber & "." & nErrorExtNumber & "." & nErrorTyp & "." & nErrorLine & "." & nErrorAdditional
      If IsNothing(AlarmMessage) Then
         AlarmMessage = If(nErrorIndex <> 0, ErrorIndexMsg & ": " & nErrorIndex & " - ", "") &
                     If(nErrorNumber <> 0, ErrorNumberMsg & ": " & nErrorNumber & " - ", "") &
                     If(nErrorExtNumber <> 0, " - " & ErrorExtNumberMsg & ": " & nErrorExtNumber, "") &
                     ErrorTypMsg & ": " &
                     If(nErrorLine <> 0, " - " & ErrorLineMsg & ": " & nErrorLine, "") &
                     " " & ErrorMessage & If(nErrorAdditional <> 0, " - " & ErrorAdditionalMsg & ": " & nErrorAdditional, "")
      End If
      ' scrivo messaggio di errore
      Select Case ErrorTyp
         ' Rossi
         Case CInt(NUM_ErrorTypes.CNC_Boot_Message),
              CInt(NUM_ErrorTypes.CNC_System_Warning),
              CInt(NUM_ErrorTypes.CNC_Warning),
              CInt(NUM_ErrorTypes.CNC_Message),
              CInt(NUM_ErrorTypes.Drive_Error),
              CInt(NUM_ErrorTypes.Communication_Message),
              CInt(NUM_ErrorTypes.HMI_Message),
              CInt(NUM_ErrorTypes.RTS_Message)

            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_ErrCycle.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_ErrCycle.RemoveAll(Function(x) x.sCode = AlarmCode)
            End If
            ' Gialli
         Case CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_1),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_2),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_3),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_4),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_5),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_6),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_7),
              CInt(NUM_ErrorTypes.PLC_Message_Reaction_Class_8),
              CInt(NUM_ErrorTypes.Drive_Warning)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_Iso.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_Iso.RemoveAll(Function(x) x.sCode = AlarmCode)
            End If
            ' Verdi
         Case CInt(NUM_ErrorTypes.User_Message),
              CInt(NUM_ErrorTypes.SysInfo_Message)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_Message.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               m_Message.RemoveAll(Function(x) x.sCode = AlarmCode)
            End If
            ' Azzzurri
         Case CInt(NUM_ErrorTypes.OperatorMsg)
            If AlarmOperation = CInt(ISOCNC.Remoting.AlarmOperation.Addition) Then
               m_ErrSystem.Add(Alarm.CreateAlarm(AlarmCode, AlarmMessage))
            Else
               Select Case CurrentMachine.NCType
                  Case NCTypes.TPA
                     m_ErrSystem.RemoveAll(Function(x) x.sCode = AlarmCode)
                  Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
                     m_ErrSystem.RemoveAll(Function(x) x.sMessage = AlarmMessage)
               End Select
            End If
         Case Else
      End Select
      ' forzo aggiornamento allarmi
      AlarmTimer_Tick()
      ' se non ci sono errori
      If m_ErrCycle.Count = 0 AndAlso m_Iso.Count = 0 AndAlso m_Message.Count = 0 AndAlso m_ErrSystem.Count = 0 Then
         ' fermo timer degli allarmi
         m_AlarmTimer.Stop()
      End If
      'DbControllers.m_LogMachineController.Create(MachLog.CreateAlarmLog(AlarmOperation, ErrorTyp, AlarmMessage, AlarmCode, DateTime.Now))
      DbControllers.m_LogMachineController.Create(LogEvent.CreateAlarmLog(DateTime.Now(), AlarmOperation & LogEvent.cSeparator & ErrorTyp & LogEvent.cSeparator & AlarmMessage & LogEvent.cSeparator & AlarmCode & LogEvent.cSeparator, DbControllers.m_SupervisorId))
   End Sub

   Friend Sub AxisCoordinatesCallbackDlg(AxisValue As Double, AxisIndex As Integer)
      Map.refAxesPanelVM.AxisCoordinatesCallbackDlg(AxisValue, AxisIndex)
   End Sub

   Friend Sub OpStateCallbackDlg(newOpState As Integer)
      Dim NewState As OPState = Map.refLeftPanelVM.OPStateList.FirstOrDefault(Function(x) x.Id = newOpState)
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            If newOpState <> OPStates.Unspecified Then
               Dim bDifferent As Boolean = (Map.refLeftPanelVM.SelOPState.Id <> newOpState)
               Map.refLeftPanelVM.SetOPState(NewState)
               If bDifferent Then
                  For Each MachGroup As MyMachGroupVM In Map.refSupervisorMachGroupPanelVM.MachGroupVMList
                     MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Produce_IsEnabled))
                  Next
               End If
            End If
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            Map.refLeftPanelVM.SetOPState(NewState)
      End Select
      'DbControllers.m_LogMachineController.Create(MachLog.CreateOPStateLog(newOpState))
      DbControllers.m_LogMachineController.Create(LogEvent.CreateMachineStateLog(newOpState, DbControllers.m_SupervisorId))
   End Sub

   Friend Sub OpModeCallbackDlg(newOpState As Integer)
      Dim NewState As OPState = Map.refLeftPanelVM.OPModeList.FirstOrDefault(Function(x) x.Id = newOpState)
      If IsNothing(NewState) Then
         EgtOutLog("Machine state not recognized, state " & newOpState)
         Return
      End If
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            Map.refLeftPanelVM.SetOPMode(NewState)
      End Select
      'DbControllers.m_LogMachineController.Create(MachLog.CreateOPStateLog(newOpState))
      DbControllers.m_LogMachineController.Create(LogEvent.CreateMachineModeLog(newOpState, DbControllers.m_SupervisorId))
   End Sub

   Friend Sub ChannelCallbackDlg(NewChannelId As Short)
      Dim NewChannel As IdNameStruct = Map.refLeftPanelVM.ChannelList.FirstOrDefault(Function(x) x.Id = NewChannelId)
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            Map.refLeftPanelVM.SetChannel(NewChannel)
      End Select
      'DbControllers.m_LogMachineController.Create(MachLog.CreateOPStateLog(NewChannelId))
   End Sub

   Friend Sub ReadVarCallbackDlg(CommandExecutedCorrectly As Boolean, VarAddress As String, VarValue As String, VarType As Integer)
      Dim VarName As String = RWVariableManager.GetReadVarNameFromAddress(VarAddress)
      If Not String.IsNullOrEmpty(VarName) Then
         Select Case VarName
            Case "AsseX", "AsseY", "AsseZ", "AsseC", "AsseB"
               SetAxisValue(VarName, VarValue)
         End Select
         'DbControllers.m_LogMachineController.Create(MachLog.CreateReadLog(CommandExecutedCorrectly, VarAddress, VarValue))
         DbControllers.m_LogMachineController.Create(LogEvent.CreateReadVarLog(VarAddress, VarValue, DbControllers.SupervisorId))
      End If
   End Sub

   Private Sub SetAxisValue(VarName As String, VarValue As String)
      Dim Axis As Axis = Map.refAxesPanelVM.AxesList.FirstOrDefault(Function(x) x.sName = VarName)
      If Not IsNothing(Axis) Then
         Axis.SetValue(VarValue)
      End If
   End Sub

#End Region    ' CALLBACKS

End Class

Class Alarm

   Private m_sCode As String
   Public ReadOnly Property sCode As String
      Get
         Return m_sCode
      End Get
   End Property

   Private m_sMessage As String
   Public ReadOnly Property sMessage As String
      Get
         Return m_sMessage
      End Get
   End Property

   Protected Sub New()
   End Sub

   Public Shared Function CreateAlarm(Code As String, Message As String) As Alarm
      Dim NewAlarm As New Alarm
      NewAlarm.m_sCode = Code
      NewAlarm.m_sMessage = Message
      Return NewAlarm
   End Function

End Class