Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Globalization
Imports System.IO
Imports System.Windows.Threading
Imports EgtBEAMWALL.Core
Imports EgtUILib
Imports EgtWPFLib5

Public Class LeftPanelVM
   Inherits VMBase

#Region "FIELDS & PROPERTIES"

   Private m_PrintTimer As New DispatcherTimer

   Private Property m_GridDims As New ObservableCollection(Of GridDimension)
   Public Property GridDims As ObservableCollection(Of GridDimension)
      Get
         Return m_GridDims
      End Get
      Set
         m_GridDims = Value
         NotifyPropertyChanged(NameOf(GridDims))
      End Set
   End Property

   Private m_ChannelList As List(Of IdNameStruct)
   Public Property ChannelList As List(Of IdNameStruct)
      Get
         Return m_ChannelList
      End Get
      Set(ByVal value As List(Of IdNameStruct))
         m_ChannelList = value
      End Set
   End Property

   Private m_SelChannel As IdNameStruct
   Public Property SelChannel As IdNameStruct
      Get
         Return m_SelChannel
      End Get
      Set(ByVal value As IdNameStruct)
         MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.SETCHANNEL, value.Id))
         m_SelChannel = value
      End Set
   End Property
   Friend Sub SetChannel(value As IdNameStruct)
      m_SelChannel = value
      NotifyPropertyChanged(NameOf(SelChannel))
   End Sub

   Private m_OPStateList As List(Of OPState)
   Public Property OPStateList As List(Of OPState)
      Get
         Return m_OPStateList
      End Get
      Set(ByVal value As List(Of OPState))
         m_OPStateList = value
      End Set
   End Property

   Private m_SelOPState As OPState
   Public ReadOnly Property SelOPState As OPState
      Get
         Return m_SelOPState
      End Get
   End Property
   Friend Sub SetOPState(value As OPState)
      m_SelOPState = value
      NotifyPropertyChanged(NameOf(SelOPState))
   End Sub

   Private m_OPModeList As List(Of OPState)
   Public Property OPModeList As List(Of OPState)
      Get
         Return m_OPModeList
      End Get
      Set(ByVal value As List(Of OPState))
         m_OPModeList = value
      End Set
   End Property

   Private m_SelOPMode As OPState
   Public Property SelOPMode As OPState
      Get
         Return m_SelOPMode
      End Get
      Set(ByVal value As OPState)
         MachManaging.AddToCommandList(ThreadCommand.CreateCommand(CommandTypes.SETOPMODE, value.Id))
         ' se MDI
         If value.Id = OPModes.Mdi Then
            ' mostro pagina comandi MDI
            Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.MDI)
         ElseIf Map.refCALCPanelVM.bMachineLog Then
            ' mostro log macchina
            Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.MACHINELOG)
         Else
            ' mostro scena
            Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.SCENE)
         End If
         m_SelOPMode = value
      End Set
   End Property
   Friend Sub SetOPMode(value As OPState)
      ' se MDI
      If value.Id = OPModes.Mdi Then
         ' mostro pagina comandi MDI
         Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.MDI)
      ElseIf Map.refCALCPanelVM.bMachineLog Then
         ' mostro log macchina
         Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.MACHINELOG)
      Else
         ' mostro scena
         Map.refProjectVM.SetSelTabPage(ProjectVM.TabPages.SCENE)
      End If
      m_SelOPMode = value
      NotifyPropertyChanged(NameOf(SelOPMode))
   End Sub
   Public ReadOnly Property sE80000 As String
      Get
         Dim MachIndexVar As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = MACHINDEX)
         Return If(IsNothing(MachIndexVar), "", MachIndexVar.sValue)
      End Get
   End Property
   Public ReadOnly Property sE80001 As String
      Get
         Dim ToolIndexVar As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = TOOLINDEX)
         Return If(IsNothing(ToolIndexVar), "", ToolIndexVar.sValue)
      End Get
   End Property
   Public ReadOnly Property sE80002 As String
      Get
         Dim ToolIndex2Var As Variable = Map.refMachCommandMessagePanelVM.MainVariablesList.FirstOrDefault(Function(x) x.sName = TOOLINDEX2)
         Return If(IsNothing(ToolIndex2Var), "", ToolIndex2Var.sValue)
      End Get
   End Property
   Public Property m_E80000_Visibility As Visibility
   Public ReadOnly Property E80000_Visibility As Visibility
      Get
         Return m_E80000_Visibility
      End Get
   End Property
   Public Property m_E80002_Visibility As Visibility
   Public ReadOnly Property E80002_Visibility As Visibility
      Get
         Return m_E80002_Visibility
      End Get
   End Property

   Private m_bRestart As Boolean = False
   Public Property bRestart As Boolean
      Get
         Return m_bRestart
      End Get
      Set(value As Boolean)
         m_bRestart = value
         If value Then
            If Not IsNothing(Map.refPartInRawPartListVM.colPartInRawPart_Redo) Then
               Map.refPartInRawPartListVM.colPartInRawPart_Redo.ColumnVisibility = Visibility.Visible
            End If
            If Not IsNothing(Map.refFeatureInPartInRawPartListVM.colFeatureInPartInRawPart_Redo) Then
               Map.refFeatureInPartInRawPartListVM.colFeatureInPartInRawPart_Redo.ColumnVisibility = Visibility.Visible
            End If
            ' disabilito interfaccia
            Map.refProjectVM.ManageIsEnabled(False)
         Else
            If Not IsNothing(Map.refPartInRawPartListVM.colPartInRawPart_Redo) Then
               Map.refPartInRawPartListVM.colPartInRawPart_Redo.ColumnVisibility = Visibility.Collapsed
            End If
            If Not IsNothing(Map.refFeatureInPartInRawPartListVM.colFeatureInPartInRawPart_Redo) Then
               Map.refFeatureInPartInRawPartListVM.colFeatureInPartInRawPart_Redo.ColumnVisibility = Visibility.Collapsed
            End If
            ' riabilito interfaccia
            Map.refProjectVM.ManageIsEnabled(True)
         End If
         NotifyPropertyChanged(NameOf(FeatureList_Visibility))
      End Set
   End Property

   Public ReadOnly Property FeatureList_Visibility As Visibility
      Get
         Return If(m_bRestart, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Private m_LeftPanel_IsEnabled As Boolean = True
   Public ReadOnly Property LeftPanel_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled
      End Get
   End Property

   Public ReadOnly Property MoveRawPart_IsEnabled As Boolean
      Get
         If IsNothing(Map.refProjectVM) OrElse IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
            Return False
         ElseIf m_SelOPState.Id <> OPStates.End AndAlso m_SelOPState.Id <> OPStates.Unspecified Then
            Return False
         ElseIf IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Return False
         ElseIf Map.refRawPartListVM.bRawPartListSorted Then
            Return False
         ElseIf Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Dim SelMachgroup As MyMachGroupVM = DirectCast(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup, MyMachGroupVM)
            Return SelMachgroup.nProduction_State <= ItemState.Confirmed AndAlso Not SelMachgroup.bToBeProduced
         Else
            Return m_LeftPanel_IsEnabled
         End If
      End Get
   End Property

   Public ReadOnly Property DoneRawPart_IsEnabled As Boolean
      Get
         If IsNothing(Map.refProjectVM) OrElse IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
            Return False
         ElseIf m_SelOPState.Id <> OPStates.End AndAlso m_SelOPState.Id <> OPStates.Unspecified Then
            Return False
         ElseIf IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Return False
         ElseIf Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Dim SelMachgroup As MyMachGroupVM = DirectCast(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup, MyMachGroupVM)
            Return SelMachgroup.nProduction_State <= ItemState.WIP
         Else
            Return m_LeftPanel_IsEnabled
         End If
      End Get
   End Property

   Public ReadOnly Property ResetRawPart_IsEnabled As Boolean
      Get
         If IsNothing(Map.refProjectVM) OrElse IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
            Return False
         ElseIf m_SelOPState.Id <> OPStates.End AndAlso m_SelOPState.Id <> OPStates.Unspecified Then
            Return False
         ElseIf IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Return False
         ElseIf Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Dim SelMachgroup As MyMachGroupVM = DirectCast(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup, MyMachGroupVM)
            Return SelMachgroup.nProduction_State > ItemState.Confirmed AndAlso Not SelMachgroup.bToBeProduced
         Else
            Return m_LeftPanel_IsEnabled
         End If
      End Get
   End Property

   Public ReadOnly Property DeleteRawPart_IsEnabled As Boolean
      Get
         If IsNothing(Map.refProjectVM) OrElse IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM) Then
            Return False
         ElseIf m_SelOPState.Id <> OPStates.End AndAlso m_SelOPState.Id <> OPStates.Unspecified Then
            Return False
         ElseIf IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Return False
         ElseIf Not IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then
            Dim SelMachgroup As MyMachGroupVM = DirectCast(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup, MyMachGroupVM)
            Return SelMachgroup.nProduction_State <= ItemState.Confirmed AndAlso Not SelMachgroup.bToBeProduced
         Else
            Return m_LeftPanel_IsEnabled
         End If
      End Get
   End Property

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

   Public ReadOnly Property OPMode_Visibility As Visibility
      Get
         Return If(CurrentMachine.NCType = NCTypes.NUM_FLEXIUM Or CurrentMachine.NCType = NCTypes.NUM_AXIUM_APSERVER Or CurrentMachine.NCType = NCTypes.NUM_AXIUM_PCTOOLKIT, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Private m_PrintLabel_Visibility As Visibility
   Public ReadOnly Property PrintLabel_Visibility As Visibility
      Get
         Return If(Map.refMainWindowVM.MainWindowM.bPrinterLink, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property DonePart_Visibility As Visibility
      Get
         ' per test -> 'Return Visibility.Visible
         Return If(Not IsNothing(Map.refSupervisorManagerVM.CurrProd) AndAlso Map.refSupervisorManagerVM.CurrProd.nType = BWType.BEAM, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

#Region "Messages"

   Public ReadOnly Property Channel_Msg As String
      Get
         Return EgtMsg(62501)
      End Get
   End Property

   Public ReadOnly Property OPMode_Msg As String
      Get
         Return EgtMsg(62502)
      End Get
   End Property

   Public ReadOnly Property ProduceAll_ToolTip As String
      Get
         Return EgtMsg(62503)
      End Get
   End Property

   Public ReadOnly Property DoneRawPart_ToolTip As String
      Get
         Return EgtMsg(62504)
      End Get
   End Property

   Public ReadOnly Property ResetRawPart_ToolTip As String
      Get
         Return EgtMsg(62505)
      End Get
   End Property

   Public ReadOnly Property DeleteRawPart_ToolTip As String
      Get
         Return EgtMsg(62506)
      End Get
   End Property

   Public ReadOnly Property PrintLabel_ToolTip As String
      Get
         Return EgtMsg(62507)
      End Get
   End Property

   Public ReadOnly Property DonePart_ToolTip As String
      Get
         Return EgtMsg(62508)
      End Get
   End Property

#End Region    ' Messages

   ' Definizione comandi
   Private m_cmdDeleteRawPart As ICommand
   Private m_cmdMoveUpRawPart As ICommand
   Private m_cmdMoveDownRawPart As ICommand
   Private m_cmdProduceAll As ICommand
   Private m_cmdDoneRawPart As ICommand
   Private m_cmdResetRawPart As ICommand
   Private m_cmdDonePart As ICommand
   Private m_cmdPrintLabel As ICommand

#End Region    'FIELDS & PROPERTIES

   Sub New()
      ' imposto riferimento su mappa
      Map.SetRefLeftPanelVM(Me)
      ' imposto dimensioni colonne/righe della Grid
      DimensionsIniFile.ReadGridDimensions(ConstDims.LEFTPANEL_SUPERVISOR, GridDims)
      m_PrintTimer.Interval = TimeSpan.FromMilliseconds(1000)
      AddHandler m_PrintTimer.Tick, AddressOf PrintTimer_Tick
   End Sub

#Region "METHODS"

   Friend Sub UpdateView()
      NotifyPropertyChanged("ViewPage_Visibility")
      NotifyPropertyChanged("MachiningPage_Visibility")
   End Sub

   Friend Sub SetLeftPanelIsEnabled(bIsEnabled As Boolean)
      m_LeftPanel_IsEnabled = bIsEnabled
      NotifyPropertyChanged(NameOf(LeftPanel_IsEnabled))
   End Sub

   Private Sub PrintTimer_Tick()
      m_PrintTimer.Stop()
      EgtOutLog("Print label timeout!")
   End Sub

   Friend Sub LoadChannels()
      ' carico stati della macchina
      Select Case NCType
         Case NCTypes.TPA
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            m_ChannelList = New List(Of IdNameStruct)
            Dim ChannelIndex As Integer = 1
            Dim ChannelString As String = ""
            While GetPrivateProfileString(S_CHANNELS, ChannelIndex, "", ChannelString, CurrentMachine.sMachIniFile) > 0 AndAlso
                  Not String.IsNullOrWhiteSpace(ChannelString)
               Dim sChannel() As String = ChannelString.Split(","c)
               If sChannel.Length >= 2 Then
                  ' elimino spazi
                  For Each Par In sChannel
                     Par = Par.Trim
                  Next
                  ' verifico se Id e' intero
                  Dim nId As Integer = -1
                  If Not Integer.TryParse(sChannel(0), nId) Then
                     ChannelIndex += 1
                     Continue While
                  End If
                  If nId < 0 Then
                     ChannelIndex += 1
                     Continue While
                  End If
                  ' verifico se messaggio e' numero intero
                  Dim sMessage As String = ""
                  Dim nMessage As Integer = 0
                  If Integer.TryParse(sChannel(1), nMessage) Then
                     sMessage = EgtMsg(nMessage)
                  End If
                  m_ChannelList.Add(New IdNameStruct(nId, If(Not String.IsNullOrWhiteSpace(sMessage), sMessage, sChannel(1))))
               End If
               ChannelIndex += 1
            End While
      End Select
      ' seleziono in partenza unspecified
      SetChannel(Nothing)
   End Sub

   Friend Sub LoadOPStates()
      ' carico stati della macchina
      Select Case NCType
         Case NCTypes.TPA
            m_OPStateList = New List(Of OPState) From {
                                                         New OPState("Start", OPStates.Start),
                                                         New OPState("Stop", OPStates.Stop),
                                                         New OPState("Reset", OPStates.End),
                                                         New OPState("SetPoint", OPStates.SetPoint),
                                                         New OPState("Pending", OPStates.Pending),
                                                         New OPState("Unspecified", OPStates.Unspecified)
         }
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            m_OPStateList = New List(Of OPState) From {
                                                         New OPState("Start", OPStates.Start),
                                                         New OPState("Stop", OPStates.Stop),
                                                         New OPState("Reset", OPStates.End),
                                                         New OPState("Unspecified", OPStates.Unspecified)
         }
         Case Else
            m_OPStateList = New List(Of OPState) From {
                                                         New OPState("Unspecified", OPStates.Unspecified)
         }
      End Select
      ' seleziono in partenza unspecified
      Dim UnspecifiedState As OPState = m_OPStateList.FirstOrDefault(Function(x) x.Id = OPStates.Unspecified)
      SetOPState(UnspecifiedState)
   End Sub

   Friend Sub LoadOPModes()
      ' carico stati della macchina
      Select Case NCType
         Case NCTypes.TPA
            m_OPModeList = New List(Of OPState) From {
                                                         New OPState("Manual", OPModes.Manual)
            }
         Case NCTypes.NUM_FLEXIUM, NCTypes.NUM_AXIUM_APSERVER, NCTypes.NUM_AXIUM_PCTOOLKIT
            m_OPModeList = New List(Of OPState) From {
                                                         New OPState("Auto", OPModes.Auto),
                                                         New OPState("Single", OPModes.Single),
                                                         New OPState("Mdi", OPModes.Mdi),
                                                         New OPState("Manual", OPModes.Manual),
                                                         New OPState("Home", OPModes.Home)
            }
      End Select
   End Sub

   Friend Sub SetE80000Visibility()
      ' imposto visibilità variabili E80000 e seconda del tipo di controllo
      If CurrentMachine.NCType = NCTypes.TPA Then
         m_E80000_Visibility = Visibility.Collapsed
         m_E80002_Visibility = Visibility.Collapsed
      Else
         m_E80000_Visibility = Visibility.Visible
         m_E80002_Visibility = Visibility.Collapsed
         Dim ReadVar As String = ""
         Dim Index = 1
         While GetPrivateProfileString(S_MAINVARIABLES, Index, "", ReadVar, CurrentMachine.sMachIniFile) <> 0
            If ReadVar.StartsWith(TOOLINDEX2) Then
               m_E80002_Visibility = Visibility.Visible
               Exit While
            End If
            Index += 1
         End While
      End If
      NotifyPropertyChanged(NameOf(E80000_Visibility))
      NotifyPropertyChanged(NameOf(E80002_Visibility))
   End Sub

   Friend Sub UpdateButtonIsEnabledState()
      NotifyPropertyChanged(NameOf(MoveRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(DoneRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(ResetRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(DeleteRawPart_IsEnabled))
   End Sub

#End Region    ' METHODS

#Region "COMMANDS"

#Region "ProduceAll"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property ProduceAll_Command As ICommand
      Get
         If m_cmdProduceAll Is Nothing Then
            m_cmdProduceAll = New Command(AddressOf ProduceAll)
         End If
         Return m_cmdProduceAll
      End Get
   End Property

   ''' <summary>
   ''' </summary>
   Public Sub ProduceAll()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList) OrElse Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count = 0 Then Return
      If Not Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Any(Function(x As MyMachGroupVM) x.nProduction_State <= ItemState.Confirmed) Then Return
      If Not Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Any(Function(x As MyMachGroupVM) x.dtStartTime = DateTime.MinValue) Then Return
      Dim View As List(Of MachGroupVM) = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList_View.Cast(Of MachGroupVM).ToList()
      Dim ToDoList As List(Of MachGroupVM) = View.Where(Function(x As MyMachGroupVM) x.nProduction_State <= 1 AndAlso Not x.bResetWhileCutting AndAlso x.dtStartTime = DateTime.MinValue AndAlso Not x.bToBeProduced).ToList()
      If Not IsNothing(ToDoList) AndAlso ToDoList.Count > 0 Then
         MyMachGroupVM.Produce(ToDoList)
      End If
   End Sub

#End Region    ' ProduceAll

#Region "DoneRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property DoneRawPart_Command As ICommand
      Get
         If m_cmdDoneRawPart Is Nothing Then
            m_cmdDoneRawPart = New Command(AddressOf DoneRawPart)
         End If
         Return m_cmdDoneRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub DoneRawPart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If (Not IsNothing(Map.refMachManaging) AndAlso Map.refMachManaging.bConnected AndAlso m_SelOPState.Id <> OPStates.End) OrElse
         Map.refSupervisorMachGroupPanelVM.MachGroupVMList.Any(Function(x As MyMachGroupVM) (x.bToBeProduced AndAlso x.Id <> SelMachGroup.Id) OrElse
                                                                                            (x.nProduction_State = ItemState.WIP AndAlso x.Id <> SelMachGroup.Id) OrElse
                                                                                            (x.dtStartTime <> DateTime.MinValue AndAlso x.dtEndTime = DateTime.MinValue AndAlso x.Id <> SelMachGroup.Id)) Then Return
      ' scrivo tutti pezzi completati
      For PartIndex = 0 To SelMachGroup.PartVMList.Count - 1
         Dim Part As PartVM = SelMachGroup.PartVMList(PartIndex)
         SetDonePart(SelMachGroup, Part)
      Next
      ' riseleziono il gruppo
      Map.refSupervisorMachGroupPanelVM.SelectedMachGroup = SelMachGroup
      ' aggiorno bottoni
      NotifyPropertyChanged(NameOf(DeleteRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(DoneRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(MoveRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(ResetRawPart_IsEnabled))
      ' se avanzamento singolo, sblocco produzione di tutti gli altri
      If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
         MyMachGroupVM.UpdateProduceIsEnabledForAll()
      End If
      ' aggiorno log macchina
      Map.refMachineLogPageVM.UpdateMachineLogList(False)
   End Sub

#End Region    ' DoneRawPart

#Region "ResetRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property ResetRawPart_Command As ICommand
      Get
         If m_cmdResetRawPart Is Nothing Then
            m_cmdResetRawPart = New Command(AddressOf ResetRawPart)
         End If
         Return m_cmdResetRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub ResetRawPart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      If (Not IsNothing(Map.refMachManaging) AndAlso Map.refMachManaging.bConnected AndAlso m_SelOPState.Id <> OPStates.End) OrElse
         Map.refSupervisorMachGroupPanelVM.MachGroupVMList.Any(Function(x As MyMachGroupVM) x.bToBeProduced) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If SelMachGroup.nProduction_State = ItemState.Assigned Then Return
      ' annullo stati dei pezzi gia' fatti
      For Each Part In SelMachGroup.PartVMList
         If Part.dtEndTime <> DateTime.MinValue Then
            DbControllers.m_PartController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, Part.nPartId, DateTime.MinValue)
            ' annullo stato end
            Part.dtEndTime = DateTime.MinValue
         End If
         If Part.dtStartTime <> DateTime.MinValue Then
            DbControllers.m_PartController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, Part.nPartId, DateTime.MinValue)
            DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, Part.nPartId, ItemState.Assigned)
            ' annullo stato start
            Part.nProduction_State = ItemState.Assigned
            Part.dtStartTime = DateTime.MinValue
            Part.NotifyPropertyChanged(NameOf(Part.nProduction_State))
         End If
      Next
      ' annullo stato del MachGroup
      DbControllers.m_MachGroupController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, DateTime.MinValue)
      DbControllers.m_MachGroupController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, DateTime.MinValue)
      DbControllers.m_MachGroupController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, ItemState.Assigned)
      ' scrivo stato end
      SelMachGroup.MyMachGroupM.SetProductionState(ItemState.Assigned)
      SelMachGroup.dtStartTime = DateTime.MinValue
      SelMachGroup.dtEndTime = DateTime.MinValue
      SelMachGroup.NotifyPropertyChanged(NameOf(SelMachGroup.nProduction_State))
      ' resetto stati di produzione del pezzo
      SelMachGroup.SetResetWhileCutting(False)
      SelMachGroup.ResetProduce()


      ' cerco primo indice di pezzo non in produzione
      Dim NewIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) x IsNot SelMachGroup AndAlso DirectCast(x, MyMachGroupVM).dtStartTime = DateTime.MinValue AndAlso DirectCast(x, MyMachGroupVM).bToBeProduced = False))

      ' sposto MachGroup in lista come ultimo dei pronti da produrre
      Dim OldIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(SelMachGroup)
      ' se non ho trovato nessuno che deve partire, tengo indice corrente
      If NewIndex < 0 Then NewIndex = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count()

      SelMachGroup.SetProductionIndex(NewIndex)
      ' aggiorno indice di tutte le barre in coda
      For Each CurrMachGroup As MyMachGroupVM In Map.refSupervisorMachGroupPanelVM.MachGroupVMList
         If Not (CurrMachGroup Is SelMachGroup) AndAlso CurrMachGroup.nProductionIndex < 5000 Then
            If CurrMachGroup.nProductionIndex > SelMachGroup.nProductionIndex Then
               CurrMachGroup.SetProductionIndex(CurrMachGroup.nProductionIndex + 1)
               DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, CurrMachGroup.Id, CurrMachGroup.nProductionIndex)
            ElseIf CurrMachGroup.nProductionIndex > OldIndex AndAlso CurrMachGroup.nProductionIndex <= SelMachGroup.nProductionIndex Then
               CurrMachGroup.SetProductionIndex(CurrMachGroup.nProductionIndex - 1)
               DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, CurrMachGroup.Id, CurrMachGroup.nProductionIndex)
            End If
         End If
      Next
      ' sposto machgroup corrente
      DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, SelMachGroup.nProductionIndex)
      Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Move(OldIndex, NewIndex - 1)

      ' riseleziono il gruppo
      Map.refSupervisorMachGroupPanelVM.SelectedMachGroup = SelMachGroup
      ' aggiorno bottoni
      NotifyPropertyChanged(NameOf(DeleteRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(DoneRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(MoveRawPart_IsEnabled))
      NotifyPropertyChanged(NameOf(ResetRawPart_IsEnabled))
      ' se avanzamento singolo, sblocco produzione di tutti gli altri
      If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
         MyMachGroupVM.UpdateProduceIsEnabledForAll()
      End If
   End Sub

   Public Sub ResetDonePart(MachGroup As MyMachGroupVM, Part As PartVM)
      If IsNothing(MachGroup) OrElse IsNothing(Part) Then Return
      ' se ora d'inizio non e' gia' fissata
      Dim Time As DateTime = DateTime.Now()
      If Part.nProduction_State = ItemState.Scrapped Then
         ' fare domanda se modificare quantita' aggiunti se viene resettato un pezzo scraped??
         'If MessageBox.Show("There are scraped parts in this bar. Would you like to add them to the added quantity?", "", MessageBoxButton.YesNo, MessageBoxImage.Information) = MessageBoxResult.Yes Then
         '   DbControllers.m_StatusMapController.UpdateAction("", Map.refSupervisorManagerVM.CurrProd.nProdId, Part.nPartId, StatusMapItemType.Part, StatusMapOpType.AddQtyForUnscraped, "")
         'End If
      End If
      If Part.dtStartTime <> DateTime.MinValue Then
         DbControllers.m_PartController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, DateTime.MinValue)
         DbControllers.m_PartController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, DateTime.MinValue)
         DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, ItemState.ND)
         Part.dtStartTime = DateTime.MinValue
         Part.dtEndTime = DateTime.MinValue
         Part.nProduction_State = ItemState.ND
         ' se e' il primo ad essere resettato
         If Not MachGroup.PartVMList.All(Function(x) x IsNot Part AndAlso x.dtStartTime > DateTime.MinValue) Then
            ' cerco primo indice di pezzo non in produzione
            Dim NewIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) DirectCast(x, MyMachGroupVM).dtStartTime = DateTime.MinValue AndAlso DirectCast(x, MyMachGroupVM).bToBeProduced = False))
            ' sposto MachGroup in lista come ultimo dei pronti da produrre
            Dim OldIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(MachGroup)
            MachGroup.SetProductionIndex(NewIndex + 1)
            DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, MachGroup.nProductionIndex)
            Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Move(OldIndex, NewIndex)
            ' aggiorno anche start MachGroup
            DbControllers.m_MachGroupController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Time)
            DbControllers.m_MachGroupController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, ItemState.WIP)
            MachGroup.dtStartTime = Time
            MachGroup.nProduction_State = ItemState.WIP
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Production_Background))
            ' blocco produzione di tutti gli altri perche' iniziato questo
            MyMachGroupVM.UpdateProduceIsEnabledForAll()
         End If
      End If
      If Part.dtEndTime = DateTime.MinValue Then
         DbControllers.m_PartController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, Time)
         DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, ItemState.Produced)
         Part.dtEndTime = Time
         Part.nProduction_State = ItemState.Produced
         If MachGroup.PartVMList.All(Function(x) x.nProduction_State >= ItemState.Produced) Then
            'aggiorno anche fine MachGroup
            DbControllers.m_MachGroupController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Time)
            DbControllers.m_MachGroupController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, ItemState.Produced)
            MachGroup.dtEndTime = Time
            MachGroup.nProduction_State = ItemState.Produced
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Production_Background))
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Produce_IsEnabled))
            ' se avanzamento singolo, sblocco produzione di tutti gli altri
            If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
               MyMachGroupVM.UpdateProduceIsEnabledForAll()
            End If
         End If
      End If
      Part.NotifyPropertyChanged(NameOf(Part.Production_Background))
   End Sub

