$LogFilePath = "$env:temp\eole_script.log"
function Check-Log-Size {
    #if ((Get-Item $LogFilePath).Length -gt 5MB) {
    if ((Get-Item $LogFilePath).Length -gt 5KB) {
#        Write-Output "Le fichier dépasse 5 Mo."
        Set-Content -Path $LogFilePath -Value ""
    }
}

Check-Log-Size
Start-Transcript -Path $LogFilePath -Append
#Set-PSDebug -Trace 1

$before_netuse = @()
$after_netuse = @()

function Write-Log {
    param (
        [string]$message
    )
    try {
        $callerFunction = (Get-PSCallStack)[1].FunctionName
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        #"$timestamp - $callerFunction - $message" | Add-Content -Path $logFilePath
        Write-Host "$timestamp - $callerFunction - $message"
    } catch {
        return
    }
}

function Replace-NonAlphanumericPreserveSpace {
    param (
        [string]$InputString,
        [string]$ReplacementChar = "_"
    )

    # Replace everything that is NOT a-z, A-Z, 0-9, or space
    return ($InputString -replace '[^a-zA-Z0-9]', $ReplacementChar)
}

function ScheduleCommand {
    # Utilisation de la commande 'powershell.exe -Command "Start-Process -FilePath <application.exe> -ArgumentList <argument(s) de application.exe>"
    # Cela permet d'exécuter <application.exe> sans attendre que la commande finisse de s'exécuter
    # Ainsi le planificateur de tâches considère le processus powershell.exe comme étant terminé
    # et la tâche planifiée peut être supprimée
    param (
        [string]$Command,
        [string]$CmdArgs = '',
        [bool]$Hide = $false
        )
    Write-Log "Command = $Command, CmdArgs = $CmdArgs, Hide = $Hide"

    if ($Hide) {
        #$HideString = "-WindowStyle Hidden"
        $VBSHideString = ",0"
    }

#    if ($CmdArgs) {
#        $CmdArgString = "-ArgumentList `"$CmdArgs`""
#    }
#
#    $ArgString = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -Command `"Start-Process $HideString -FilePath $Command $CmdArgString`""
#    Write-Log "powershell.exe $ArgString"

    # User qui se connecte
    $myuser = "$env:USERDOMAIN\$env:USERNAME"
    # Nommage unique de la tâche programmée
    $taskName = Replace-NonAlphanumericPreserveSpace -InputString "EOLE Run '${Command}' '$CmdArgs' AtLogon $myuser"
    $taskDescription = Replace-NonAlphanumericPreserveSpace -InputString "EOLE Runs '${Command}' '$CmdArgs' once at the next user logon $myuser"

    # Powershell ouvre une fenêtre shell, utilisation de wscript.exe pour exécuter les commandes personnalisées
    #$EscapedArgString = $ArgString.Replace('"', '""')
    #$VBSCmd = "$EscapedCommand $EscapedCmdArgs"
    # Doubler les double quote pour VBS
    $EscapedCommand = $Command.Replace('"', '""')
    $EscapedCmdArgs = $CmdArgs.Replace('"', '""')
    $VBSCmd = "$EscapedCommand $EscapedCmdArgs"
    # Define the VBScript content
    $vbsContent = @"
Dim shell,command
command = "$VBSCmd"
Set shell = CreateObject("WScript.Shell")
shell.Run command $VBSHideString
"@
#shell.Run command,0
#"@

    # Chemin vers le script VBS : %TMP%\${taskName}.vbs
    $VBSoutputPath = "$env:TMP\${taskName}.vbs"

    # Attempt to write the file
    try {
        Set-Content -Path $VBSoutputPath -Value $vbsContent -Encoding ASCII -ErrorAction Stop
        Write-Log "VBS file created successfully: $VBSoutputPath"
    }
    catch {
        Write-Log "Failed to create VBS file '$VBSoutputPath': $_"
    }

    #$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $ArgString
    $action = New-ScheduledTaskAction -Execute "wscript.exe" -Argument $VBSoutputPath

    # Dans X secondes on exécute la tâche car si on l'exécute trop tôt, l'ouverture de session n'est pas terminée, le bureau n'est pas prête et la tâche échoue
    $runTime = (Get-Date).AddSeconds(10)
    # Expiration du Trigger
    $endTrigger = $runTime.AddSeconds(120).ToString("yyyy-MM-ddTHH:mm:ss")

    #$trigger = New-ScheduledTaskTrigger -AtLogOn -User $myuser
    $trigger = New-ScheduledTaskTrigger -Once -At $runTime
    $trigger.EndBoundary = $endTrigger

    $principal = New-ScheduledTaskPrincipal -UserId $myuser -LogonType Interactive -RunLevel Limited

    $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries `
                                        -DontStopIfGoingOnBatteries `
                                        -DisallowStartOnRemoteAppSession `
                                        -DisallowHardTerminate `
                                        -DisallowDemandStart `
                                        -DontStopOnIdleEnd `
                                        -ExecutionTimeLimit 0 `
                                        -StartWhenAvailable `
                                        -DeleteExpiredTaskAfter "00:00:01"

    # Effacement de la tâche si elle existe
    if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) {
        Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
        Write-Log "Task '$taskName' deleted successfully" -ForegroundColor Green
    }

    # Register the task
    Write-Log "Register-ScheduledTask -TaskName $taskName -Description $taskDescription -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force"
    Register-ScheduledTask -TaskName "$taskName" -Description "$taskDescription" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force

    Write-Log "Scheduled task '$taskName' created."
}

