Imports System.Threading
Imports System.Math
Imports EgtUILib
Imports EgtWPFLib5
Imports EgtBEAMWALL.Core
Imports System.IO

Public Class MainWindowM

#Region "FIELDS"

   ' massimo numero di istanze del programma ammesse
   Const MAX_INST As Integer = 1

   Private m_sDataRoot As String = String.Empty
   Friend ReadOnly Property sDataRoot As String
      Get
         Return m_sDataRoot
      End Get
   End Property

   Private m_sDataDir As String = String.Empty
   Friend ReadOnly Property sDataDir As String
      Get
         Return m_sDataDir
      End Get
   End Property

   Private m_sConfigDir As String = String.Empty
   Public ReadOnly Property sConfigDir As String
      Get
         Return m_sConfigDir
      End Get
   End Property

   Private m_nDebug As Integer = 0

   Private m_objMutex As Mutex

   Private m_bFirstInstance As Boolean = False
   Friend ReadOnly Property bFirstInstance As Boolean
      Get
         Return m_bFirstInstance
      End Get
   End Property

   Private m_nInstance As Integer = 0
   Friend ReadOnly Property nInstance As Integer
      Get
         Return m_nInstance
      End Get
   End Property

   Private m_nUserLevel As Integer = 1
   Friend ReadOnly Property nUserLevel As Integer
      Get
         Return m_nUserLevel
      End Get
   End Property

   Private m_nKeyLevel As Integer = 0
   Friend ReadOnly Property nKeyLevel As Integer
      Get
         Return m_nKeyLevel
      End Get
   End Property

   Private m_nKeyOptions As UInteger = 0
   Friend ReadOnly Property nKeyOptions As Integer
      Get
         Return m_nKeyOptions
      End Get
   End Property

   Private m_bAutoNestOption As Boolean = False
   Friend ReadOnly Property AutoNestOption As Boolean
      Get
         Return m_bAutoNestOption
      End Get
   End Property

   Friend ReadOnly Property sVersion As String
      Get
         Return My.Application.Info.Version.Major.ToString() & "." &
                My.Application.Info.Version.Minor.ToString() &
                (ChrW(97 - 1 + My.Application.Info.Version.Build)).ToString() &
                My.Application.Info.Version.Revision.ToString()
      End Get
   End Property

   Private m_sTempDir As String
   Friend ReadOnly Property sTempDir As String
      Get
         Return m_sTempDir
      End Get
   End Property
   Private m_sMachinesRoot As String
   Friend ReadOnly Property sMachinesRoot As String
      Get
         Return m_sMachinesRoot
      End Get
   End Property
   Friend ReadOnly Property sMachineMacroDir As String
      Get
         Return m_sMachinesRoot & MACRO_DFL_DIR
      End Get
   End Property
   Private m_sBeamRoot As String
   Friend ReadOnly Property sBeamRoot As String
      Get
         Return m_sBeamRoot
      End Get
   End Property
   Private m_sWallRoot As String
   Friend ReadOnly Property sWallRoot As String
      Get
         Return m_sWallRoot
      End Get
   End Property
   Private m_sWarehouseRoot As String
   Friend ReadOnly Property sWarehouseRoot As String
      Get
         Return m_sWarehouseRoot
      End Get
   End Property
   Private m_sToolMakersDir As String
   Friend ReadOnly Property sToolMakersDir As String
      Get
         Return m_sToolMakersDir
      End Get
   End Property
   Private m_sResourcesRoot As String
   Friend ReadOnly Property sResourcesRoot As String
      Get
         Return m_sResourcesRoot
      End Get
   End Property
   Private m_sLogFile As String
   Friend ReadOnly Property sLogFile As String
      Get
         Return m_sLogFile
      End Get
   End Property

   Private m_sProjsDir As String
   Friend ReadOnly Property sProjsDir As String
      Get
         Return m_sProjsDir
      End Get
   End Property
   Private m_sProdsDir As String
   Friend ReadOnly Property sProdsDir As String
      Get
         Return m_sProdsDir
      End Get
   End Property

   Friend ReadOnly Property sZebraPrinterExe As String
      Get
         Dim sPrinterExe As String = ""
         GetMainPrivateProfileString(S_PRINTER, K_ZEBRAUTILITIES, ZEBRAPRINTER_EXE, sPrinterExe)
         Return sPrinterExe
      End Get
   End Property

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

#End Region    ' FIELDS

#Region "CONSTRUCTOR"

   Sub New()
      InitializeEgtEnvironment()
   End Sub

#End Region    ' CONSTRUCTOR