#End Region    ' ResetRawPart

#Region "DeleteRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property DeleteRawPart_Command As ICommand
      Get
         If m_cmdDeleteRawPart Is Nothing Then
            m_cmdDeleteRawPart = New Command(AddressOf DeleteRawPart)
         End If
         Return m_cmdDeleteRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub DeleteRawPart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      ' se gia' prodotto, o in produzione non lo posso eliminare
      If SelMachGroup.dtStartTime <> Date.MinValue OrElse SelMachGroup.dtEndTime <> Date.MinValue OrElse SelMachGroup.bReadyForMachining OrElse SelMachGroup.bSentToMachine OrElse SelMachGroup.bResetWhileCutting Then
         MessageBox.Show("Impossibile cancellare il grezzo")
         Return
      End If
      ' rimuovo da Db il MachGroup
      If DbControllers.m_MachGroupController.RemoveFromSupervisor(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id) Then
         ' rimuovo da DB tutti i pezzi del MachGroup
         For Each Part In SelMachGroup.PartVMList
            DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, SelMachGroup.Id, Part.nPartId, ItemState.ND)
         Next
         Dim nRemovedIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(SelMachGroup)
         ' se rimozione da Db ok, lo rimuovo da lista
         Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Remove(SelMachGroup)
         If Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count = 0 Then
            EgtResetCurrMachGroup()
            ManageBTLParts.HideAll()
         Else
            If nRemovedIndex >= Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count Then nRemovedIndex = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count - 1
            Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList(nRemovedIndex)
         End If
      End If
   End Sub

