Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.IO
Imports System.Windows
Imports System.Windows.Input
Imports System.Windows.Media
Imports EgtBEAMWALL.Core
Imports EgtUILib
Imports EgtWPFLib5

Public MustInherit Class MyMachGroupVM
   Inherits MachGroupVM

#Region "FIELDS & PROPERTIES"

#Region "General"

   Public ReadOnly Property MyMachGroupM As MyMachGroupM
      Get
         Return m_MachGroupM
      End Get
   End Property

   Public ReadOnly Property nType As BWType
      Get
         Return MyMachGroupM.nType
      End Get
   End Property

   Public ReadOnly Property nName As Integer
      Get
         Dim nIntName As Integer = 0
         Integer.TryParse(MyMachGroupM.Name, nIntName)
         Return nIntName
      End Get
   End Property

   Public Property dL As Double
      Get
         Return MyMachGroupM.dL
      End Get
      Set(value As Double)
         MyMachGroupM.dL = value
      End Set
   End Property

   Public Property dW As Double
      Get
         Return MyMachGroupM.dW
      End Get
      Set(value As Double)
         MyMachGroupM.dW = value
      End Set
   End Property

   Public Property dH As Double
      Get
         Return MyMachGroupM.dH
      End Get
      Set(value As Double)
         MyMachGroupM.dH = value
      End Set
   End Property

   Public Property dtStartTime As DateTime
      Get
         Return MyMachGroupM.dtStartTime
      End Get
      Set(value As DateTime)
         MyMachGroupM.dtStartTime = value
         NotifyPropertyChanged(NameOf(Production_Background))
      End Set
   End Property

   Public Property dtEndTime As DateTime
      Get
         Return MyMachGroupM.dtEndTime
      End Get
      Set(value As DateTime)
         MyMachGroupM.dtEndTime = value
         NotifyPropertyChanged(NameOf(Production_Background))
      End Set
   End Property

   Public ReadOnly Property dUsage As Double
      Get
         Return If(MyMachGroupM.dMatForPart > 0 AndAlso MyMachGroupM.dTotMat > 0, If(nType = BWType.WALL, MyMachGroupM.dMatForPart / MyMachGroupM.dTotMat * 100, MyMachGroupM.dMatForPart / MyMachGroupM.dL * 100), 0)
      End Get
   End Property

   Public ReadOnly Property dWaste As Double
      Get
         Return If(MyMachGroupM.dMatForPart > 0 AndAlso MyMachGroupM.dTotMat > 0, If(nType = BWType.WALL, (MyMachGroupM.dTotMat - MyMachGroupM.dMatForPart) / 1000000000, MyMachGroupM.dL - MyMachGroupM.dTotMat), 0)
      End Get
   End Property

   Public ReadOnly Property sUsage As String
      Get
         Return DoubleToString(dUsage, 3)
      End Get
   End Property

   Public ReadOnly Property sWaste As String
      Get
         Return LenToString(dWaste, 3)
      End Get
   End Property

   Public Property sMATERIAL As String
      Get
         Return MyMachGroupM.sMATERIAL
      End Get
      Set(value As String)
         MyMachGroupM.sMATERIAL = value
      End Set
   End Property

   Public ReadOnly Property sUnitTime As String
      Get
         Return TimeSpan.FromSeconds(nCALC_TIME).ToString()
      End Get
   End Property

   Public ReadOnly Property dUnitVolume As Double
      Get
         Return dL * dW * dH
      End Get
   End Property

   Public ReadOnly Property Section As SectionXMaterial
      Get
         Return New SectionXMaterial(dW, dH, dL, MyMachGroupM.sMATERIAL)
      End Get
   End Property

   ' lista dei pezzi che sono nel grezzo
   Protected m_PartVMList As New ObservableCollection(Of PartVM)
   Public Property PartVMList As ObservableCollection(Of PartVM)
      Get
         Return m_PartVMList
      End Get
      Set(value As ObservableCollection(Of PartVM))
         m_PartVMList = value
      End Set
   End Property

   Protected m_SelPart As PartVM
   Public Overridable Property SelPart As PartVM
      Get
         Return m_SelPart
      End Get
      Set(value As PartVM)
         m_SelPart = value
         ' seleziono pezzo
         EgtDeselectAll()
         If Not IsNothing(value) Then EgtSelectObj(SelPart.nPartId)
         EgtDraw()
         NotifyPropertyChanged(NameOf(SelPart))
      End Set
   End Property

#End Region    ' General