#Region "METHODS"

   Private Sub InitializeEgtEnvironment()
      '' Abilito drag and drop
      'Me.AllowDrop = True
      ' Impostazione path radice per i dati
      m_sDataRoot = System.AppDomain.CurrentDomain.BaseDirectory
      If EgtUILib.GetPrivateProfileString(S_DATA, K_DATAROOT, "", m_sDataRoot, m_sDataRoot & "\" & DAT_FILE_NAME) = 0 Then
         m_sDataRoot = System.AppDomain.CurrentDomain.BaseDirectory
      End If
      ' Impostazione direttorio di configurazione
      m_sConfigDir = m_sDataRoot & "\" & CONF_DIR
      ' Impostazione direttorio per file temporanei
      m_sTempDir = m_sDataRoot & "\" & TEMP_DIR
      ' Impostazione path Ini file
      IniFile.m_sIniFile = m_sConfigDir & "\" & Core.ConstIni.INI_FILE_NAME
      ' Impostazione path BTL Ini File
      BTLIniFile.m_sBTLIniFile = m_sConfigDir & "\" & BTLFEATURES_FILE_NAME
      ' Impostazione path Ini file DataGrid
      DataGridColumnsIniFile.m_sDataGridColumnsIniFile = m_sConfigDir & "\" & DATAGRIDCOLUMNS_FILE_NAME
      ' Impostazione path Ini file Dimensioni
      DimensionsIniFile.m_sDimensionsIniFile = m_sConfigDir & "\" & ConstDims.DIMENSIONS_FILE_NAME
      ' Impostazione path resources dir
      m_sResourcesRoot = m_sDataRoot & "\" & RES_DIR
      ' Impostazione direttorio per le macchine
      If GetMainPrivateProfileString(S_MACH, K_MACHINESDIR, "", m_sMachinesRoot) = 0 Then
         m_sMachinesRoot = m_sDataRoot & "\" & MACHINES_DFL_DIR
      End If
      ' Impostazione direttorio per toolmakers
      If GetMainPrivateProfileString(S_MACH, K_TOOLMAKERSDIR, "", m_sToolMakersDir) = 0 Then
         m_sToolMakersDir = m_sDataRoot & "\" & TOOLMAKERS_DFL_DIR
      End If
      ' Impostazione direttori Beam e Wall
      If GetMainPrivateProfileString(S_BEAM, K_BEAMBASEDIR, "", m_sBeamRoot) = 0 Then
         m_sBeamRoot = m_sDataRoot & "\" & BEAM_DIR
      End If
      If GetMainPrivateProfileString(S_WALL, K_WALLBASEDIR, "", m_sWallRoot) = 0 Then
         m_sWallRoot = m_sDataRoot & "\" & WALL_DIR
      End If
      ' Impostazione direttorio magazzino grezzi
      If GetMainPrivateProfileString(S_GENERAL, K_DATADIR, "", m_sDataDir) = 0 Then
         m_sDataDir = m_sDataRoot
      End If
      ' Verifico indice di istanza
      ManageInstance()
      ' Imposto tipo di chiave
      EgtSetLockType(KEY_TYPE.HW)
      ' Leggo e imposto chiave di protezione
      Dim sLicFileName As String = String.Empty
      GetMainPrivateProfileString(S_GENERAL, K_LICENCE, LIC_FILE_NAME, sLicFileName)
      Dim sLicFile As String = m_sConfigDir & "\" & sLicFileName
      Dim sKey As String = String.Empty
      EgtUILib.GetPrivateProfileString(S_LICENCE, K_KEY, "", sKey, sLicFile)
      EgtSetKey(sKey)
      Dim sNestKey As String = ""
      EgtUILib.GetPrivateProfileString(S_LICENCE, K_NESTKEY, "", sNestKey, sLicFile)
      EgtSetNestKey(sNestKey)
      ' Verifico abilitazione nesting automatico
      m_bAutoNestOption = Not String.IsNullOrWhiteSpace(sNestKey)
      ' Impostazioni per chiave di rete
      Dim bNetKey As Boolean = ( GetMainPrivateProfileInt( S_GENERAL, K_NETKEY, 0) = 1)
      EgtSetNetHwKey( bNetKey)
      Dim sLockId As String = ""
      EgtUILib.GetPrivateProfileString( S_LICENCE, K_LOCKID, "", sLockId, sLicFile)
      If Not String.IsNullOrEmpty( sLockId) Then
         EgtSetLockId( sLockId)
      End If
      ' Recupero livello e opzioni della chiave
      Dim bKey As Boolean = EgtGetKeyLevel(5327, 2611, 1, m_nKeyLevel) And
                            EgtGetKeyOptions(5327, 2611, 1, m_nKeyOptions)
      ' Inizializzazione generale di EgtInterface
      m_nDebug = GetMainPrivateProfileInt(S_GENERAL, K_DEBUG, 0)
      m_sLogFile = m_sTempDir & "\" & SUPGENLOG_FILE_NAME.Replace("#", m_nInstance.ToString())
      Dim sLogMsg As String = "User " & Environment.MachineName & "\" & Environment.UserName & " (" & m_nInstance.ToString() & ")" & vbLf &
                              My.Application.Info.Title.ToString() & " ver. " &
                              My.Application.Info.Version.Major.ToString() &
                              "." & My.Application.Info.Version.Minor.ToString() &
                              (ChrW(97 - 1 + My.Application.Info.Version.Build)).ToString() &
                              My.Application.Info.Version.Revision.ToString()
      EgtInit(m_nDebug, m_sLogFile, sLogMsg)
      EgtSetTempDir(m_sTempDir)
      EgtSetIniFile(IniFile.m_sIniFile)
      ' Leggo direttorio dei messaggi (se manca uso direttorio di configurazione)
      Dim sMsgDir As String = String.Empty
      If GetMainPrivateProfileString(S_GENERAL, K_MESSAGESDIR, "", sMsgDir) = 0 Then
         sMsgDir = m_sConfigDir
      End If
      ' Leggo lingua corrente
      Dim sLanguage As String = String.Empty
      GetMainPrivateProfileString(S_GENERAL, K_MESSAGES, "", sLanguage)
      ' Recupero nome file dei messaggi della lingua corrente
      Dim sMsgName As String = "EgalTechIta.txt"
      Dim nIndex As Integer = 1
      While True
         Dim ReadLanguage As Language = GetMainPrivateProfileLanguage(S_LANGUAGES, K_LANGUAGE & nIndex)
         If IsNothing(ReadLanguage) Then Exit While
         If String.Compare(ReadLanguage.Name, sLanguage, True) = 0 Then
            sMsgName = ReadLanguage.FilePath
            Exit While
         End If
         nIndex += 1
      End While
      ' Leggo file messaggi
      Dim sMsgFilePath As String = sMsgDir & "\" & sMsgName
      If Not EgtLoadMessages(sMsgFilePath) Then
         EgtOutLog("Error in EgtLoadMessages")
      End If
      ' Leggo e imposto unità di misura per interfaccia utente
      EgtSetUiUnits(GetMainPrivateProfileInt(S_SCENE, K_MMUNITS, 1) <> 0)
      ' Leggo e imposto livello utilizzatore
      m_nUserLevel = Math.Min(m_nKeyLevel, GetMainPrivateProfileInt(S_GENERAL, K_USERLEVEL, 1))
      ' Imposto dir font Nfe e font default
      Dim sNfeDir As String = String.Empty
      GetMainPrivateProfileString(S_GEOMDB, K_NFEFONTDIR, "", sNfeDir)
      Dim sDefFont As String = String.Empty
      GetMainPrivateProfileString(S_GEOMDB, K_DEFAULTFONT, "", sDefFont)
      EgtSetFont(sNfeDir, sDefFont)
      ' imposto dir di default per libreria Lua e lancio libreria di base
      Dim sLuaLibsDir As String = String.Empty
      GetMainPrivateProfileString(S_LUA, K_LIBSDIR, "", sLuaLibsDir)
      EgtSetLuaLibs(sLuaLibsDir)
      Dim sLuaBaseLib As String = String.Empty
      GetMainPrivateProfileString(S_LUA, K_BASELIB, "EgtBase", sLuaBaseLib)
      EgtLuaRequire(sLuaBaseLib)
      ' verifico se stampante attiva
      Dim sPrinterLink As String = ""
      Dim nPrinterLink As Integer = 0
      GetMainPrivateProfileString(S_PRINTER, K_ENABLE, "", sPrinterLink)
      If Integer.TryParse(sPrinterLink, nPrinterLink) Then
         m_bPrinterLink = nPrinterLink > 0
      End If
      ' Info su opzioni chiave
      EgtOutLog("KeyOptions : " & bKey.ToString() & " " & m_nKeyOptions.ToString())
   End Sub

   Private Sub ManageInstance()
      Dim bCreated As Boolean
      Try
         m_objMutex = New Mutex(True, "Global\EgtBEAMWALL.Supervisor", bCreated)
      Catch
         bCreated = False
      End Try
      m_bFirstInstance = bCreated
      If bCreated Then
         ' Prima istanza
         m_nInstance = 1
         ' Aggiorno stato istanze attive
         WriteMainPrivateProfileString(S_GENERAL, K_SUPERVISOR_INSTANCES, m_nInstance.ToString())
         ' Rilascio il possesso del mutex
         m_objMutex.ReleaseMutex()
      Else
         ' Leggo il massimo numero di istanze ammesse
         Dim nMaxInst As Integer = GetMainPrivateProfileInt(S_GENERAL, K_MAXINST, 1)
         nMaxInst = 1                  ' Max(1, Min(nMaxInst, MAX_INST))
         ' Richiedo il possesso del mutex
         Dim bOk As Boolean = False
         If m_objMutex.WaitOne(500) Then
            ' Cerco il primo indice di istanza libero
            Dim nTmp As Integer = GetMainPrivateProfileInt(S_GENERAL, K_SUPERVISOR_INSTANCES, 0)
            m_nInstance = 1
            Dim nMask As Integer = 1
            While (nTmp And nMask) <> 0 And m_nInstance <= MAX_INST
               m_nInstance += 1
               nMask *= 2
            End While
            ' Se nuova istanza nei limiti
            If m_nInstance <= nMaxInst Then
               bOk = True
               ' Aggiorno stato istanze attive
               nTmp += (1 << (m_nInstance - 1))
               WriteMainPrivateProfileString(S_GENERAL, K_SUPERVISOR_INSTANCES, nTmp.ToString())
            End If
            ' Rilascio il possesso del mutex
            m_objMutex.ReleaseMutex()
         End If
         ' Se non è possibile continuare
         If Not bOk Then
            ' porto in primo piano la prima istanza
            Dim bFound As Boolean = False
            ' processi del programma a 32 bit
            Dim localProc As Process() = Process.GetProcessesByName("EgtBEAMWALL.SupervisorR32")
            For Each p As Process In localProc
               If p.Id <> Process.GetCurrentProcess().Id Then
                  bFound = True
                  ShowWindow(p.MainWindowHandle, SW.SHOWMAXIMIZED)
                  Exit For
               End If
            Next
            ' se non trovati processi a 32 bit provo a 64 bit
            If Not bFound Then
               localProc = Process.GetProcessesByName("EgtBEAMWALL.SupervisorR64")
               For Each p As Process In localProc
                  If p.Id <> Process.GetCurrentProcess().Id Then
                     bFound = True
                     ShowWindow(p.MainWindowHandle, SW.SHOWMAXIMIZED)
                     Exit For
                  End If
               Next
            End If
            ' esco dal programma
            Environment.Exit(1)
         End If
      End If
   End Sub

   Friend Function GetKeyOption(nKeyOpt As KEY_OPT) As Boolean
      Return ((m_nKeyOptions And nKeyOpt) <> 0)
   End Function

   Friend Function GetMaxInstances() As Integer
      ' Leggo il massimo numero di istanze ammesse
      Dim nMaxInst As Integer = GetMainPrivateProfileInt(S_GENERAL, K_MAXINST, 1)
      Return 1             ' Max(1, Min(nMaxInst, MAX_INST))
   End Function

   Friend Sub UpdatePathForNetwork(sSharedFolder As String)
      m_sProjsDir = sSharedFolder & "\" & PROJS_DIR
      m_sProdsDir = sSharedFolder & "\" & PRODS_DIR
      ' imposto cartelle dei progetti
      Core.ProjectFileVM.Init(sProjsDir, sProdsDir)
   End Sub

   Friend Sub UpdatePathForKey(sKey As String)
      m_sProjsDir = m_sDataDir & "\" & sKey & "\" & PROJS_DIR
      m_sProdsDir = m_sDataDir & "\" & sKey & "\" & PRODS_DIR
      If Not Directory.Exists(m_sDataDir & "\" & sKey) Then
         Directory.CreateDirectory(m_sDataDir & "\" & sKey & "\" & PROJS_DIR)
         Directory.CreateDirectory(m_sDataDir & "\" & sKey & "\" & PRODS_DIR)
      End If
      ' imposto cartelle dei progetti
      Core.ProjectFileVM.Init(sProjsDir, sProdsDir)
   End Sub

   Friend Function GetKeyNumber() As Integer
      Dim sKey As String = ""
      Dim nKey As Integer = 0
      EgtGetKeyInfo(sKey)
      sKey = sKey.Replace(" ", "")
      If Not IsNothing(sKey) AndAlso sKey.Length > 11 Then
         If Integer.TryParse(sKey.Substring(3, 6), nKey) AndAlso nKey > 0 Then
            Return nKey
         End If
      End If
      Return -1
   End Function

   Friend Sub Close()
      ' Terminazione generale di EgtInterface
      EgtExit()
      ' Aggiorno istanze usate
      m_objMutex.WaitOne(1000)
      Dim nTmp As Integer = GetMainPrivateProfileInt(S_GENERAL, K_SUPERVISOR_INSTANCES, 0)
      nTmp -= (1 << (m_nInstance - 1))
      WriteMainPrivateProfileString(S_GENERAL, K_SUPERVISOR_INSTANCES, nTmp.ToString())
      m_objMutex.ReleaseMutex()
      ' Rilascio mutex
      If Not IsNothing(m_objMutex) Then m_objMutex.Close()
   End Sub

#End Region    ' METHODS

End Class