#End Region    ' DeleteRawPart

#Region "DonePart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property DonePart_Command As ICommand
      Get
         If m_cmdDonePart Is Nothing Then
            m_cmdDonePart = New Command(AddressOf DonePart)
         End If
         Return m_cmdDonePart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub DonePart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      If (Not IsNothing(Map.refMachManaging) AndAlso Map.refMachManaging.bConnected AndAlso m_SelOPState.Id <> OPStates.End) OrElse
         Map.refSupervisorMachGroupPanelVM.MachGroupVMList.Any(Function(x As MyMachGroupVM) x.bToBeProduced) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If IsNothing(SelMachGroup.SelPart) Then Return
      ' verifico se pezzi precedenti nella barra siano lavorati
      For Index = 0 To SelMachGroup.PartVMList.Count - 1
         Dim CurrPart As PartVM = SelMachGroup.PartVMList(Index)
         If CurrPart Is SelMachGroup.SelPart Then
            Exit For
         ElseIf CurrPart.nProduction_State < ItemState.Produced Then
            MessageBox.Show("It is not possible to set as done a part that has before not already produced parts.", "Error", MessageBoxButton.OK, MessageBoxImage.Error)
            Return
         End If
      Next
      SetDonePart(SelMachGroup, SelMachGroup.SelPart)
      Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup = SelMachGroup
      ' aggiorno log macchina
      Map.refMachineLogPageVM.UpdateMachineLogList(False)
   End Sub

   Public Sub SetDonePart(MachGroup As MyMachGroupVM, Part As PartVM)
      If IsNothing(MachGroup) OrElse IsNothing(Part) Then Return
      ' se ora d'inizio non e' gia' fissata
      Dim Time As DateTime = DateTime.Now()
      If Part.dtStartTime = DateTime.MinValue Then
         DbControllers.m_PartController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, Time)
         DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, ItemState.WIP)
         Part.dtStartTime = Time
         Part.nProduction_State = ItemState.WIP
         ' scrivo evento inizio pezzo su DB
         DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(Time - TimeSpan.FromSeconds(1), Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, 1, DbControllers.SupervisorId))
         ' se e' il primo ad essere lavorato
         If Not MachGroup.PartVMList.Any(Function(x) x IsNot Part AndAlso x.dtStartTime > DateTime.MinValue) Then
            Dim bCurrToBeProduced As Boolean = MachGroup.bToBeProduced Or MachGroup.bReadyForMachining Or MachGroup.bSentToMachine
            ' se non e' gia' in coda per essere prodotto
            If Not bCurrToBeProduced Then
               ' riposiziono il gruppo come primo dei non lavorati assegnandogli indice corretto
               ' cerco primo indice di pezzo non in produzione
               Dim NewIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.FirstOrDefault(Function(x) DirectCast(x, MyMachGroupVM).dtStartTime = DateTime.MinValue AndAlso DirectCast(x, MyMachGroupVM).bToBeProduced = False))
               ' sposto MachGroup in lista come ultimo dei pronti da produrre
               Dim OldIndex As Integer = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(MachGroup)
               MachGroup.SetProductionIndex(NewIndex + 1)
               ' aggiorno indice di tutte le barre in coda
               For Each CurrMachGroup As MyMachGroupVM In Map.refSupervisorMachGroupPanelVM.MachGroupVMList
                  If Not (CurrMachGroup Is MachGroup) AndAlso CurrMachGroup.nProductionIndex >= MachGroup.nProductionIndex AndAlso CurrMachGroup.nProductionIndex < 5000 Then
                     CurrMachGroup.SetProductionIndex(CurrMachGroup.nProductionIndex + 1)
                     DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, CurrMachGroup.Id, CurrMachGroup.nProductionIndex)
                  End If
               Next
               ' sposto machgroup impostato a Done
               DbControllers.m_MachGroupController.UpdateOrder(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, MachGroup.nProductionIndex)
               Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Move(OldIndex, NewIndex)
            End If
            ' aggiorno anche start MachGroup
            DbControllers.m_MachGroupController.UpdateStart(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Time)
            DbControllers.m_MachGroupController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, ItemState.WIP)
            MachGroup.dtStartTime = Time
            MachGroup.nProduction_State = ItemState.WIP
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Production_Background))
            ' aggiorno sort custom dei MachGroup
            If Not bCurrToBeProduced Then
               Map.refSupervisorMachGroupPanelVM.RefreshMachGroupVMSort()
            End If
            ' scrivo evento inizio MachGroup su DB
            DbControllers.m_LogMachineController.Create(LogEvent.CreateMachGroupStateLog(Time - TimeSpan.FromSeconds(1), Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, 1, DbControllers.SupervisorId))
            ' blocco produzione di tutti gli altri perche' iniziato questo
            MyMachGroupVM.UpdateProduceIsEnabledForAll()
         End If
      End If
      If Part.dtEndTime = DateTime.MinValue Then
         DbControllers.m_PartController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, Time)
         DbControllers.m_PartController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, ItemState.Produced)
         Part.dtEndTime = Time
         Part.nProduction_State = ItemState.Produced
         ' scrivo evento fine pezzo su DB
         DbControllers.m_LogMachineController.Create(LogEvent.CreatePartStateLog(Time, Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Part.nPartId, 2, DbControllers.SupervisorId))
         If MachGroup.PartVMList.All(Function(x) x.nProduction_State >= ItemState.Produced) Then
            'aggiorno anche fine MachGroup
            DbControllers.m_MachGroupController.UpdateEnd(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, Time)
            DbControllers.m_MachGroupController.UpdateStatus(Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, ItemState.Produced)
            MachGroup.dtEndTime = Time
            MachGroup.nProduction_State = ItemState.Produced
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Production_Background))
            MachGroup.NotifyPropertyChanged(NameOf(MachGroup.Produce_IsEnabled))
            ' reset delle variabili di invio alla macchina
            MachGroup.ResetProduce()
            ' aggiorno bottoni
            NotifyPropertyChanged(NameOf(DeleteRawPart_IsEnabled))
            NotifyPropertyChanged(NameOf(DoneRawPart_IsEnabled))
            NotifyPropertyChanged(NameOf(MoveRawPart_IsEnabled))
            NotifyPropertyChanged(NameOf(ResetRawPart_IsEnabled))
            ' scrivo evento fine MachGroup su DB
            DbControllers.m_LogMachineController.Create(LogEvent.CreateMachGroupStateLog(Time, Map.refSupervisorManagerVM.CurrProd.nProdId, MachGroup.Id, 2, DbControllers.SupervisorId))
            ' se avanzamento singolo, sblocco produzione di tutti gli altri
            If CurrentMachine.Flow = FlowTypes.ONEBYONE Then
               MyMachGroupVM.UpdateProduceIsEnabledForAll()
            End If
         End If
      End If
      Part.NotifyPropertyChanged(NameOf(Part.Production_Background))
   End Sub

