Imports EgtBEAMWALL.Core
Imports EgtBEAMWALL.Core.ConstBeam
Imports EgtBEAMWALL.Core.ConstGen
Imports EgtBEAMWALL.Core.ConstIni
Imports EgtUILib
Imports EgtWPFLib5
Imports System.IO
Imports System.Threading
Imports System.Windows.Threading

Public Class MainWindowVM
   Inherits VMBase

   Private m_SupervisorCommThread As Thread
   Private m_Supervisor_Timer As New DispatcherTimer

   ' Riferimento al Model della MainWindow
   Private m_MainWindowM As MainWindowM
   Friend ReadOnly Property MainWindowM As MainWindowM
      Get
         Return m_MainWindowM
      End Get
   End Property

   ' Variabile che indica che il programma è stato avviato correttamente (sia la mappa che l'ambiente Egt)
   Private m_bInitStatus As Boolean
   Friend ReadOnly Property bInitStatus As Boolean
      Get
         Return m_bInitStatus
      End Get
   End Property

   ' Titolo
   Private m_Title As String = ""
   Public ReadOnly Property Title As String
      Get
         Return m_Title
      End Get
   End Property

   ' proprietà che seleziona la giusta pagina del TabControl
   Public Property nSelTabPage As Integer
      Get
         Return If(IsNothing(Map.refMainMenuVM.SelPage) OrElse Map.refMainMenuVM.SelPage = -1 OrElse Map.refMainMenuVM.SelPage = Pages.VIEW OrElse Map.refMainMenuVM.SelPage = Pages.MACHINING, 0, 1)
      End Get
      Set(value As Integer)
      End Set
   End Property

   Private m_MachinePanelVM As MachinePanelVM
   Public ReadOnly Property MachinePanelVM As MachinePanelVM
      Get
         Return m_MachinePanelVM
      End Get
   End Property

   'Friend m_SupervisorStop As Boolean = False
   Private BlockedWnd As BlockedWndV

   ' definizione comandi
   Private m_cmdAboutBox As ICommand
   Private m_cmdCloseApplication As ICommand

#Region "CONSTRUCTOR"

   Sub New()
      ' Avvio l'inizializzazione della mappa passandogli il riferimento al MainWindowVM
      Map.BeginInit(Me)
      ' Creo Model della MainWindow
      m_MainWindowM = New MainWindowM
      ' inizializzo machine panel
      m_MachinePanelVM = New MachinePanelVM
      ' inizializzo contatore per blocco da supervisore
      m_Supervisor_Timer.Interval = TimeSpan.FromMilliseconds(500)
      AddHandler m_Supervisor_Timer.Tick, AddressOf SupervisorTimer_Tick
      m_Supervisor_Timer.Start()
   End Sub

#End Region    ' CONSTRUCTOR