#Region "Beam"

   Public Overridable Property sStartCut As String
      Get
         Return LenToString(MyMachGroupM.dStartCut, 3)
      End Get
      Set(value As String)
         StringToLenAdv(value, MyMachGroupM.dStartCut, True)
      End Set
   End Property
   Public Property dStartCut As Double
      Get
         Return MyMachGroupM.dStartCut
      End Get
      Set(value As Double)
         MyMachGroupM.dStartCut = value
         NotifyPropertyChanged(NameOf(sStartCut))
      End Set
   End Property

#End Region    ' Beam

#Region "Wall"

#End Region    ' Wall

#Region "Calc"

   Public ReadOnly Property nCALC_ERR As Integer
      Get
         Return MyMachGroupM.nCALC_ERR
      End Get
   End Property

   Public ReadOnly Property nCALC_FALL As Integer
      Get
         Return MyMachGroupM.nCALC_FALL
      End Get
   End Property

   Public ReadOnly Property sCALC_MSG As String
      Get
         Return MyMachGroupM.sCALC_MSG
      End Get
   End Property

   Public Property nCALC_ROT As Integer
      Get
         Return MyMachGroupM.nCALC_ROT
      End Get
      Set(value As Integer)
         MyMachGroupM.nCALC_ROT = value
      End Set
   End Property

   Public Property nCALC_TIME As Integer
      Get
         Return MyMachGroupM.nCALC_TIME
      End Get
      Set(value As Integer)
         MyMachGroupM.nCALC_TIME = value
      End Set
   End Property

   Public Property nGlobalState As CalcStates
      Get
         Return MyMachGroupM.nCALC_GlobalState
      End Get
      Set(value As CalcStates)
         MyMachGroupM.nCALC_GlobalState = value
      End Set
   End Property

   Public ReadOnly Property nPartsGlobalState As CalcStates
      Get
         Return MyMachGroupM.bCALC_PartsGlobalState
      End Get
   End Property

   Public Property nCALC_State As CalcStates
      Get
         Return MyMachGroupM.nCALC_State
      End Get
      Set(value As CalcStates)
         MyMachGroupM.nCALC_State = value
      End Set
   End Property

   Public ReadOnly Property Calc_Background As SolidColorBrush
      Get
         Select Case MyMachGroupM.nCALC_GlobalState
            Case CalcStates.ERROR_, CalcStates.COLLISION
               Return Brushes.Red
            Case CalcStates.WARNING
               Return Brushes.Orange
            Case CalcStates.INFO, CalcStates.OK
               Return Brushes.Green
            Case CalcStates.NOTCALCULATED
               Return Brushes.LightGray
            Case Else
               Return Brushes.Red
         End Select
      End Get
   End Property

   Public ReadOnly Property CALC_ROT_Visibility As Visibility
      Get
         Return If(MyMachGroupM.nCALC_ROT <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property CALC_FALL_Visibility As Visibility
      Get
         Return If(MyMachGroupM.nCALC_FALL <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property CALC_ERR_Letter As String
      Get
         Select Case MyMachGroupM.nCALC_GlobalState
            Case CalcStates.COLLISION
               Return "c"
            Case CalcStates.ERROR_
               Return "e"
            Case CalcStates.WARNING
               Return "w"
            Case CalcStates.INFO
               Return "i"
            Case Else
               Return ""
         End Select
      End Get
   End Property

   Public ReadOnly Property CALC_ERR_Foreground As SolidColorBrush
      Get
         Select Case MyMachGroupM.m_nCALC_GlobalState
            Case CalcStates.ERROR_, CalcStates.COLLISION
               Return Brushes.Red
            Case CalcStates.WARNING
               Return Brushes.Orange
            Case CalcStates.INFO
               Return Brushes.Green
            Case Else
               Return Brushes.Red
         End Select
      End Get
   End Property

#End Region    ' Calc

#Region "Supervisor"

   Public Property nProduction_State As ItemState
      Get
         Return MyMachGroupM.nProductionState
      End Get
      Set(value As ItemState)
         MyMachGroupM.SetProductionState(value)
      End Set
   End Property

   Public ReadOnly Property Production_Background As SolidColorBrush
      Get
         Select Case nProduction_State
            Case ItemState.ND
               Return Brushes.White
            Case ItemState.Assigned, ItemState.Confirmed
               If m_bToBeProduced Then                     ' barra in attesa
                  If m_bCNReCalculated Then
                     Return Brushes.Orange
                  Else                                     ' barra in check calc
                     Return Brushes.Purple
                  End If
               Else                                        ' barra in coda
                  Return Brushes.White
               End If
            Case ItemState.WIP
               Return Brushes.Green
            Case ItemState.Produced
               Return Brushes.Yellow
            Case Else         ' ItemState.Scrapped
               Return Brushes.Aqua
         End Select
      End Get
   End Property

   ' indica se il pezzo deve essere tagliato
   Protected m_bToBeProduced As Boolean = False
   Public ReadOnly Property bToBeProduced As Boolean
      Get
         Return m_bToBeProduced
      End Get
   End Property

   ' indica se il pezzo e' gia' stato ricalcolato e quindi pronto a partire
   Protected m_bCNReCalculated As Boolean = False
   Public ReadOnly Property bReadyForMachining As Boolean
      Get
         Return m_bToBeProduced AndAlso m_bCNReCalculated
      End Get
   End Property

   Protected m_bSendingToMachine As Boolean = False
   Public ReadOnly Property bSendingToMachine As Boolean
      Get
         Return m_bSendingToMachine
      End Get
   End Property
   Public Sub SetSendingToMachine(value As Boolean)
      m_bSendingToMachine = value
   End Sub

   ' indica se il pezzo e' stato mandato alla macchina
   Protected m_bSentToMachine As Boolean = False
   Public ReadOnly Property bSentToMachine As Boolean
      Get
         Return m_bSentToMachine
      End Get
   End Property
   Public Sub SetSentToMachine(value As Boolean)
      m_bSentToMachine = value
      m_bSendingToMachine = False
   End Sub

   ' indica se la macchina e' stata interrotta durante la lavorazione
   Protected m_bResetWhileCutting As Boolean = False
   Public ReadOnly Property bResetWhileCutting As Boolean
      Get
         Return m_bResetWhileCutting
      End Get
   End Property
   Public Sub SetResetWhileCutting(value As Boolean)
      m_bResetWhileCutting = value
   End Sub

   Public ReadOnly Property Background As SolidColorBrush
      Get
         Select Case nProduction_State
            Case ItemState.ND
               Return Brushes.White
            Case ItemState.Assigned
               Return Brushes.LightGray
            Case ItemState.Confirmed
               Return Brushes.LightGray
            Case ItemState.WIP
               Return Brushes.Green
            Case ItemState.Produced
               Return Brushes.Yellow
            Case Else         ' ItemState.Scrapped
               Return Brushes.Aqua
         End Select
      End Get
   End Property

   Public Overridable ReadOnly Property Produce_IsEnabled As Boolean
      Get
         Select Case nProduction_State
            Case ItemState.Assigned, ItemState.Confirmed
               Return Not m_bToBeProduced
            Case Else
               Return False
         End Select
      End Get
   End Property

   Private m_SupervisorId As String = ""
   Public ReadOnly Property SupervisorId As String
      Get
         Return m_SupervisorId
      End Get
   End Property
   Public Sub SetSupervisorId(SupervisorId As String)
      m_SupervisorId = SupervisorId
   End Sub

   Private m_cc As StateChangeEventArgs

   Public ReadOnly Property IsReadOnly As Boolean
      Get
         Return String.IsNullOrEmpty(m_SupervisorId)
      End Get
   End Property

#End Region    ' Supervisor

   ' definizione comandi
   Private m_cmdDeleteMachGroup As ICommand
   Private m_cmdProduceMachGroup As ICommand

#End Region    ' FIELDS & PROPERTIES

#Region "CONSTRUCTORS"

   Sub New(MyMachGroupM As MyMachGroupM)
      MyBase.New(MyMachGroupM)
      'aggiorno lista pezzi
      RefreshPartList()
      AddHandler MyMachGroupM.PartAdded, AddressOf OnPartAdded
      AddHandler MyMachGroupM.PartRemoved, AddressOf OnPartRemoved
      CreatePartVMList()
      ' Aggiorno stato da stati feature
      CalcGlobalUpdate()
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
   End Sub

#End Region    ' CONSTRUCTORS

#Region "METHODS"

#Region "Machgroup"

   Public MustOverride Sub RefreshGroupData()

   Public Overridable Function Copy() As MyMachGroupVM
      Return Nothing
   End Function

   Public Sub UpdateUsage()
      If nType = BWType.BEAM Then
         MyMachGroupM.SetMatForPart(0)
         Dim dPartLength As Double
         Dim dPartOffsetLength As Double
         For Each Part In PartVMList
            dPartOffsetLength += Part.dL + Part.dOffset
            dPartLength += Part.dL
         Next
         MyMachGroupM.SetTotMat(dPartOffsetLength)
         MyMachGroupM.SetMatForPart(dPartLength)
      Else
         MyMachGroupM.SetTotMat(dL * dH * dW)
         MyMachGroupM.SetMatForPart(0)
         Dim dPartVolume As Double
         For Each Part In PartVMList
            dPartVolume += Part.dVolume
         Next
         MyMachGroupM.SetMatForPart(dPartVolume)
      End If
      NotifyPropertyChanged(NameOf(sUsage))
      NotifyPropertyChanged(NameOf(sWaste))
   End Sub

   Public Overridable Function CnFilePath() As String
      Return Nothing
   End Function

#End Region    ' Machgroup

#Region "Calc"

   ' funzione che aggiorna lo stato e gli errori dopo calcolo
   Public Sub CalcMachGroupUpdate(ERR As Integer, ROT As Integer, MSG As String)
      EgtSetInfo(Id, ITG_PROD_ERR, ERR, True)
      EgtSetInfo(Id, ITG_PROD_MSG, MSG, True)
      EgtSetInfo(Id, ITG_PROD_ROT, ROT, True)
      MyMachGroupM.nCALC_ERR = ERR
      MyMachGroupM.nCALC_ROT = ROT
      MyMachGroupM.sCALC_MSG = MSG
      Select Case ERR
         Case 0
            nCALC_State = CalcStates.OK
         Case 22
            nCALC_State = CalcStates.COLLISION
         Case 17, 19
            nCALC_State = CalcStates.WARNING
         Case < 0
            nCALC_State = CalcStates.INFO
         Case > 0
            nCALC_State = CalcStates.ERROR_
      End Select
      NotifyPropertyChanged(NameOf(Calc_Background))
   End Sub

   Public Sub ResetCalcMachGroup()
      EgtRemoveInfo(Id, ITG_PROD_ERR)
      EgtRemoveInfo(Id, ITG_PROD_MSG)
      EgtRemoveInfo(Id, ITG_PROD_ROT)
      MyMachGroupM.nCALC_GlobalState = CalcStates.NOTCALCULATED
      MyMachGroupM.nCALC_State = CalcStates.NOTCALCULATED
      MyMachGroupM.nCALC_GlobalERR = 0
      MyMachGroupM.nCALC_ERR = 0
      MyMachGroupM.nCALC_ROT = 0
      MyMachGroupM.nCALC_FALL = 0
      MyMachGroupM.sCALC_MSG = ""
      NotifyPropertyChanged(NameOf(Calc_Background))
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ROT_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ERR_Letter))
      NotifyPropertyChanged(NameOf(CALC_ERR_Foreground))
   End Sub

   ' funzione che aggiorna lo stato e gli errori dopo calcolo
   Public Overridable Sub CalcGlobalUpdate()
      MyMachGroupM.nCALC_GlobalERR = nCALC_ERR
      MyMachGroupM.nCALC_GlobalState = nCALC_State
      ' stato globale dei pezzi
      MyMachGroupM.bCALC_PartsGlobalState = CalcStates.NOTCALCULATED
      For Each Part In MyMachGroupM.PartMList
         If Part.nCALC_GlobalState = CalcStates.NOTCALCULATED And nCALC_State < CalcStates.ERROR_ Then
            MyMachGroupM.nCALC_GlobalState = Part.nCALC_GlobalState
            MyMachGroupM.nCALC_GlobalERR = Part.nCALC_GlobalERR
            Exit For
         ElseIf Part.nCALC_GlobalState > MyMachGroupM.nCALC_GlobalState Then
            MyMachGroupM.nCALC_GlobalState = Part.nCALC_GlobalState
            MyMachGroupM.nCALC_GlobalERR = Part.nCALC_GlobalERR
         End If
         If Part.nCALC_GlobalState > MyMachGroupM.bCALC_PartsGlobalState Then
            MyMachGroupM.bCALC_PartsGlobalState = Part.nCALC_GlobalState
         End If
         If Part.nCALC_ROT <> 0 Then
            MyMachGroupM.m_nCALC_ROT = Part.nCALC_ROT
         End If
         If Part.nCALC_FALL <> 0 Then
            MyMachGroupM.nCALC_FALL = Part.nCALC_FALL
         End If
      Next

      NotifyPropertyChanged(NameOf(Calc_Background))
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ROT_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ERR_Letter))
      NotifyPropertyChanged(NameOf(CALC_ERR_Foreground))
   End Sub

   Public Sub CalcTimeUpdate(TIME As Integer)
      EgtSetInfo(Id, ITG_PROD_TIME, TIME, True)
      nCALC_TIME = TIME
      NotifyPropertyChanged(NameOf(sUnitTime))
   End Sub

   Public Overridable Sub CALCEnd()
   End Sub

