Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports EgtBEAMWALL.Core.ConstMachComm
Imports ISOCNC.Remoting
Imports EgtUILib
Imports EgtWPFLib5
Imports System.IO
Imports EgtBEAMWALL.Core
Imports EgtBEAMWALL.Supervisor.CommVar

Public Class MachManaging

   ' lock per aggiunta elemento a lista MachGroup
   Private Shared Lock_CommandList As New Object

   Private m_bConnected As Boolean = False
   Public ReadOnly Property bConnected As Boolean
      Get
         Return m_bConnected
      End Get
   End Property
   Friend Sub SetConnected(value As Boolean)
      m_bConnected = value
   End Sub

   Private m_CN As Object = Nothing
   Public ReadOnly Property CN As Object
      Get
         Return m_CN
      End Get
   End Property
   Public ReadOnly Property Tpa As TPAComm
      Get
         Return m_CN
      End Get
   End Property
   Public ReadOnly Property Num_Flexium As NUMFlexiumComm
      Get
         Return m_CN
      End Get
   End Property
   Public ReadOnly Property Num_Axium_APServer As NUMAxiumComm
      Get
         Return m_CN
      End Get
   End Property
   Public ReadOnly Property Num_Axium_PCToolkit As NUMAxiumPcToolkitComm
      Get
         Return m_CN
      End Get
   End Property

   Private Shared WithEvents m_CommandList As New ObservableCollection(Of ThreadCommand)
   Public Shared ReadOnly Property CommandList As ObservableCollection(Of ThreadCommand)
      Get
         Return m_CommandList
      End Get
   End Property
   Friend Shared Sub AddToCommandList(value As ThreadCommand)
      SyncLock Lock_CommandList
         ' EgtOutLog("Inizio ciclo rimozioni")
         For CommandIndex = m_CommandList.Count - 1 To 0 Step -1
            Dim Command As ThreadCommand = m_CommandList(CommandIndex)
            If Command.ProcessingStatus = ThreadCommand.ProcessingStatuses.DONE Then
               ' EgtOutLog("Inizio rimozione comando")
               m_CommandList.Remove(Command)
               ' EgtOutLog("Fine rimozione comando")
            End If
         Next
         ' EgtOutLog("Fine ciclo rimozioni")
         CommandList.Add(value)
         ' EgtOutLog("Count dopo aggiunta: " & CommandList.Count)
      End SyncLock
   End Sub

   Private m_bStartPending As Boolean = False
   Public ReadOnly Property StartPending As Boolean
      Get
         Return m_bStartPending
      End Get
   End Property
   Friend Sub ResetStartPending()
      m_bStartPending = False
   End Sub
   Friend Sub SetStartPending(value As Boolean)
      m_bStartPending = value
   End Sub

   ' prossima barra di cui mando i parametri di carico
   Private m_NextBarId As Integer

   ' indice di lavorazione della macchina (pareti NUM)
   Private m_nMachIndex As Integer
   Friend ReadOnly Property nMachIndex As Integer
      Get
         Return m_nMachIndex
      End Get
   End Property

   Sub New()
      ' imposto in Map
      Map.SetRefMachManaging(Me)
      AddHandler m_CommandList.CollectionChanged, AddressOf CommandList_CollectionChanged
      ' mi connetto alla macchina
      Connect()
   End Sub

   Private Sub OnDispose()
      RemoveHandler m_CommandList.CollectionChanged, AddressOf CommandList_CollectionChanged
   End Sub

   Friend Sub Timer_Tick()
      Select Case CurrentMachine.NCType
         'Case NCTypes.TPA
         '   'Dim bCancel As Boolean = False
         '   'callback(0, "Init", bCancel)

         '   ' leggo tutte le variabili
         '   CN.RWVariableManager.RefreshAllVars()

         '   ' eseguo ciclo principale
         '   Dim nReset_State As Integer
         '   Dim nP_Prod As Integer
         '   Dim nP_Machgroup As Integer
         '   Dim nP_Part As Integer
         '   Dim nP_State As Integer
         '   CN.RWVariableManager.ReadVar(P_PROD, nP_Prod)
         '   CN.RWVariableManager.ReadVar(P_MACHGROUP, nP_Machgroup)
         '   CN.RWVariableManager.ReadVar(P_PART, nP_Part)
         '   CN.RWVariableManager.ReadVar(P_STATE, nP_State)
         '   CN.RWVariableManager.ReadVar(RESET_STATE, nReset_State)
         '   ' se non ancora fatto, preparo variabili barra successiva
         '   If CurrentMachine.Flow = FlowTypes.CONTINUOUS AndAlso m_NextBarId = 0 Then
         '      SetNextBarVars()
         '   End If
         '   'Dim TestOpState As Integer = Tpa.remObject.MachineOperativeStatus
         '   ' verifico se scattato stato reset
         '   If nReset_State <> 0 Then
         '      ' resetto tutti i programmi
         '      If Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then Map.refProjectVM.SupervisorMachGroupPanelVM.ResetAllMachGroups()
         '      ' resetto variabili P
         '      Tpa.RWVariableManager.WriteVar(P_PROD, 0)
         '      Tpa.RWVariableManager.WriteVar(P_MACHGROUP, 0)
         '      Tpa.RWVariableManager.WriteVar(P_PART, 0)
         '      Tpa.RWVariableManager.WriteVar(P_STATE, 0)
         '      ' cancello tutti i programmi da memoria CN
         '      RemoveAllProgram() ' rimuovo programma default per pending
         '      ' azzero variabile reset
         '      Tpa.remObject.SetVariableCommand(CInt(ISOCNC.Remoting.VariableCommands.WriteVar),
         '                                    RWVariableManager.GetReadVarFromName(RESET_STATE).sAddress, "0")
         '      ' resetto prossima barra e variabili V
         '      If CurrentMachine.Flow = FlowTypes.CONTINUOUS Then
         '         m_NextBarId = 0
         '         For Index As Integer = 1 To 6
         '            Tpa.RWVariableManager.WriteVar(VPAR & Index.ToString(), 0)
         '         Next
         '      End If
         '      Return
         '      ' se macchina pronta e non sta tagliando alcun pezzo
         '   ElseIf (nP_Prod = 0 AndAlso
         '    nP_Machgroup = 0 AndAlso
         '    nP_Part = 0 AndAlso
         '    nP_State = PartState.NULL) AndAlso
         '    Tpa.opState = MachineOperatingState.Pending AndAlso Tpa.remObject.MachineOperativeStatus = MachineOperatingState.Pending Then
         '      ' verifico se c'e' un programma da lanciare
         '      SendNextProgram()
         '      ' attesa per essere sicuro che abbia scritto e riletto variabili
         '      Threading.Thread.Sleep(300)
         '      ' verifico stati inizio e fine pezzi
         '   ElseIf nP_Prod <> 0 AndAlso
         '    nP_Machgroup <> 0 AndAlso
         '    nP_Part <> 0 Then
         '      If nP_State = PartState.START Then
         '         ' scrivo data start su Db pezzo
         '         Dim dtStart As DateTime = DateTime.Now()
         '         DbControllers.m_PartController.UpdateStart(nP_Prod, nP_Machgroup, nP_Part, dtStart)
         '         DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, nP_Part, ItemState.WIP)
         '         ' recupero gruppo di lavorazione del pezzo
         '         Dim MachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) x.Id = nP_Machgroup)
         '         ' recupero pezzo
         '         Dim Part As PartVM = MachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nP_Part)
         '         ' scrivo stato start
         '         Part.nProduction_State = ItemState.WIP
         '         Part.dtStartTime = dtStart
         '         Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
         '         ' azzero variabile per far ripartire macchina
         '         Tpa.RWVariableManager.WriteVar(P_STATE, 0)
         '         ' se nessun pezzo della barra diverso da quello corrente e' in start
         '         If Not MachGroup.PartVMList.Any(Function(x) x.nPartId <> nP_Part AndAlso x.nProduction_State = 1) Then
         '            ' scrivo data start su Db barra
         '            DbControllers.m_MachGroupController.UpdateStart(nP_Prod, nP_Machgroup, dtStart)
         '            DbControllers.m_MachGroupController.UpdateStatus(nP_Prod, nP_Machgroup, ItemState.WIP)
         '            ' scrivo stato start
         '            MachGroup.MyMachGroupM.SetProductionState(ItemState.WIP)
         '            MachGroup.dtStartTime = dtStart
         '            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.nProduction_State))
         '         End If
         '         ' attesa per essere sicuro che abbia scritto e riletto variabili
         '         Threading.Thread.Sleep(300)
         '      ElseIf nP_State = PartState.END_ Then
         '         ' scrivo data end su Db pezzo
         '         Dim dtEnd As DateTime = DateTime.Now()
         '         DbControllers.m_PartController.UpdateEnd(nP_Prod, nP_Machgroup, nP_Part, dtEnd)
         '         DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, nP_Part, ItemState.Produced)
         '         ' recupero gruppo di lavorazione del pezzo
         '         Dim MachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) x.Id = nP_Machgroup)
         '         ' recupero pezzo
         '         Dim Part As PartVM = MachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nP_Part)
         '         ' scrivo stato end
         '         Part.nProduction_State = ItemState.Produced
         '         Part.dtEndTime = dtEnd
         '         Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
         '         ' resetto stato redo
         '         Part.bRedo = False
         '         ' azzero variabile per far ripartire macchina
         '         Tpa.RWVariableManager.WriteVar(P_STATE, 0)
         '         ' se tutti i pezzi della barra sono in end
         '         If MachGroup.PartVMList.All(Function(x) x.nProduction_State >= 2) Then
         '            ' scrivo data end su Db barra
         '            DbControllers.m_MachGroupController.UpdateEnd(nP_Prod, nP_Machgroup, dtEnd)
         '            DbControllers.m_MachGroupController.UpdateStatus(nP_Prod, nP_Machgroup, ItemState.Produced)
         '            ' scrivo stato end
         '            MachGroup.MyMachGroupM.SetProductionState(ItemState.Produced)
         '            MachGroup.dtEndTime = dtEnd
         '            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.nProduction_State))
         '            ' azzero tutte le variabilli per iniziare barra successiva
         '            Tpa.RWVariableManager.WriteVar(P_PROD, 0)
         '            Tpa.RWVariableManager.WriteVar(P_MACHGROUP, 0)
         '            Tpa.RWVariableManager.WriteVar(P_PART, 0)
         '            Tpa.RWVariableManager.WriteVar(P_STATE, 0)
         '            ' resetto stati di produzione
         '            MachGroup.ResetProduce()
         '            ' se partenza pezzi uno a uno
         '            If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
         '               ' riattivo bottone produzione per tutti gli altri
         '               MyMachGroupVM.UpdateProduceIsEnabledForAll()
         '            End If
         '         End If
         '         Map.refLeftPanelVM.PrintLabel(MachGroup, Part)
         '         ' attesa per essere sicuro che abbia scritto e riletto variabili
         '         Threading.Thread.Sleep(300)
         '      End If
         '   End If
         Case NCTypes.NUM_FLEXIUM, NCTypes.TPA, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            ' eseguo ciclo principale
            Dim nReset_State As Integer
            Dim nStart_State As Boolean
            Dim nStop_State As Boolean
            Dim nP_Prod As Integer
            Dim nP_Machgroup As Integer
            Dim nP_Part As Integer
            Dim nP_State As Integer
            Dim nISO_Num As Integer
            Dim nISO_Sent As Integer
            Dim nRunning As Integer
            Dim nCurrMachIndex As Integer
            Dim ResetVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = RESET_STATE)
            Dim StartVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = START_STATE)
            Dim StopVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = STOP_STATE)
            Dim ProdVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_PROD)
            Dim MachGroupVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_MACHGROUP)
            Dim PartVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_PART)
            Dim StateVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_STATE)
            Dim ISONumVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = ISO_NUM)
            Dim ISOSentVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = ISO_SENT)
            Dim RunningVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = RUNNING)
            Dim MachIndexVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = MACHINDEX)
            Select Case CurrentMachine.NCType
               Case NCTypes.TPA
                  ' leggo tutte le variabili
                  Tpa.RWVariableManager.RefreshAllVars()
                  Tpa.RWVariableManager.ReadVar(P_PROD, nP_Prod)
                  Tpa.RWVariableManager.ReadVar(P_MACHGROUP, nP_Machgroup)
                  Tpa.RWVariableManager.ReadVar(P_PART, nP_Part)
                  Tpa.RWVariableManager.ReadVar(P_STATE, nP_State)
                  Tpa.RWVariableManager.ReadVar(RESET_STATE, nReset_State)
               Case NCTypes.NUM_FLEXIUM
                  ResetVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = RESET_STATE)
                  StartVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = START_STATE)
                  StopVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = STOP_STATE)
                  ProdVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_PROD)
                  MachGroupVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_MACHGROUP)
                  PartVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_PART)
                  StateVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = P_STATE)
                  ISONumVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = ISO_NUM)
                  ISOSentVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = ISO_SENT)
                  RunningVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = RUNNING)
                  MachIndexVariable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = MACHINDEX)
                  Integer.TryParse(ResetVariable.sValue, nReset_State)
                  Boolean.TryParse(StartVariable.sValue, nStart_State)
                  Boolean.TryParse(StopVariable.sValue, nStop_State)
                  Integer.TryParse(ProdVariable.sValue, nP_Prod)
                  Integer.TryParse(MachGroupVariable.sValue, nP_Machgroup)
                  Integer.TryParse(PartVariable.sValue, nP_Part)
                  Integer.TryParse(StateVariable.sValue, nP_State)
                  Integer.TryParse(ISONumVariable.sValue, nISO_Num)
                  Integer.TryParse(ISOSentVariable.sValue, nISO_Sent)
                  Integer.TryParse(RunningVariable.sValue, nRunning)
                  Integer.TryParse(MachIndexVariable.sValue, nCurrMachIndex)
                  ' se indice lavorazione positivo, lo aggiorno
                  If nCurrMachIndex > 0 AndAlso nReset_State = 0 Then
                     m_nMachIndex = nCurrMachIndex
                  End If
               Case NCTypes.NUM_AXIUM_APSERVER
                  Dim dTemp As Double = 0
                  Dim nTemp As Integer = 0
                  If Not IsNothing(ResetVariable.sValue) Then
                     Integer.TryParse(ResetVariable.sValue, nReset_State)
                  Else
                     nReset_State = 1
                  End If
                  If Not IsNothing(StartVariable.sValue) Then
                     Integer.TryParse(StartVariable.sValue, nTemp)
                     nStart_State = (nTemp = 1)
                  Else
                     nStart_State = -1
                  End If
                  If Not IsNothing(StopVariable.sValue) Then
                     Integer.TryParse(StopVariable.sValue, nTemp)
                     nStop_State = (nTemp = 1)
                  Else
                     nStop_State = -1
                  End If
                  If Not IsNothing(ProdVariable.sValue) Then
                     Integer.TryParse(ProdVariable.sValue, nP_Prod)
                  Else
                     nP_Prod = -1
                  End If
                  If Not IsNothing(MachGroupVariable.sValue) Then
                     Integer.TryParse(MachGroupVariable.sValue, nP_Machgroup)
                  Else
                     nP_Machgroup = -1
                  End If
                  If Not IsNothing(PartVariable.sValue) Then
                     Integer.TryParse(PartVariable.sValue, nP_Part)
                  Else
                     nP_Part = -1
                  End If
                  If Not IsNothing(StateVariable.sValue) Then
                     Integer.TryParse(StateVariable.sValue, nP_State)
                  Else
                     nP_State = -1
                  End If
                  If Not IsNothing(ISONumVariable.sValue) Then
                     Integer.TryParse(ISONumVariable.sValue, nISO_Num)
                  Else
                     nISO_Num = -1
                  End If
                  If Not IsNothing(ISOSentVariable.sValue) Then
                     Integer.TryParse(ISOSentVariable.sValue, nISO_Sent)
                  Else
                     nISO_Sent = -1
                  End If
                  If Not IsNothing(RunningVariable.sValue) Then
                     Integer.TryParse(RunningVariable.sValue, nRunning)
                  Else
                     nRunning = -1
                  End If
                  If Not IsNothing(MachIndexVariable.sValue) Then
                     Integer.TryParse(MachIndexVariable.sValue, nCurrMachIndex)
                  Else
                     nCurrMachIndex = -1
                  End If
                  ' se indice lavorazione positivo, lo aggiorno
                  If nCurrMachIndex > 0 AndAlso nReset_State = 0 Then
                     m_nMachIndex = nCurrMachIndex
                  End If
                  ' leggo messaggi plc
                  ReadPLCMessages()
               Case NCTypes.NUM_AXIUM_PCTOOLKIT
                  ' leggo tutte le variabili
                  Num_Axium_PCToolkit.RefreshAllVars()
                  'EgtOutLog("Post lettura variabili")
                  Dim dTemp As Double = 0
                  Dim nTemp As Integer = 0
                  If Not IsNothing(ResetVariable.sValue) Then
                     Integer.TryParse(ResetVariable.sValue, nReset_State)
                  Else
                     nReset_State = 1
                  End If
                  If Not IsNothing(StartVariable.sValue) Then
                     Integer.TryParse(StartVariable.sValue, nTemp)
                     nStart_State = (nTemp = 1)
                  Else
                     nStart_State = -1
                  End If
                  If Not IsNothing(StopVariable.sValue) Then
                     Integer.TryParse(StopVariable.sValue, nTemp)
                     nStop_State = (nTemp = 1)
                  Else
                     nStop_State = -1
                  End If
                  If Not IsNothing(ProdVariable.sValue) Then
                     Integer.TryParse(ProdVariable.sValue, nP_Prod)
                  Else
                     nP_Prod = -1
                  End If
                  If Not IsNothing(MachGroupVariable.sValue) Then
                     Integer.TryParse(MachGroupVariable.sValue, nP_Machgroup)
                  Else
                     nP_Machgroup = -1
                  End If
                  If Not IsNothing(PartVariable.sValue) Then
                     Integer.TryParse(PartVariable.sValue, nP_Part)
                  Else
                     nP_Part = -1
                  End If
                  If Not IsNothing(StateVariable.sValue) Then
                     Integer.TryParse(StateVariable.sValue, nP_State)
                  Else
                     nP_State = -1
                  End If
                  If Not IsNothing(ISONumVariable.sValue) Then
                     Integer.TryParse(ISONumVariable.sValue, nISO_Num)
                  Else
                     nISO_Num = -1
                  End If
                  If Not IsNothing(ISOSentVariable.sValue) Then
                     Integer.TryParse(ISOSentVariable.sValue, nISO_Sent)
                  Else
                     nISO_Sent = -1
                  End If
                  If Not IsNothing(RunningVariable.sValue) Then
                     Integer.TryParse(RunningVariable.sValue, nRunning)
                  Else
                     nRunning = -1
                  End If
                  If Not IsNothing(MachIndexVariable.sValue) Then
                     Integer.TryParse(MachIndexVariable.sValue, nCurrMachIndex)
                  Else
                     nCurrMachIndex = -1
                  End If
                  'EgtOutLog("Post scrittura variabili lette")
                  ' se indice lavorazione positivo, lo aggiorno
                  If nCurrMachIndex > 0 AndAlso nReset_State = 0 Then
                     m_nMachIndex = nCurrMachIndex
                  End If
                  ' leggo messaggi plc
                  ReadPLCMessages()
                  Num_Axium_PCToolkit.ReadCncMode()
                  'EgtOutLog("Pre lettura posizioni")
                  Num_Axium_PCToolkit.ReadPosition()
                  'EgtOutLog("Post lettura messaggi")
            End Select
            ' se NUM aggiorno stato della macchina
            If CurrentMachine.NCType = NCTypes.NUM_FLEXIUM Then
               Dim OpState As OPStates
               If nStop_State Then
                  OpState = OPStates.Stop
               ElseIf nStart_State Then
                  OpState = OPStates.Start
               Else
                  OpState = OPStates.End
               End If
               If OpState <> Map.refLeftPanelVM.SelOPState.Id Then
                  m_OpStateCallbackDlg(OpState)
               End If
            ElseIf CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER OrElse CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT Then
               Dim OpState As OPStates
               If nReset_State = 1 Then
                  OpState = OPStates.End
               ElseIf nStop_State Then
                  OpState = OPStates.Stop
               ElseIf nStart_State Then
                  OpState = OPStates.Start
               Else
                  OpState = OPStates.End
               End If
               If IsNothing(Map.refLeftPanelVM.SelOPState) OrElse OpState <> Map.refLeftPanelVM.SelOPState.Id Then
                  m_OpStateCallbackDlg(OpState)
               End If
            End If
            ' se TPA e non ancora fatto, preparo variabili barra successiva
            If CurrentMachine.NCType = NCTypes.TPA AndAlso CurrentMachine.Flow = FlowTypes.CONTINUOUS AndAlso m_NextBarId = 0 Then
               SetNextBarVars()
               ' se macchina NUM, non sto gia' spedendo e variabile spedizione me lo permette
            ElseIf (CurrentMachine.NCType = NCTypes.NUM_FLEXIUM AndAlso
                   Not Num_Flexium.bIsTransferActive AndAlso
                   nISO_Sent = 1) OrElse
                   (CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER AndAlso
                   Not Num_Axium_APServer.bIsTransferActive AndAlso
                   nISO_Sent = 1) OrElse
                   (CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT AndAlso
                   Not Num_Axium_PCToolkit.bIsTransferActive AndAlso
                   nISO_Sent = 1) Then
               ' verifico se c'e' un programma da lanciare
               SendNextProgram()
            End If
            ' verifico se scattato stato reset
            If nReset_State <> 0 Then
               ' resetto tutti i programmi
               If Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then Map.refProjectVM.SupervisorMachGroupPanelVM.ResetAllMachGroups()
               ' resetto variabili P
               ProdVariable.sValue = "0"
               MachGroupVariable.sValue = "0"
               PartVariable.sValue = "0"
               StateVariable.sValue = "0"
               'Tpa.RWVariableManager.WriteVar(P_PROD, 0)
               'Tpa.RWVariableManager.WriteVar(P_MACHGROUP, 0)
               'Tpa.RWVariableManager.WriteVar(P_PART, 0)
               'Tpa.RWVariableManager.WriteVar(P_STATE, 0)
               ' cancello tutti i programmi da memoria CN
               If CurrentMachine.NCType = NCTypes.TPA Then
                  RemoveAllProgram() ' rimuovo programma default per pending
               End If
               ' azzero variabile reset
               ResetVariable.sValue = "0"
               'Tpa.remObject.SetVariableCommand(CInt(ISOCNC.Remoting.VariableCommands.WriteVar),
               '                              RWVariableManager.GetReadVarFromName(RESET_STATE).sAddress, "0")
               ' resetto prossima barra e variabili V
               If CurrentMachine.NCType = NCTypes.TPA AndAlso CurrentMachine.Flow = FlowTypes.CONTINUOUS Then
                  m_NextBarId = 0
                  For Index As Integer = 1 To 6
                     Tpa.RWVariableManager.WriteVarByName(VPAR & Index.ToString(), 0)
                  Next
               End If
               Return
               ' se macchina TPA, e' in pending e non sta tagliando alcun pezzo
            ElseIf CurrentMachine.NCType = NCTypes.TPA AndAlso
                   Tpa.opState = MachineOperatingState.Pending AndAlso
                   Tpa.remObject.MachineOperativeStatus = MachineOperatingState.Pending AndAlso
                   (nP_Prod = 0 AndAlso
                    nP_Machgroup = 0 AndAlso
                    nP_Part = 0 AndAlso
                    nP_State = PartState.NULL) Then
               ' verifico se c'e' un programma da lanciare
               SendNextProgram()
               ' attesa per essere sicuro che abbia scritto e riletto variabili
               Threading.Thread.Sleep(300)
               ' verifico stati inizio e fine pezzi
            ElseIf nP_Prod <> 0 AndAlso
                   nP_Machgroup <> 0 AndAlso
                   nP_Part <> 0 Then
               If nP_State = PartState.START Then
                  Dim dtStart As DateTime = DateTime.Now()
                  ' recupero gruppo di lavorazione del pezzo
                  Dim MachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) x.Id = nP_Machgroup)
                  ' se pezzo = -1 devo dare start a tutti i pezzi del MachGroup
                  If nP_Part = -1 Then
                     If Not IsNothing(MachGroup) Then
                        For Each Part In MachGroup.PartVMList
                           ' scrivo data start su Db pezzo
                           DbControllers.m_PartController.UpdateStart(nP_Prod, nP_Machgroup, Part.nPartId, dtStart)
                           DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, Part.nPartId, ItemState.WIP)
                           ' scrivo stato start
                           Part.nProduction_State = ItemState.WIP
                           Part.dtStartTime = dtStart
                           Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
                           ' scrivo evento inizio pezzo su DB
                           DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(dtStart, nP_Prod, nP_Machgroup, Part.nPartId, nP_State, DbControllers.SupervisorId))
                        Next
                     End If
                  Else
                     ' scrivo data start su Db pezzo
                     DbControllers.m_PartController.UpdateStart(nP_Prod, nP_Machgroup, nP_Part, dtStart)
                     DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, nP_Part, ItemState.WIP)
                     If Not IsNothing(MachGroup) Then
                        ' recupero pezzo
                        Dim Part As PartVM = MachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nP_Part)
                        If Not IsNothing(Part) Then
                           ' scrivo stato start
                           Part.nProduction_State = ItemState.WIP
                           Part.dtStartTime = dtStart
                           Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
                        End If
                     End If
                     ' scrivo evento inizio pezzo su DB
                     DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(dtStart, nP_Prod, nP_Machgroup, nP_Part, nP_State, DbControllers.SupervisorId))
                  End If
                  ' azzero variabile per far ripartire macchina
                  Select Case CurrentMachine.NCType
                     Case NCTypes.TPA
                        Tpa.RWVariableManager.WriteVarByName(P_STATE, 0)
                     Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
                        StateVariable.sValue = "0"
                  End Select
                  ' se nessun pezzo della barra diverso da quello corrente e' in start
                  If Not MachGroup.PartVMList.Any(Function(x) x.nPartId <> nP_Part AndAlso x.nProduction_State = 1) Then
                     ' scrivo data start su Db barra
                     DbControllers.m_MachGroupController.UpdateStart(nP_Prod, nP_Machgroup, dtStart)
                     DbControllers.m_MachGroupController.UpdateStatus(nP_Prod, nP_Machgroup, ItemState.WIP)
                     ' scrivo stato start
                     If Not IsNothing(MachGroup) Then
                        MachGroup.MyMachGroupM.SetProductionState(ItemState.WIP)
                        MachGroup.dtStartTime = dtStart
                        MachGroup.NotifyPropertyChanged(NameOf(MachGroup.nProduction_State))
                     End If
                     ' scrivo evento inizio MachGroup su DB
                     DbControllers.m_LogMachineController.Create(LogEvent.CreateMachGroupStateLog(dtStart, nP_Prod, nP_Machgroup, nP_State, DbControllers.SupervisorId))
                  End If
                  ' flag di aggiornamento log macchina
                  Map.refMachineLogPageVM.UpdateMachineLogList(False)
                  ' attesa per essere sicuro che abbia scritto e riletto variabili
                  Threading.Thread.Sleep(300)
               ElseIf nP_State = PartState.END_ Then
                  Dim dtEnd As DateTime = DateTime.Now()
                  ' recupero gruppo di lavorazione del pezzo
                  Dim MachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) x.Id = nP_Machgroup)
                  ' se pezzo = -1 devo dare end a tutti i pezzi del MachGroup
                  If nP_Part = -1 Then
                     If Not IsNothing(MachGroup) Then
                        For Each Part In MachGroup.PartVMList
                           ' scrivo data end su Db pezzo
                           DbControllers.m_PartController.UpdateEnd(nP_Prod, nP_Machgroup, Part.nPartId, dtEnd)
                           DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, Part.nPartId, ItemState.Produced)
                           ' scrivo stato end
                           Part.nProduction_State = ItemState.Produced
                           Part.dtEndTime = dtEnd
                           Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
                           ' resetto stato redo
                           Part.bRedo = False
                           ' se non impostata data start
                           If Part.dtStartTime = DateTime.MinValue Then
                              ' scrivo data start su Db pezzo
                              Dim dtStart As DateTime = Part.dtEndTime - TimeSpan.FromSeconds(60)
                              DbControllers.m_PartController.UpdateStart(nP_Prod, nP_Machgroup, Part.nPartId, dtStart)
                              Part.dtStartTime = dtStart
                           End If
                           ' scrivo evento fine pezzo su DB
                           DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(dtEnd, nP_Prod, nP_Machgroup, Part.nPartId, nP_State, DbControllers.SupervisorId))
                        Next
                     End If
                  Else
                     ' scrivo data end su Db pezzo
                     DbControllers.m_PartController.UpdateEnd(nP_Prod, nP_Machgroup, nP_Part, dtEnd)
                     DbControllers.m_PartController.UpdateStatus(nP_Prod, nP_Machgroup, nP_Part, ItemState.Produced)
                     If Not IsNothing(MachGroup) Then
                        ' recupero pezzo
                        Dim Part As PartVM = MachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nP_Part)
                        If Not IsNothing(Part) Then
                           ' scrivo stato end
                           Part.nProduction_State = ItemState.Produced
                           Part.dtEndTime = dtEnd
                           Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
                           ' resetto stato redo
                           Part.bRedo = False
                        End If
                     End If
                     ' scrivo evento fine pezzo su DB
                     DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(dtEnd, nP_Prod, nP_Machgroup, nP_Part, nP_State, DbControllers.SupervisorId))
                  End If

                  ' se tutti i pezzi della barra sono in end
                  If Not IsNothing(MachGroup) AndAlso MachGroup.PartVMList.All(Function(x) x.nProduction_State >= 2) Then
                     ' scrivo data end su Db barra
                     DbControllers.m_MachGroupController.UpdateEnd(nP_Prod, nP_Machgroup, dtEnd)
                     DbControllers.m_MachGroupController.UpdateStatus(nP_Prod, nP_Machgroup, ItemState.Produced)
                     ' scrivo stato end
                     MachGroup.MyMachGroupM.SetProductionState(ItemState.Produced)
                     MachGroup.dtEndTime = dtEnd
                     MachGroup.NotifyPropertyChanged(NameOf(MachGroup.nProduction_State))
                     ' scrivo evento fine MachGroup su DB
                     DbControllers.m_LogMachineController.Create(LogEvent.CreateMachGroupStateLog(dtEnd, nP_Prod, nP_Machgroup, nP_State, DbControllers.SupervisorId))
                     ' azzero tutte le variabilli per iniziare barra successiva
                     ProdVariable.sValue = "0"
                     MachGroupVariable.sValue = "0"
                     PartVariable.sValue = "0"
                     StateVariable.sValue = "0"

                     ' se non impostata data start
                     If MachGroup.dtStartTime = DateTime.MinValue Then
                        ' EgtOutLog("Start date not set on Prod " & nP_Prod & " Machgroup " & nP_Machgroup)
                        Dim dtStart As DateTime = MachGroup.dtEndTime - TimeSpan.FromSeconds(60)
                        ' provo a recuperare tempo stimato
                        If MachGroup.nCALC_TIME > 0 Then
                           Dim MinPartStart As DateTime = MachGroup.PartVMList.Min(Function(x) x.dtStartTime)
                           If MinPartStart > DateTime.MinValue Then
                              dtStart = New DateTime(Math.Min((MachGroup.dtEndTime - TimeSpan.FromSeconds(MachGroup.nCALC_TIME)).Ticks, MinPartStart.Ticks))
                           Else
                              dtStart = MachGroup.dtEndTime - TimeSpan.FromSeconds(MachGroup.nCALC_TIME)
                           End If
                        End If
                        ' scrivo data start su Db barra
                        DbControllers.m_MachGroupController.UpdateStart(nP_Prod, nP_Machgroup, dtStart)
                        MachGroup.dtStartTime = dtStart
                     End If
                     ' resetto stati di produzione
                     MachGroup.ResetProduce()
                     ' se partenza pezzi uno a uno
                     If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
                        ' riattivo bottone produzione per tutti gli altri
                        MyMachGroupVM.UpdateProduceIsEnabledForAll()
                     End If
                  Else
                     ' azzero variabile per far ripartire macchina
                     StateVariable.sValue = "0"
                  End If
                  ' se pezzo = -1 stampo etichette di tutti i pezzi del MachGroup
                  If nP_Part = -1 Then
                     If Not IsNothing(MachGroup) Then
                        For Each Part In MachGroup.PartVMList
                           Map.refLeftPanelVM.PrintLabel(MachGroup, Part)
                        Next
                     End If
                  Else
                     ' recupero pezzo
                     Dim Part As PartVM = MachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nP_Part)
                     If Not IsNothing(Part) Then
                        Map.refLeftPanelVM.PrintLabel(MachGroup, Part)
                     End If
                  End If
                  ' flag di aggiornamento log macchina
                  Map.refMachineLogPageVM.UpdateMachineLogList(False)
                  ' attesa per essere sicuro che abbia scritto e riletto variabili
                  Threading.Thread.Sleep(300)
               End If
            End If

      End Select

   End Sub

   Private m_Lock_SendProgram As New Object

   Private Function SetNextBarVars() As Boolean
      ' verifico se c'e' un programma da lanciare
      If Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
         For Each MyMachGroup As MyMachGroupVM In Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList
            If Not MyMachGroup.bSentToMachine AndAlso MyMachGroup.dtStartTime = DateTime.MinValue Then
               If MyMachGroup.bReadyForMachining Then
                  ' leggo valori parametri V da file
                  Dim dVPars(10) As Double
                  Dim Lines() As String = File.ReadAllLines(MyMachGroup.CnFilePath())
                  Dim sVs() As String = Lines(0).Split(";"c)
                  For VParIndex = 1 To sVs.Length - 1
                     Dim VPar() As String = sVs(VParIndex).Split("="c)
                     VPar(1) = VPar(1).Trim
                     StringToDoubleAdv(VPar(1), dVPars(VParIndex - 1))
                  Next
                  ' li scrivo nel CN
                  For Index As Integer = 1 To 10
                     Dim sValue As String = ""
                     sValue = DoubleToString(dVPars(Index - 1), 2)
                     Tpa.RWVariableManager.WriteVarByName(VPAR & Index.ToString(), sValue)
                  Next
                  m_NextBarId = MyMachGroup.Id
                  Return True
               Else
                  Return False
               End If
            End If
         Next
      End If
      Return False
   End Function

   Private Function SendNextProgram() As Boolean
      ' EgtOutLog("Inizio SendNextProgram")
      Dim bSent As Boolean = False
      If (CurrentMachine.NCType = NCTypes.TPA AndAlso Not m_bStartPending AndAlso Tpa.opState = MachineOperatingState.Pending) OrElse
         (CurrentMachine.NCType = NCTypes.NUM_FLEXIUM AndAlso Not Num_Flexium.bIsTransferActive) OrElse
         (CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER AndAlso Not Num_Axium_APServer.bIsTransferActive) OrElse
         (CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT AndAlso Not Num_Axium_PCToolkit.bIsTransferActive) Then ' Or Tpa.opState = MachineOperatingState.Start) Then
         ' verifico se c'e' un programma da lanciare
         If Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
            ' EgtOutLog("Start " & DateTime.Now())
            Dim bMachGroupNotReady As Boolean = False
            SyncLock m_Lock_SendProgram
               For Each MyMachGroup As MyMachGroupVM In Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList
                  ' EgtOutLog("Ciclo su name: " & MyMachGroup.Name & " id: " & MyMachGroup.Id)
                  If Not MyMachGroup.bSentToMachine AndAlso (MyMachGroup.dtStartTime = DateTime.MinValue OrElse
                     (Map.refSupervisorManagerVM.CurrProd.nType = BWType.WALL AndAlso MyMachGroup.bResetWhileCutting)) Then
                     ' EgtOutLog(MyMachGroup.Name & " id: " & MyMachGroup.Id & " è da fare")
                     ' verifico se ricalcolo finito
                     If MyMachGroup.bReadyForMachining AndAlso If(CurrentMachine.NCType = NCTypes.NUM_FLEXIUM Or CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER OrElse CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT, Not MyMachGroup.bSendingToMachine, True) Then
                        ' EgtOutLog(MyMachGroup.Name & " id: " & MyMachGroup.Id & " pronto per essere lavorato")
                        ' lo lancio
                        bSent = SendProgram(MyMachGroup.CnFilePath(), MyMachGroup.Name)
                        ' EgtOutLog(MyMachGroup.Name & " id: " & MyMachGroup.Id & " mandato " & DateTime.Now() & " " & MyMachGroup.Name & " " & bSent.ToString())
                        Select Case CurrentMachine.NCType
                           Case NCTypes.TPA
                              MyMachGroup.SetSentToMachine(bSent)
                           Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
                              MyMachGroup.SetSendingToMachine(bSent)
                        End Select
                        m_NextBarId = 0
                        Exit For
                     Else
                        ' programma non ancora pronto, esco per attendere
                        bMachGroupNotReady = True
                        ' EgtOutLog(MyMachGroup.Name & " id: " & MyMachGroup.Id & " non ancora pronto per essere mandato")
                        Exit For
                        'Return False
                     End If
                  End If
               Next
            End SyncLock
            If bMachGroupNotReady Then Return False
            ' EgtOutLog("End " & DateTime.Now())
         End If
      End If
      Return bSent
   End Function

   Private Sub CommandList_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
      If Not IsNothing(e.NewItems) Then
         ' EgtOutLog("Inizio ciclo esecuzione comandi")
         Dim nCommandCount As Integer = e.NewItems.Count
         For CommandIndex = 0 To nCommandCount - 1
            Dim Command As ThreadCommand = e.NewItems(CommandIndex)
            If Command.ProcessingStatus = ThreadCommand.ProcessingStatuses.WAITING Then
               Command.SetProcessingStatus(ThreadCommand.ProcessingStatuses.PROCESSING)
               ExecuteCommand(DirectCast(Command, ThreadCommand))
               Command.SetProcessingStatus(ThreadCommand.ProcessingStatuses.DONE)
            End If
         Next
         ' EgtOutLog("Fine ciclo esecuzione di " & nCommandCount & " comandi")
      End If
   End Sub

   Private Sub ExecuteCommand(Command As ThreadCommand)
      Select Case Command.CommandType
         Case CommandTypes.CONNECT
            Connect()
         Case CommandTypes.DISCONNECT
            Disconnect()
         Case CommandTypes.START
            Start()
         Case CommandTypes.STOP_
            [Stop]()
         Case CommandTypes.RESET
            Reset()
         Case CommandTypes.STEP_
            Step_()
         Case CommandTypes.SETPOINT
            SetPoint()
         Case CommandTypes.SENDPROG
            SendProgram(Command.sVariable, Command.sVariables(1))
         Case CommandTypes.REMOVEPROG
            RemoveProgram(Command.nVariable, Command.sVariable, Command.sVariables(1))
         Case CommandTypes.REMOVEALLPROG
            RemoveAllProgram()
         Case CommandTypes.READ_TPA
            Tpa.RWVariableManager.RefreshVar(Command.sVariable)
         Case CommandTypes.WRITE
            'EgtOutLog("Write" & Command.sVariable & " " & Command.sVariables(1) & " " & Command.nVariable)
            WriteVar(Command.sVariable, Command.sVariables(1), Command.nVariable)
         Case CommandTypes.DELETEALARMS
            DeleteAlarms()
         Case CommandTypes.SETOPMODE
            SetOPState(Command.nVariable)
         Case CommandTypes.READ_NUMFLEXIUM
            Num_Flexium.StartReadList()
            Num_Flexium.StartReadELS()
         Case CommandTypes.STOPREAD_NUMFLEXIUM
            Num_Flexium.CloseReadList()
            Num_Flexium.CloseReadELS()
         Case CommandTypes.MDI
            SendMDI(Command.sVariable)
         Case CommandTypes.SETCHANNEL
            SetChannel(Command.nVariable)
      End Select
   End Sub

   Public Sub Connect()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Try
               m_CN = New TPAComm(Me)
               m_bConnected = Tpa.remObject.OnConnect()
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
               ' imposto stato manuale
               Dim ManualMode As OPState = Map.refLeftPanelVM.OPModeList.FirstOrDefault(Function(x) x.Id = OPModes.Manual)
               Map.refLeftPanelVM.SetOPMode(ManualMode)
               ' creo classe di gestione variabili
            Catch ex As Exception
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.ERROR_, ResultTypes.EXECUTED, "Errore: impossibile connettersi!")
               Return
            End Try
         Case NCTypes.NUM_FLEXIUM
            Try
               m_CN = New NUMFlexiumComm(Me)
               Num_Flexium.InitFxServer()
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
               ' creo classe di gestione variabili
            Catch ex As Exception
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.ERROR_, ResultTypes.EXECUTED, "Errore: impossibile connettersi!")
               Return
            End Try
         Case NCTypes.NUM_AXIUM_APSERVER
            Try
               m_CN = New NUMAxiumComm(Me)
               Num_Axium_APServer.InitFxObjects()
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
               ' creo classe di gestione variabili
            Catch ex As Exception
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.ERROR_, ResultTypes.EXECUTED, "Errore: impossibile connettersi!")
               Return
            End Try
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Try
               m_CN = New NUMAxiumPcToolkitComm(Me)
               If Num_Axium_PCToolkit.InitConnection() Then
                  Num_Axium_PCToolkit.GetGeneralFunctions()
                  m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
               Else
                  m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.ERROR_, ResultTypes.EXECUTED, "Errore: impossibile connettersi!")
                  Return
               End If
               ' creo classe di gestione variabili
            Catch ex As Exception
               m_ResultCallbackDlg(CommandTypes.CONNECT, CommandStates.ERROR_, ResultTypes.EXECUTED, "Errore: impossibile connettersi!")
               Return
            End Try
      End Select
   End Sub

   Public Sub Disconnect()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = Tpa.remObject.OnClose()
            m_bConnected = Not bOk
            m_ResultCallbackDlg(CommandTypes.DISCONNECT, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
            ' chiudo classe Tpa
            Me.OnDispose()
            Tpa.OnDispose()
         Case NCTypes.NUM_FLEXIUM
            m_bConnected = False
            m_ResultCallbackDlg(CommandTypes.DISCONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
            ' chiudo classe Num_Flexium
            Me.OnDispose()
            'Num_Flexium.OnDispose()
         Case NCTypes.NUM_AXIUM_APSERVER
            m_bConnected = False
            Num_Axium_APServer.CloseFxObjects()
            m_ResultCallbackDlg(CommandTypes.DISCONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
            ' chiudo classe Num_Flexium
            Me.OnDispose()
            'Num_Flexium.OnDispose()
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            m_bConnected = False
            Num_Axium_PCToolkit.CloseFxObjects()
            m_ResultCallbackDlg(CommandTypes.DISCONNECT, CommandStates.OK, ResultTypes.EXECUTED, "")
            ' chiudo classe Num_Flexium
            Me.OnDispose()
            'Num_Flexium.OnDispose()
      End Select
      ' termino thread di comunicazione
      MachineCommThread.StopThread()
   End Sub

   Public Sub SetOPState(CNMode As NUMFlexiumComm.CNMode)
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.SetMode(CNMode)
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.SetMode(CNMode)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.SetMode(CNMode)
      End Select
   End Sub

   Public Sub Start()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean
            ' imposto programma default.iso
            If Tpa.opState = MachineOperatingState.End OrElse Tpa.opState = MachineOperatingState.Unspecified Then
               Tpa.remObject.RemoveAllProgramsFromList()
               Dim bFileOk As Boolean = False
               Dim DefaultIsoFilePath As String = "C:\Albatros\system\DEFAULT.iso"
               ' verifico se esiste path
               Try
                  If File.Exists(DefaultIsoFilePath) Then bFileOk = True
               Catch ex As Exception
                  bFileOk = False
               End Try
               If Not bFileOk Then
                  Try
                     File.Copy(Map.refMainWindowVM.MainWindowM.sMachineMacroDir & "\" & "DEFAULT.ISO", DefaultIsoFilePath)
                     bFileOk = True
                  Catch ex As Exception
                     m_ResultCallbackDlg(CommandTypes.START, CommandStates.ERROR_, ResultTypes.NULL, "Error in copying DEFAULT.ISO file")
                     MessageBox.Show("Impossibile copiare il file DEFAULT.ISO!", "Error", MessageBoxButton.OK, MessageBoxImage.Error)
                     Return
                  End Try
               End If
               'ProgramPath = ProgramPath.Replace("\\", "\")
               bOk = Tpa.remObject.AddProgramToList(DefaultIsoFilePath)
               Threading.Thread.Sleep(1000)
               bOk = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.Start))
               m_ResultCallbackDlg(CommandTypes.START, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "DEFAULT.ISO send")
            End If
            bOk = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.Start))
            m_bStartPending = bOk
            m_ResultCallbackDlg(CommandTypes.START, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.Start()
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.Start()
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.Start()
      End Select
      ' aggiorno stato bottoni in LeftPanel
      Map.refLeftPanelVM.UpdateButtonIsEnabledState()
   End Sub

   Public Sub [Stop]()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.[Stop]))
            m_ResultCallbackDlg(CommandTypes.STOP_, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.Stop_()
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.Stop_()
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.Stop_()
      End Select
   End Sub

   Public Sub Reset()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.[End]))
            m_ResultCallbackDlg(CommandTypes.RESET, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.Reset()
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.Reset()
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.Reset()
      End Select
      ' aggiorno stato bottoni in LeftPanel
      Map.refLeftPanelVM.UpdateButtonIsEnabledState()
   End Sub

   Public Sub Step_()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.Step))
            m_ResultCallbackDlg(CommandTypes.STEP_, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
         Case NCTypes.NUM_FLEXIUM
            ''
      End Select
   End Sub

   Public Sub SetPoint()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.SetPoint))
            m_ResultCallbackDlg(CommandTypes.SETPOINT, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
         Case NCTypes.NUM_FLEXIUM
            Map.refLeftPanelVM.SelOPMode = Map.refLeftPanelVM.OPModeList.Find(Function(x) x.Id = OPModes.Home)
         Case NCTypes.NUM_AXIUM_APSERVER
            Map.refLeftPanelVM.SelOPMode = Map.refLeftPanelVM.OPModeList.Find(Function(x) x.Id = OPModes.Home)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Map.refLeftPanelVM.SelOPMode = Map.refLeftPanelVM.OPModeList.Find(Function(x) x.Id = OPModes.Home)
      End Select
   End Sub

   Public Function SendProgram(ProgramPath As String, ProgramId As String) As Boolean
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            If Tpa.opState = MachineOperatingState.Pending Then
               Tpa.remObject.RemoveAllProgramsFromList()
               Dim bOk As Boolean = False
               ProgramPath = ProgramPath.Replace("\\", "\")
               bOk = Tpa.remObject.AddProgramToList(ProgramPath)
               Threading.Thread.Sleep(1000)
               bOk = Tpa.remObject.SetCommand(CInt(ISOCNC.Remoting.Commands.Start_Program_Soft))
               m_ResultCallbackDlg(CommandTypes.SENDPROG, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
               Return bOk
            End If
            Return False
         Case NCTypes.NUM_FLEXIUM
            Dim sFileType As String = "%" & ProgramId.ToString()
            Num_Flexium.FileDownload(sFileType, ProgramPath)
            Num_Flexium.StartTransfer()
            Return True
         Case NCTypes.NUM_AXIUM_APSERVER
            Dim sFileType As String = "%" & ProgramId.ToString()
            Num_Axium_APServer.FileDownload(sFileType, ProgramPath)
            Num_Axium_APServer.StartTransfer()
            Return True
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            ' EgtOutLog("Pre Download")
            Dim nFileType As Integer = 0
            If Integer.TryParse(ProgramId, nFileType) AndAlso nFileType > 0 Then
               Num_Axium_PCToolkit.FileDownload(nFileType * 10, ProgramPath)
            End If
            Return True
      End Select
      Return False
   End Function

   Public Sub RemoveProgram(ProgramIndex As Integer, ProgramPath As String, ProgramType As String)
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean
            Dim sError As String = ""
            If ProgramIndex > 0 Then
               bOk = CN.remObject.RemoveProgramFromListAtIndex(ProgramIndex)
            ElseIf Not String.IsNullOrEmpty(ProgramPath) Then
               bOk = CN.remObject.RemoveProgramFromList(ProgramPath)
            Else
               bOk = False
               sError = "Errore: nessun parametro passato"
            End If
            m_ResultCallbackDlg(CommandTypes.REMOVEPROG, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, sError)
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.FileDelete(ProgramType, ProgramPath)
            Num_Flexium.StartTransfer()
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.FileDelete(ProgramType, ProgramPath)
            Num_Axium_APServer.StartTransfer()
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.FileDelete(ProgramType, ProgramPath)
      End Select
   End Sub

   Public Sub RemoveAllProgram()
      Dim bOk As Boolean = CN.remObject.RemoveAllProgramsFromList()
      m_ResultCallbackDlg(CommandTypes.REMOVEALLPROG, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
   End Sub

   Public Sub DeleteAlarms()
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Dim bOk As Boolean = CN.remObject.DeleteAlarms(CInt(AlarmType.ISO))
            bOk = CN.remObject.DeleteAlarms(CInt(AlarmType.Message))
            bOk = CN.remObject.DeleteAlarms(CInt(AlarmType.Cycle))
            bOk = CN.remObject.DeleteAlarms(CInt(AlarmType.System))
            m_ResultCallbackDlg(CommandTypes.DELETEALARMS, If(bOk, CommandStates.OK, CommandStates.ERROR_), ResultTypes.EXECUTED, "")
      End Select
   End Sub

   Public Sub SetChannel(value As Integer)
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.SetChannel(value)
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.SetChannel(value)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.SetChannel(value)
      End Select
   End Sub

   Public Sub SendMDI(value As String)
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_FLEXIUM
            Num_Flexium.MDI_Execute(value)
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.MDI_Execute(value)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.MDI_Execute(value)
      End Select
   End Sub

   Public Sub WriteVar(Address As String, Value As String, Type As CommVar.Types)
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Tpa.RWVariableManager.WriteVarByAddress(Address, Value)
         Case NCTypes.NUM_FLEXIUM
            Select Case Type
               Case CommVar.Types.PLC
                  Num_Flexium.WritePlcVariables(Address, Value)
               Case CommVar.Types.CN
                  Num_Flexium.WriteNCVariables(Address, Value)
            End Select
         Case NCTypes.NUM_AXIUM_APSERVER
            Select Case Type
               Case CommVar.Types.PLC
                  Num_Axium_APServer.WritePlcVariables(Address, Value)
               Case CommVar.Types.CN
                  Num_Axium_APServer.WriteNCVariables(Address, Value)
            End Select
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Select Case Type
               Case CommVar.Types.PLC
                  Num_Axium_PCToolkit.WritePlcVariables(Address, Value)
               Case CommVar.Types.CN
                  Num_Axium_PCToolkit.WriteNCVariables(Address, Value)
            End Select
      End Select
   End Sub

   Public Shared Function InitVar(Section As String, nIndex As Integer) As CommVar
      Dim NewVar As CommVar = GetPrivateProfileVariable(Section, nIndex, CurrentMachine.sMachIniFile)
      If IsNothing(NewVar) Then Return Nothing
      Select Case CurrentMachine.NCType
         Case NCTypes.TPA
            Return RWVariableManager.InitVar(NewVar)
         Case NCTypes.NUM_FLEXIUM
            Return NUMFlexiumComm.InitVar(NewVar)
         Case NCTypes.NUM_AXIUM_APSERVER
            Return NUMAxiumComm.InitVar(NewVar)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Return NUMAxiumPcToolkitComm.InitVar(NewVar)
      End Select
      Return Nothing
   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)
      If String.IsNullOrWhiteSpace(sVariable) Then Return Nothing
      Dim sVariableValues() As String = sVariable.Split(","c)
      'If Not sVariableValues.Count >= 4 Then Return Nothing
      For Index As Integer = 0 To sVariableValues.Count - 1
         sVariableValues(Index) = sVariableValues(Index).Trim()
      Next
      Dim ReadType As CommVar.ReadTypes
      Select Case sVariableValues(2).ToLower()
         Case "o"
            ReadType = CommVar.ReadTypes.ONETIME
         Case "c"
            ReadType = CommVar.ReadTypes.CONTINUOUS
         Case Else
            ReadType = CommVar.ReadTypes.NULL
      End Select
      Dim Type As CommVar.Types
      Select Case sVariableValues(3).ToLower()
         Case "plc"
            Type = CommVar.Types.PLC
         Case "cn"
            Type = CommVar.Types.CN
         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
      Dim sDescription As String = ""
      If sVariableValues.Length >= 5 Then
         Dim nDescription As Integer
         If Integer.TryParse(sVariableValues(4), nDescription) Then
            Dim MsgParagraph As MsgParagraphs
            Select Case Paragraph
               Case Paragraphs.INPUT
                  MsgParagraph = MsgParagraphs.INPUT
               Case Paragraphs.OUTPUT
                  MsgParagraph = MsgParagraphs.OUTPUT
               Case Else
                  MsgParagraph = MsgParagraphs.INPUT
            End Select
            sDescription = MachMsg(MsgParagraph, nDescription)
         Else
            sDescription = sVariableValues(4)
         End If
      End If
      Return New CommVar(sVariableValues(0), sVariableValues(1), ReadType, Type, Paragraph, sDescription)
   End Function

   Private Sub ReadPLCMessages()
      Dim nPlc_Msg(5) As Integer
      For Index As Integer = 1 To 6
         Dim nIndex As Integer = Index
         Dim PLCMessagesVariable As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = PLC_MESSAGES & nIndex)
         If IsNothing(PLCMessagesVariable) OrElse IsNothing(PLCMessagesVariable.sValue) Then Return
         Dim nTemp As Integer = 0
         Integer.TryParse(PLCMessagesVariable.sValue, nTemp)
         Dim Bytes As Byte() = BitConverter.GetBytes(nTemp)
         Dim NewBytes As Byte() = BitConverter.GetBytes(nTemp)
         For nBIndex = Bytes.Count - 1 To 0 Step -1
            NewBytes(Bytes.Count - 1 - nBIndex) = Bytes(nBIndex)
         Next
         Dim Res = BitConverter.ToInt32(NewBytes, 0)
         nPlc_Msg(nIndex - 1) = Res
      Next
      Dim BitArray As New BitArray(nPlc_Msg)
      Dim ErrorList As New List(Of Integer)
      For BitIndex = 0 To BitArray.Count - 1
         If BitIndex <= 169 AndAlso BitArray(BitIndex) Then
            ErrorList.Add(BitIndex)
         End If
      Next
      Select Case CurrentMachine.NCType
         Case NCTypes.NUM_AXIUM_APSERVER
            Num_Axium_APServer.objErrorHandler_ErrorFromActiveCnc2(ErrorList)
         Case NCTypes.NUM_AXIUM_PCTOOLKIT
            Num_Axium_PCToolkit.objErrorHandler_ErrorFromActiveCnc2(ErrorList)
      End Select
   End Sub

End Class