function read_logon_script($path) {

    if(test-path $path) {
        Write-Log "found", $path
        $is_before = $true
        Get-Content $path | ForEach-Object {
            if ( $_ -eq "%%NetUse%%" -or  $_ -eq "%NetUse%"  ) {
                $is_before = $false
            } elseif ( $is_before -eq $true) {
                $global:before_netuse += [System.Environment]::ExpandEnvironmentVariables($_)
            } else {
                $global:after_netuse += [System.Environment]::ExpandEnvironmentVariables($_)
            }
       }
    }
    else {
        Write-Log "not found $path"
    }
}

function execute_cmd($items) {
    if($items.length -gt 1) {
        $cmd, $args = $items[1].split(' ', 2, [System.StringSplitOptions]::RemoveEmptyEntries)
        if($cmd) {
            $hide = $false
            $wait = $true
            if ($items.length -gt 2) {
                $option = $items[2].Trim().ToUpper()
                if($option -eq "HIDDEN") {
                    $hide = $true
                } elseif ($option -eq "NOWAIT") {
                    $wait = $false
                } else {
                    Write-Log "Unknown option $option for cmd $items"
                    return
                }
            }
            if($items.length -gt 3) {
                $option = $items[3].Trim().ToUpper()
                if($option -eq "HIDDEN") {
                    $hide = $true
                } elseif ($option -eq "NOWAIT") {
                    $wait = $false
                } else {
                    Write-Log "Unknown option $option for cmd $items"
                    return
                }
            }
            if($hide) {
                $windowstyle = "Hidden"
            } else {
                $windowstyle = "Normal"
            }
            if ($wait) {
                if($args) {
                    Write-Log "Launch command $cmd Wait:$wait WindowStyle:$windowstyle with arguments $args"
                    Start-Process -FilePath $cmd -WindowStyle $windowstyle -Wait:$wait -ArgumentList $args
                }
                else {
                    Write-Log "Launch command $cmd Wait:$wait WindowStyle:$windowstyle"
                    Start-Process -FilePath $cmd -WindowStyle $windowstyle -Wait:$wait
                }
            }
            else {
                Write-Log "Launch command $action Wait:$wait $cmd $args hide=$hide"
                ScheduleCommand -Command $cmd -CmdArgs $args -Hide $hide
            }
        }
        else {
             Write-Log "Invalid line $items"
        }
    }
    else {
        Write-Log "Invalid line $items"
    }

}