#End Region    ' Calc

#Region "Supervisor"

   Public Sub SentToSupervisor()
      MyMachGroupM.SetProductionState(ItemState.Assigned)
      NotifyPropertyChanged(NameOf(Background))
   End Sub

   Public Sub ResetProduce()
      m_bCNReCalculated = False
      m_bToBeProduced = False
      m_bSendingToMachine = False
      m_bSentToMachine = False
      NotifyPropertyChanged(NameOf(Production_Background))
   End Sub

#End Region    ' Supervisor

#Region "Parts"

   Protected MustOverride Sub CreatePartVMList()

   Public MustOverride Sub RefreshPartList()

#End Region    ' Parts

#End Region    ' METHODS

#Region "COMMANDS"

#Region "DeleteMachGroup"

   ' Returns a command that manage the MainWindow_Unloaded command
   Public ReadOnly Property DeleteMachGroup_Command As ICommand
      Get
         If m_cmdDeleteMachGroup Is Nothing Then
            m_cmdDeleteMachGroup = New Command(AddressOf DeleteMachGroupCmd)
         End If
         Return m_cmdDeleteMachGroup
      End Get
   End Property

   Public Sub DeleteMachGroupCmd()
      DeleteMachGroup()
   End Sub

   Public Overridable Sub DeleteMachGroup(Optional bMultipleCommand As Boolean = False)
      ' elimino tutte le copie
      Dim nRawPartId As Integer = EgtGetFirstRawPart()
      Dim nBeamId As Integer = EgtGetFirstPartInRawPart(nRawPartId)
      While nRawPartId <> GDB_ID.NULL
         EgtRemovePartFromRawPart(nBeamId)
         EgtErase(nBeamId)
         nRawPartId = EgtGetNextRawPart(nRawPartId)
         nBeamId = EgtGetFirstPartInRawPart(nRawPartId)
      End While
      ' elimino MachGroup
      EgtRemoveMachGroup(Me.Id)
   End Sub

