#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7

#include <Misc.au3>

Dim $baseName = "yaP"
Dim $appName = StringRegExpReplace(@ScriptFullPath, "^.+\\(.+)\.\w{1,5}$", "$1")
Dim $rootdir = @ScriptDir & "/" & $baseName & "/"
Dim $ini = $appName & ".ini"
Dim $app, $commandLine, $silentBatch, $workDir, $multipleInstance, $secondInstance
Dim $beforeBatch, $beforeRegistry, $beforeRegistryIfEmpty, $beforeWait, $beforeSystemRefresh
Dim $afterBatch, $afterRegistry, $afterRegistryIfEmpty, $afterWait, $afterSystemRefresh

_Init()
_BeforeItems()
_Main()
_AfterItems()

Func _Init()    ; check ini presence and read settings
    ; check if ini exists
    If Not FileExists($ini) Then
        $ini = $baseName & ".ini"
        If Not FileExists($ini) Then
            If MsgBox(20, $appName, "No ini file found!" & @CRLF & "Create a new one?", 30) = 6 Then
                FileInstall("yaP.ini", $ini)
            Endif
            Exit
        Endif
    EndIf

    ; check main application
    $app = IniRead($ini, "GENERAL", "application", "")

    If FileExists(@ScriptDir & "\" & $app) AND NOT $app = "" Then
        $app = @ScriptDir & "\" & $app
    Endif

    If Not FileExists($app) Then
        MsgBox(16, $appName, "Main application is not set or path is invalid!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    EndIf
    
    ; check commandLine
    $commandLine = IniRead($ini, "GENERAL", "commandline", "")
    
    ; check multipleinstance
    $multipleInstance = IniRead($ini, "GENERAL", "multipleinstance", "")
 
    If _Singleton($appName, 1) = 0 Then
        If $multipleInstance = -1 Then
            Exit
        ElseIf $multipleInstance = 2 Then
           $secondInstance = true
        Else
           If $multipleInstance = 0 OR $multipleInstance = "" Then
               If MsgBox(68, $appName, $appName & ".exe is already running!" & @CRLF & "Are you sure to launch another instance of " & $appName & "?") = 7 Then
                   Exit
               Endif
            Endif
        Endif
    EndIf
    
    ; check BEFORE batch
    $beforeBatch = IniRead($ini, "BEFORE", "batch", "")
    If Not $beforeBatch = "" AND Not FileExists($rootdir & $beforeBatch) Then
        MsgBox(16, $appName, $rootdir & $beforeBatch & " not found!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    Endif

    ; check AFTER batch
    $afterBatch = IniRead($ini, "AFTER", "batch", "")
    If Not $afterBatch = "" AND Not FileExists($rootdir & $afterBatch) Then
        MsgBox(16, $appName, $rootdir & $afterBatch & " not found!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    Endif

    ; check BEFORE registry
    $beforeRegistry = IniRead($ini, "BEFORE", "registry", "")
    If Not $beforeRegistry = "" AND Not FileExists($rootdir & $beforeRegistry) Then
        MsgBox(16, $appName, $rootdir & $beforeRegistry & " not found!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    Endif

    ; check AFTER registry
    $afterRegistry = IniRead($ini, "AFTER", "registry", "")
    If Not $afterRegistry = "" AND Not FileExists($rootdir & $afterRegistry) Then
        MsgBox(16, $appName, $rootdir & $afterRegistry & " not found!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    Endif
    
    ; check working directory
    $workDir = IniRead($ini, "GENERAL", "workdir", "")
    If $app = "" Then
        $workDir = @ScriptDir & "\"
    ElseIf FileExists(@ScriptDir & "\" & $workDir) Then
        $workDir = @ScriptDir & "\" & $workDir
    Endif    
    
    If Not FileExists($workDir) Then
        MsgBox(16, $appName, "Working directory does not exist!" & @CRLF & "Please check " & $ini & ".", 30)
        Exit
    EndIf

    ; check BEFORE wait
    $beforeWait = IniRead($ini, "BEFORE", "wait", "")
    If isInt($beforeWait) OR $beforeWait < 500 OR $beforeWait > 10000 Then
        $beforeWait = 500
    Endif

    ; check AFTER wait
    $afterWait = IniRead($ini, "AFTER", "wait", "")
    If isInt($afterWait) OR $afterWait < 500 OR $afterWait > 10000 Then
        $afterWait = 500
    Endif

    ; check silentBatch
    $silentBatch = IniRead($ini, "GENERAL", "silentbatch", "")

    ; check systemrefresh
    $beforeSystemRefresh = IniRead($ini, "BEFORE", "systemrefresh", "")
    $afterSystemRefresh = IniRead($ini, "AFTER", "systemrefresh", "")
    
EndFunc   ;==>_Init


Func _BeforeItems()    ; execute BEFORE items

    If Not ($secondInstance) Then

        ; prompt the user to launch the main application or quit
        Local $message = IniRead($ini, "BEFORE", "message", 0)

        If StringLen($message) > 1 Then
            If MsgBox(36, $appName, $message, 30) = 7 Then
                Exit
            Endif
        ElseIf $message = 1 Then
            If MsgBox(36, $appName, "You are about to launch " & $appName & "." & @CRLF & "Continue?", 30) = 7 Then
                Exit
            Endif
        Endif

        ; execute batch
        If $silentBatch = 1 Then
            RunWait($rootdir & $beforeBatch, $workDir, @SW_HIDE)
        Else
            RunWait($rootdir & $beforeBatch, $workDir)
        Endif

        ; execute registry
        If $silentBatch = 1 Then
            RunWait("REGEDIT /S " & $rootdir & $beforeRegistry, $workDir, @SW_HIDE)
        Else
            RunWait("REGEDIT /S " & $rootdir & $beforeRegistry, $workDir)
        Endif
        
        ; delete registry key if empty
        Local $i = 0
        While 1
            $i += 1
            $beforeRegistryIfEmpty = IniRead($ini, "BEFORE", "DeleteRegKeyIfEmpty" & $i, "")
            If $beforeRegistryIfEmpty = "" Then ExitLoop
            If _RegKeyIsEmpty($beforeRegistryIfEmpty) = 3 Then
                RegDelete($beforeRegistryIfEmpty)
            Endif
        WEnd
        
        ; system refresh
        If $beforeSystemRefresh = 1 Then
            _RunDOS("RunDll32.exe USER32.DLL, UpdatePerUserSystemParameters, 1, True")
        Endif
    Endif
EndFunc   ;==>_BeforeItems


Func _Main()    ; execute main application
    Sleep($beforeWait)

    If $afterBatch = "" AND $afterRegistry = "" Then
        Run($app & " " & $commandLine & " " & $CmdLineRaw, $workDir)
    Else
        RunWait($app & " " & $commandLine & " " & $CmdLineRaw, $workDir)
    Endif
    
    Sleep($afterWait)
EndFunc   ;==>_Main


Func _AfterItems()    ; execute AFTER items
    
    If Not ($secondInstance) Then

        ; prompt the user to execute AFTER items or quit
        Local $message = IniRead($ini, "AFTER", "message", 0)

        If StringLen($message) > 1 Then
            If MsgBox(36, $appName, $message, 30) = 7 Then Exit
            ElseIf $message = 1 Then
                If MsgBox(36, $appName, "You are about to launch AFTER items for " & $appName & "." & @CRLF & "Continue?", 30) = 7 Then
                    Exit
            Endif
        Endif

        ; execute batch
         If $silentBatch = 1 Then
             RunWait($rootdir & $afterBatch, $workDir, @SW_HIDE)
         Else
             RunWait($rootdir & $afterBatch, $workDir)
         Endif

         ; execute registry
         If $silentBatch = 1 Then
             RunWait("REGEDIT /S " & $rootdir & $afterRegistry, $workDir, @SW_HIDE)
         Else
             RunWait("REGEDIT /S " & $rootdir & $afterRegistry, $workDir)
         Endif
         
         ; delete registry key if empty
         Local $i = 0
         While 1
             $i += 1
             $afterRegistryIfEmpty = IniRead($ini, "AFTER", "afterRegistryIfEmpty" & $i, "")
             If $afterRegistryIfEmpty = "" Then ExitLoop
             If _RegKeyIsEmpty($afterRegistryIfEmpty) = 3 Then
                 RegDelete($afterRegistryIfEmpty)
             Endif
         WEnd
         
         ; system refresh
         If $afterSystemRefresh = 1 Then
             _RunDOS("RunDll32.exe USER32.DLL, UpdatePerUserSystemParameters, 1, True")
         Endif
    
    Endif
EndFunc   ;==>_AfterItems

Func _RegKeyIsEmpty($Key)
       ; Prog@ndy
    Local $result = 0
    RegEnumVal($Key,1)
    If @error = -1 Then $result += 1
    RegEnumKey($Key,1)
    If @error = -1 Then $result += 2
    Return SetError($result=0,0,$result)
EndFunc ;==>_RegKeyIsEmpty


Func _RunDOS($sCommand)
    Return RunWait(@ComSpec & " /C " & $sCommand, "", @SW_HIDE)
EndFunc   ;==>_RunDOS