#Region "METHODS"

   Friend Sub SetTitle(sTitle As String)
      m_Title = sTitle
      NotifyPropertyChanged(NameOf(Title))
   End Sub
   Public Sub UpdateTitle()
      m_Title = ""
      Select Case Map.refMainMenuVM.SelPage
         Case Pages.VIEW
            If GetMainPrivateProfileInt(S_GENERAL, K_PROJECTMODE, 0) = 1 Then
               If Not IsNothing(Map.refProjManagerVM.CurrProj) Then
                  If Map.refProjManagerVM.CurrProj.bIsNew Then m_Title = "New - "
                  If Not IsNothing(Map.refProjManagerVM.CurrProj.nProdId) AndAlso Map.refProjManagerVM.CurrProj.nProdId > 0 Then
                     m_Title &= Map.refProjManagerVM.CurrProj.nProdId.ToString("0000") & " - "
                  End If
                  m_Title &= Map.refProjManagerVM.CurrProj.sBTLFileName
               End If
            Else
               If Not IsNothing(Map.refProjManagerVM.CurrProj) Then
                  If Map.refProjManagerVM.CurrProj.bIsNew Then m_Title = "New - "
                  m_Title &= Map.refProjManagerVM.CurrProj.nProjId.ToString("0000") & " - " & Map.refProjManagerVM.CurrProj.sBTLFileName
               End If
            End If
         Case Pages.MACHINING
            If GetMainPrivateProfileInt(S_GENERAL, K_PROJECTMODE, 0) = 1 Then
               If Not IsNothing(Map.refProdManagerVM.CurrProd) Then
                  If Map.refProdManagerVM.CurrProd.bIsNew Then m_Title = "New - "
                  m_Title &= Map.refProdManagerVM.CurrProd.nProdId.ToString("0000") & " - " & Map.refProdManagerVM.CurrProd.sName
               End If
            Else
               If Not IsNothing(Map.refProdManagerVM.CurrProd) Then
                  If Map.refProdManagerVM.CurrProd.bIsNew Then m_Title = "New - "
                  m_Title &= Map.refProdManagerVM.CurrProd.nProdId.ToString("0000") & " - " & Map.refProdManagerVM.CurrProd.sBTLFileName
               End If
            End If
         Case Pages.CONFIG
            m_Title = "Configuration Page"
      End Select
      m_Title &= " - EgtBEAMWALL"
      NotifyPropertyChanged(NameOf(Title))
   End Sub

   Friend Sub ContentRendered()
      DbControllers.Init()
      '' chiamata a caso su Db per inizializzarlo
      DbControllers.m_ProjController.FindByProjDbId(0)
      ' Verifico che l'inizializzazione di tutte le parti del programma sia andata a buon fine
      If Map.EndInit() Then
         m_bInitStatus = True
         ' altrimenti chiudo il programma
      Else
         m_bInitStatus = False
      End If
      ' Aggiorno visualizzazione unità di misura
      'Map.refStatusBarVM.SetMeasureUnit(If(EgtUiUnitsAreMM(), MeasureUnitOpt.MM, MeasureUnitOpt.INCH))
      ' imposto MainWindow per finestra di Loading
      LoadingWndHelper.SetMainWindow(Application.Current.MainWindow)
      ' leggo riga di comando
      Dim nCommandType As Integer = 0
      Dim nPage As Pages = Pages.VIEW
      Dim nProdId As Integer = 0
      If ProcessCommandLine(nCommandType, nPage, nProdId) Then
         Select Case nCommandType
            Case 1
               Map.refProdManagerVM.SetCurrProd(nProdId)
            Case 2
               ' pagina gia' impostata nella variabile
         End Select
      Else
         ' setto il primo file dalla lista degli MRU come progetto corrente da aprire
         Dim sLastProjectPath As String = String.Empty
         GetMainPrivateProfileString(S_MRUPROJFILES, K_FILE & "1", String.Empty, sLastProjectPath)
         If Not String.IsNullOrWhiteSpace(sLastProjectPath) AndAlso File.Exists(sLastProjectPath) Then
            ' ricavo l'Id e il progetto associato per l'apertura di quest'ultimo
            Dim PjId As Integer = 0
            Dim sPjId As String = Path.GetFileNameWithoutExtension(sLastProjectPath)
            Integer.TryParse(sPjId, PjId)
            Map.refProjManagerVM.SetCurrProj(PjId)
         End If
      End If
      ' seleziono pagina da aprire
      Map.refMainMenuVM.SelPage = nPage

      ' inizializzo thread di aggiornamento e comunicazione con DB
      ' creo thread gestione macchina
      m_SupervisorCommThread = New Thread(Sub()
                                             SupervisorCommThread.SupervisorCommThreadFunction()
                                          End Sub)
      m_SupervisorCommThread.SetApartmentState(ApartmentState.STA)
      ' avvio thread di gestione della macchina che avvia la connessione
      m_SupervisorCommThread.Start()

      ' verifico se richiedere di fare backup
      If Map.refConfigurationPageVM.SelReminder.Id <> 0 Then
         Dim sBackupFolder As String = Map.refMainWindowVM.MainWindowM.sDataDir & "\Backup"
         Dim nYear As Integer = 0
         Dim nMonth As Integer = 0
         Dim nDay As Integer = 0
         Dim LastBackupDate As Date = Date.MinValue
         ' verifico se esiste backup
         If Directory.Exists(sBackupFolder) Then
            ' cerco ultimo backup
            Dim YearDirList() As String = Directory.GetDirectories(sBackupFolder)
            For YearIndex = YearDirList.Length - 1 To 0 Step -1
               nYear = 0
               Integer.TryParse(Path.GetFileName(YearDirList(YearIndex)), nYear)
               Dim sYearDir As String = sBackupFolder & "\" & nYear
               Dim MonthDirList() As String = Directory.GetDirectories(sYearDir)
               For MonthIndex = MonthDirList.Length - 1 To 0 Step -1
                  nMonth = 0
                  Integer.TryParse(Path.GetFileName(MonthDirList(MonthIndex)), nMonth)
                  Dim sMonthDir As String = sYearDir & "\" & nMonth
                  Dim DayDirList() As String = Directory.GetDirectories(sMonthDir)
                  For DayIndex = DayDirList.Length - 1 To 0 Step -1
                     nDay = 0
                     Integer.TryParse(Path.GetFileName(DayDirList(DayIndex)), nDay)
                     Dim sDayDir As String = sMonthDir & "\" & nDay
                     Dim VersionList() As String = Directory.GetFiles(sDayDir)
                     If VersionList.Length > 0 Then
                        Dim nMaxVersion As Int64 = VersionList.Max(Function(x) Int64.Parse(Path.GetFileNameWithoutExtension(x)))
                        LastBackupDate = New Date(nYear, nMonth, nDay)
                        Exit For
                     End If
                  Next
                  If LastBackupDate <> Date.MinValue Then Exit For
               Next
               If LastBackupDate <> Date.MinValue Then Exit For
            Next
         End If
         Dim TimeFromLastBackup As TimeSpan = DateTime.Now - LastBackupDate
         If TimeFromLastBackup > TimeSpan.FromDays(Map.refConfigurationPageVM.SelReminder.Id) Then
            If MessageBox.Show(String.Format(EgtMsg(61987), Map.refConfigurationPageVM.SelReminder.Name), EgtMsg(15002), MessageBoxButton.YesNo, MessageBoxImage.Warning) = MessageBoxResult.Yes Then
               Map.refConfigurationPageVM.Backup(True)
            End If
         End If
      End If

   End Sub

   Friend Function ProcessCommandLine(ByRef nCommandType As Integer, ByRef nPage As Pages, ByRef nProdId As Integer) As Boolean
      ' Se non ci sono veri parametri su linea di comando, esco (il primo è sempre il nome del programma)
      If Environment.GetCommandLineArgs.Count() <= 1 Then Return False
      ' Recupero primo parametro che dovrebbe essere il tipo di modalita' riga di comando
      Dim sFile As String = Environment.GetCommandLineArgs(1)
      If String.IsNullOrWhiteSpace(sFile) OrElse Not Integer.TryParse(sFile, nCommandType) OrElse nCommandType <= 0 Then Return False
      Select Case nCommandType
         Case 1         ' apri progetto in ottimizzatore
            ' recupero secondo parametro
            Dim sProdId As String = Environment.GetCommandLineArgs(2)
            If Not Integer.TryParse(sProdId, nProdId) OrElse nProdId <= 0 Then Return False
            nPage = Pages.MACHINING
            Return True
         Case 2         ' apri pagina specifica senza progetto specifico
            ' recupero secondo parametro
            Dim sPage As String = Environment.GetCommandLineArgs(2)
            If Not Integer.TryParse(sPage, nPage) OrElse (nPage <> Pages.VIEW AndAlso nPage <> Pages.MACHINING) Then Return False
            Return True
      End Select
      Return False
   End Function

   Friend Sub KeyDown(PressedKey As Key)
      ' Con ESC esco dall'azione corrente
      Select Case PressedKey
         Case Key.Escape
            ' se in modifica L250
            If Map.refFreeContourManagerVM.bIsActive Then
               ' se in modifica testo angolo di inclinazione
               If Map.refFreeContourManagerVM.bIsModifyingTextAngle Then
                  Map.refFreeContourManagerVM.CloseIsModifyingTextAngle(False)
               ElseIf Map.refFreeContourManagerVM.bIsCreatingPath Then
                  Map.refFreeContourManagerVM.CreatingPathEnd()
               ElseIf Map.refFreeContourManagerVM.bIsOpeningCurveCompo Then
                  Map.refFreeContourManagerVM.CloseIsOpeningCurveCompo()
               End If
               ' reset Azione corrente
               Map.refSceneHostVM.MainController.ResetStatus()
               Map.refFreeContourInputVM.ResetInputBox()
            End If
            ' se misura attiva, la disattivo
            If Map.refInstrumentPanelVM.GetDistIsChecked Then
               Map.refInstrumentPanelVM.SetGetDistance_IsChecked(False)
            End If
            ' se Reset Macchina è aperto 
            If (nSelTabPage = Pages.VIEW Or nSelTabPage = Pages.MACHINING) AndAlso Map.refCALCPanelVM.ChooseMachine_Visibility = Visibility.Visible Then
               Map.refCALCPanelVM.CloseResetMachine()
            End If
            ' pulisco output
            Map.refMyStatusBarVM.ClearOutputMessage()
      End Select
   End Sub

   Friend m_ManagingSupervisorStop As Boolean = False

   Private Sub SupervisorTimer_Tick()
      If SupervisorCommThread.bViewerOptimizerBlocked And Not m_ManagingSupervisorStop Then
         m_ManagingSupervisorStop = True
         BlockedWnd = New BlockedWndV(Application.Current.MainWindow, New BlockedWndVM)
         BlockedWnd.ShowDialog()
      ElseIf Not SupervisorCommThread.bViewerOptimizerBlocked And m_ManagingSupervisorStop Then
         m_ManagingSupervisorStop = False
         BlockedWnd.Close()
      End If
   End Sub