function execute_drive($items) {
    if($items.length -ne 3)
    {
       Write-Log "Invalid line '$items', ignore !"
       return
    }

    Try {
        # si l'utilisateur a saisi R: --> R
        $argLetter = $items[1] -replace ':' , ''
        #Write-Log "Map drive '$argLetter'"
        [ValidatePattern('^[a-zA-Z]$')]$letter = $argLetter
        }
    catch
    {
        Write-Log "Invalid letter for unit in '$items', ignore !"
        return
    }

    Try {
        if ( $major -ge 10 )
        {
            # Cas Windows 10
            $unc = $items[2]
            Write-Log "Map drive (W10) '$unc' in '$letter'"
            $smbMapping = Get-SmbMapping -LocalPath "${letter}:" -ErrorAction SilentlyContinue
            if ( $smbMapping )
            {
                if ( $smbMapping.RemotePath -eq "$unc" )
                {
                    Write-Log "Map drive (W10) '$unc' in '$letter' déjà monté !"
                    # hum.. danger si le token est celui d'un autre !
                    return
                }
                # la lettre est déjà utilisée pour un autre Path... force
                Remove-SmbMapping -LocalPath "${letter}:" -Force
            }
            New-SmbMapping -LocalPath "${letter}:" -RemotePath "$unc"
        }
        else
        {
            # Cas Windows 7
            $unc = $items[2]
            Write-Log "Map drive (W7) '$unc' in '$letter'"
            Start-Process -FilePath "net" -ArgumentList "use","${letter}:","$unc","/PERSISTENT:NO" -Wait -WindowStyle Hidden
        }
    }
    catch
    {
        "Exception pour '$unc' in '$letter'" | Out-String
        $_ | Out-String
        return
    }
}

function execute($line) {
    $items = $line.Split(',')
    $type = $items[0]
    if( $type -eq 'cmd' ) {
        execute_cmd $items
    }
    elseif ( $type -eq 'lecteur' ) {
        execute_drive $items
    }
    else {
        Write-Log "unknown action type $_"
    }
}

Write-Log "Attention: ps-Futur.ps1"

#FIXME : $servername = $env:USERDNSDOMAIN
#ou si serveur de logon : $env:LOGONSERVER
$scripts_path = "$env:LOGONSERVER\sysvol\$env:USERDNSDOMAIN\scripts"

# Personal script
$user = $env:USERNAME
$path = "$scripts_path\users\$user.txt"
read_logon_script $path

# pour raison de compatibilité
$path = "$scripts_path\os\Vista.txt"
read_logon_script $path

$major = [Environment]::OSVersion.Version.Major
$path = "$scripts_path\os\$major.txt"
read_logon_script $path

$build = [Environment]::OSVersion.Version.Build
$path = "$scripts_path\os\$major\$build.txt"
read_logon_script $path

# pour raison de compatibilité
$path = "$scripts_path\os\Vista\users\$user.txt"
read_logon_script $path
$path = "$scripts_path\os\$major\users\$user.txt"
read_logon_script $path
$path = "$scripts_path\os\$major\$build\users\$user.txt"
read_logon_script $path

# Groups scripts
$Identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object System.Security.Principal.WindowsPrincipal($Identity)

$Groups = $Identity.Groups | ForEach-Object { $_.Translate([Security.Principal.NTAccount]) }

$Groups |ForEach {
    $group = $_.toString()
    if ($group.StartsWith("$env:USERDOMAIN\")) {
        $group = $group.Split('\', 2)[1]
        $path = "$scripts_path\groups\$group.txt"
        read_logon_script $path
        # pour raison de compatibilité
        $path = "$scripts_path\os\Vista\groups\$group.txt"
        read_logon_script $path
        $path = "$scripts_path\os\$major\groups\$group.txt"
        read_logon_script $path
        $path = "$scripts_path\os\$major\$build\groups\$group.txt"
        read_logon_script $path
    }
}

$path = "$scripts_path\machines\$env:COMPUTERNAME.txt"
read_logon_script $path

$before_netuse |ForEach {
    execute $_
}
$after_netuse |ForEach {
    execute $_
}

Stop-Transcript