#End Region ' DeleteMachGroup

#Region "ProduceMachGroup"

   ' Returns a command that manage the MainWindow_Unloaded command
   Public ReadOnly Property ProduceMachGroup_Command As ICommand
      Get
         If m_cmdProduceMachGroup Is Nothing Then
            m_cmdProduceMachGroup = New Command(AddressOf ProduceMachGroup)
         End If
         Return m_cmdProduceMachGroup
      End Get
   End Property

   ' Manage the MainWindow_Unloaded event. This method is invoked by the cmdMainWindow_Unloaded.
   Public Overridable Sub ProduceMachGroup()
   End Sub

#End Region ' ProduceMachGroup

#End Region    ' COMMANDS

#Region "EVENTS"

   Protected MustOverride Sub OnPartAdded(sender As Object, e As PartAddedEventArgs)

   Private Sub OnPartRemoved(sender As Object, e As PartAddedEventArgs)
      Dim PartVM As PartVM = PartVMList.FirstOrDefault(Function(x) x.PartM Is e.m_NewPart)
      If Not IsNothing(PartVM) Then PartVMList.Remove(PartVM)
   End Sub

   Protected Sub OnPartVMListChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
      If e.Action = NotifyCollectionChangedAction.Add Then
         If Not IsNothing(e.NewItems) AndAlso e.NewItems.Count > 0 Then
            For Each PartVM As PartVM In e.NewItems
               AddHandler PartVM.PropertyChanged, AddressOf OnPartVMPropertyChanged
            Next
         End If
      End If
      If e.Action = NotifyCollectionChangedAction.Remove Then
         If Not IsNothing(e.OldItems) AndAlso e.OldItems.Count > 0 Then
            For Each PartVM As PartVM In e.OldItems
               RemoveHandler PartVM.PropertyChanged, AddressOf OnPartVMPropertyChanged
               MyMachGroupM.PartMList.Remove(PartVM.PartM)
            Next
         End If
      End If
      If e.Action = NotifyCollectionChangedAction.Move Then
         Dim ItemVM As PartVM = e.OldItems(0)
         MyMachGroupM.PartMList.RemoveAt(e.OldStartingIndex)
         MyMachGroupM.PartMList.Insert(e.NewStartingIndex, ItemVM.PartM)
      End If
   End Sub

   Protected Overridable Sub OnPartVMPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
      Select Case e.PropertyName
         Case NameOf(sender.sPOSX), NameOf(sender.sPOSY), NameOf(sender.bFLIP), NameOf(sender.sROT)
            ' setto pezzo da ricalcolare
            ResetCalcMachGroup()
      End Select
   End Sub

#End Region    ' EVENTS

End Class