#End Region    ' DonePart

#Region "MoveUpRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property MoveUpRawPart_Command As ICommand
      Get
         If m_cmdMoveUpRawPart Is Nothing Then
            m_cmdMoveUpRawPart = New Command(AddressOf MoveUpRawPart)
         End If
         Return m_cmdMoveUpRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub MoveUpRawPart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If SelMachGroup.nProduction_State >= ItemState.WIP Or SelMachGroup.bReadyForMachining Then Return
      Dim nSelMGIndex = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(SelMachGroup)
      If nSelMGIndex = 0 Then Return
      Dim PreviousMG As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList(nSelMGIndex - 1)
      If PreviousMG.nProduction_State >= ItemState.WIP Or PreviousMG.bReadyForMachining Then Return
      ' scambio indici
      Dim nSelMGProdIndex As Integer = SelMachGroup.nProductionIndex
      SelMachGroup.SetProductionIndex(PreviousMG.nProductionIndex)
      PreviousMG.SetProductionIndex(nSelMGProdIndex)
      Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Move(nSelMGIndex, nSelMGIndex - 1)
      ' lancio sort custom
      Map.refSupervisorMachGroupPanelVM.RefreshMachGroupVMSort()
   End Sub

#End Region    ' MoveUpRawPart

#Region "MoveDownRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property MoveDownRawPart_Command As ICommand
      Get
         If m_cmdMoveDownRawPart Is Nothing Then
            m_cmdMoveDownRawPart = New Command(AddressOf MoveDownRawPart)
         End If
         Return m_cmdMoveDownRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub MoveDownRawPart()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If SelMachGroup.nProduction_State >= ItemState.WIP Or SelMachGroup.bReadyForMachining Then Return
      Dim nSelMGIndex = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.IndexOf(SelMachGroup)
      If nSelMGIndex = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Count - 1 Then Return
      ' scambio indici
      Dim NextMG As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList(nSelMGIndex + 1)
      Dim nSelMGProdIndex As Integer = SelMachGroup.nProductionIndex
      SelMachGroup.SetProductionIndex(NextMG.nProductionIndex)
      NextMG.SetProductionIndex(nSelMGProdIndex)
      Map.refProjectVM.SupervisorMachGroupPanelVM.MachGroupVMList.Move(nSelMGIndex, nSelMGIndex + 1)
      ' lancio sort custom
      Map.refSupervisorMachGroupPanelVM.RefreshMachGroupVMSort()
   End Sub