#End Region    ' METHODS

#Region "COMMANDS"

#Region "AboutBoxCommand"

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

   ' Manage the MainWindow_Unloaded event. This method is invoked by the cmdMainWindow_Unloaded.
   Public Sub AboutBox(ByVal param As Object)
      Dim AboutBoxWindow As New AboutBoxV
      AboutBoxWindow.Owner = Application.Current.MainWindow
      AboutBoxWindow.ShowDialog()
   End Sub

#End Region ' AboutBoxCommand

#Region "CloseApplicationCommand"

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

   ' Manage the MainWindow_Unloaded event. This method is invoked by the cmdMainWindow_Unloaded.
   Public Sub CloseApplication(ByVal param As Object)
      If (Keyboard.Modifiers And ModifierKeys.Alt) = ModifierKeys.Alt OrElse Keyboard.IsKeyDown(Key.F4) Then
         Return
      End If
      ' verifico se sono in modifica percorso libero
      If Map.refFreeContourManagerVM.bIsActive Then
         MessageBox.Show(EgtMsg(61994))
         Return
      End If
      ' verifico se sto facendo backup
      If Map.refConfigurationPageVM.bBackupRunning Then
         MessageBox.Show(EgtMsg(62101), EgtMsg(15002), MessageBoxButton.OK, MessageBoxImage.Warning)              'Backup running! Impossible closing the software until finish the backup process!
         Return
      End If
      If Map.refConfigurationPageVM.bRestoreRunning Then
         MessageBox.Show(EgtMsg(62102), EgtMsg(15002), MessageBoxButton.OK, MessageBoxImage.Warning)                 'Restore running! Impossible closing the software until finish the restore process!
         Return
      End If
      'If Map.refOptionPanelVM.SelItem = OptionPanelVM.Tabs.SIMUL Then
      '   Map.refSimulTabVM.ResetSimulation()
      'End If
      ' Imposto contesto principale
      'EgtSetCurrentContext(Map.refSceneHostVM.MainScene.GetCtx())
      ' Gestisco eventuale file corrente modificato
      Dim bOk As Boolean = True
      Select Case Map.refMainMenuVM.SelPage
         Case Pages.VIEW
            bOk = ProjFileVM.VerifyProjectModification(Map.refProjManagerVM.CurrProj, ProjectType.PROJ)
         Case Pages.MACHINING
            bOk = ProdFileVM.VerifyProjectModification(Map.refProdManagerVM.CurrProd) <> MessageBoxResult.Cancel
         Case Pages.CONFIG
            ' Verifica modifica parametri Macchina e chiedo il salvataggio
            Map.refConfigurationPageVM.VerifyConfigPageModification()
      End Select
      ' se salvataggio annullato, rimango
      If Not bOk Then Return
      Dim bAllowClose As Boolean = Map.refSceneHostVM.MainController.ManageModified()
      ' Salvo impostazione macchina corrente
      Map.refMachinePanelVM.SaveCurrentMachine()
      ' Se non confermata chiusura, esco
      If Not bAllowClose Then Return
      ' termino thread di comunicazione con Db ed altri programmi
      SupervisorCommThread.StopThread()
      ' salvo modo di visualizzazione
      WriteMainPrivateProfileString(S_SCENE, K_SHOWMODE, EgtGetShowMode().ToString)
      ' salvo visualizzazione assemblato
      WriteMainPrivateProfileString(S_SCENE, K_SHOWBUILDING, If(Map.refShowBeamPanelVM.ShowBuilding_IsChecked, 1, 0))
      ' Salvo nome ultimo file (per gestire bene multi istanza)
      Dim sFilePath As String = String.Empty
      If EgtGetCurrFilePath(sFilePath) Then WriteMainPrivateProfileString(S_GENERAL, K_LASTPROJ, sFilePath)
      ' tolgo lock da file aperto
      If Map.refMainMenuVM.SelPage = Pages.VIEW And Not IsNothing(Map.refProjManagerVM.CurrProj) Then
         DbControllers.m_ProjController.LockByProjId(Map.refProjManagerVM.CurrProj.nProjId, False, Map.refMainWindowVM.MainWindowM.GetKeyNumber())
      ElseIf Map.refMainMenuVM.SelPage = Pages.MACHINING And Not IsNothing(Map.refProdManagerVM.CurrProd) Then
         DbControllers.m_ProdController.LockByProdId(Map.refProdManagerVM.CurrProd.nProdId, False, Map.refMainWindowVM.MainWindowM.GetKeyNumber())
      End If
      ' Termino il Model
      m_MainWindowM.Close()
      ' Termino il programma
      Application.Current.Shutdown()
   End Sub

#End Region ' CloseApplicationCommand

#End Region    ' COMMANDS

End Class