#End Region    ' MoveDownRawPart

#Region "PrintLabel"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property PrintLabel_Command As ICommand
      Get
         If m_cmdPrintLabel Is Nothing Then
            m_cmdPrintLabel = New Command(AddressOf PrintLabelComm)
         End If
         Return m_cmdPrintLabel
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub PrintLabelComm()
      If IsNothing(Map.refSupervisorManagerVM.CurrProd) Then Return
      If IsNothing(Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup) Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refProjectVM.SupervisorMachGroupPanelVM.SelectedMachGroup
      If IsNothing(SelMachGroup.SelPart) Then Return
      PrintLabel(SelMachGroup, SelMachGroup.SelPart)
   End Sub

   Public Sub PrintLabel(SelMachGroup As MyMachGroupVM, SelPart As PartVM)
      If Not Map.refMainWindowVM.MainWindowM.bPrinterLink Then Return
      If IsNothing(SelMachGroup) Then Return
      If IsNothing(SelPart) Then Return
      ' recupero file template
      Dim TemplateFilePath As String = ""
      GetMainPrivateProfileString(S_PRINTER, K_TEMPLATE, "", TemplateFilePath)
      Dim FileName As String = DateTime.Now.ToString
      FileName = FileName.Replace("/"c, "_")
      FileName = FileName.Replace(":"c, "_")
      FileName = FileName.Replace(" "c, "&")
      Dim FileINI As String = Map.refMainWindowVM.MainWindowM.sTempDir & "\" & FileName & ".ini"
      ' creo file dati 
      CreateDataFile(FileINI, SelPart, SelMachGroup)

      Dim Proc = New Process()
      Proc.StartInfo.FileName = Map.refMainWindowVM.MainWindowM.sZebraPrinterExe
      Proc.StartInfo.Arguments = TemplateFilePath & " " & FileINI
      Proc.StartInfo.CreateNoWindow = True
      Proc.StartInfo.UseShellExecute = False
      AddHandler Proc.Exited, AddressOf Proc_Exited

      For Inde = 0 To 100
         If Not m_PrintTimer.IsEnabled Then Exit For
         Threading.Thread.Sleep(100)
      Next
      If Not m_PrintTimer.IsEnabled AndAlso Proc.Start() Then
         m_PrintTimer.Start()
      End If

   End Sub

   Private Sub Proc_Exited()
      m_PrintTimer.Stop()
   End Sub

   Private Sub CreateDataFile(sFilePath As String, SelPart As PartVM, SelMachGroup As MyMachGroupVM)
      Dim sFileText As New List(Of String)
      Dim nBtlInfoId As Integer = EgtGetFirstNameInGroup(GDB_ID.ROOT, BTLINFO)
      Dim sInfo As String = ""
      Dim bOk As Boolean = False
      ' inserisco il capitolo del [Main]
      sFileText.Add("[Main]")
      sFileText.Add("Var1=$PRODID$," & Map.refSupervisorManagerVM.CurrProd.sProdId)
      sFileText.Add("Var2=$MACHGROUPID$," & SelMachGroup.nName)
      sFileText.Add("Var3=$PARTID$," & SelPart.nPDN)
      sFileText.Add("Var4=$MATERIAL$," & SelPart.sMATERIAL)
      bOk = EgtGetInfo(nBtlInfoId, BTL_GEN_PROJNUM, sInfo)
      sFileText.Add("Var5=$PROJECTNUMBER$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(nBtlInfoId, BTL_GEN_PROJNAME, sInfo)
      sFileText.Add("Var6=$PROJECTNAME$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(nBtlInfoId, BTL_GEN_CUSTOMER, sInfo)
      sFileText.Add("Var7=$CUSTOMER$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_ASSEMBLYNUM, sInfo)
      sFileText.Add("Var8=$ASSEMBLYNUMBER$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_ORDERNUM, sInfo)
      sFileText.Add("Var9=$ORDERNUMBER$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_DESIGNATION, sInfo)
      sFileText.Add("Var10=$DESIGNATION$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_ANNOTATION, sInfo)
      sFileText.Add("Var11=$ANNOTATION$," & If(bOk, sInfo, ""))
      sFileText.Add("Var12=$STOREY$," & SelPart.sSTOREY)
      sFileText.Add("Var13=$GROUP$," & SelPart.sGROUP)
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_PACKAGE, sInfo)
      sFileText.Add("Var14=$PACKAGE$," & If(bOk, sInfo, ""))
      sFileText.Add("Var15=$WHL$," & SelPart.sW & "x" & SelPart.sH & "x" & SelPart.sL)
      sFileText.Add("Var16=$PRODUCTIONDATE$," & Date.Now().ToString("yyyy-MM-dd"))
      ' calcolo numero settimana corrente secondo ISO 8601
      Dim time As Date = Date.Now()
      Dim Day As DayOfWeek = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time)
      If Day >= DayOfWeek.Monday AndAlso Day <= DayOfWeek.Wednesday Then time = time.AddDays(3)
      Dim nWeekOfYear As Integer = CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)
      sFileText.Add("Var17=$PRODUCTIONWEEK$," & nWeekOfYear)
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_DESCRIPTION, sInfo)
      sFileText.Add("Var18=$DESCRIPTION$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(SelPart.nPartId, BTL_PRT_QUALITYGRADE, sInfo)
      sFileText.Add("Var19=$QUALITYGRADE$," & If(bOk, sInfo, ""))
      bOk = EgtGetInfo(nBtlInfoId, BTL_GEN_BTLPATH, sInfo)
      sFileText.Add("Var20=$BTLPATH$," & If(bOk, Path.GetFileNameWithoutExtension(sInfo), ""))

      Try
         File.WriteAllLines(sFilePath, sFileText)
      Catch ex As Exception
         EgtOutLog("Prepare print file: " & ex.ToString)
      End Try
   End Sub

#End Region    ' PrintLabel

#End Region    ' COMMANDS

End Class

Public Class OPState

   Private m_Name As String
   Public ReadOnly Property Name As String
      Get
         Return m_Name
      End Get
   End Property
   Private m_Id As Integer
   Public ReadOnly Property Id As Integer
      Get
         Return m_Id
      End Get
   End Property

   Sub New(Name As String, Id As Integer)
      m_Name = Name
      m_Id = Id
   End Sub

End Class

Public Class FeatureDataGridHeightConverter
   Implements IValueConverter

   Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
      Dim Height As Double = CDbl(value)
      If Not IsNothing(Height) Then
         Return Height / 2
      Else
         Return 200
      End If
   End Function

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

End Class
