DemoPresentation.psm1

$currentDirectory = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)

function wait {

    Write-Debug "Waiting"

    if ($Replaying -or $Skipping) {
        return
    }

    while ([System.Console]::KeyAvailable) {
        [System.Console]::ReadKey() | Out-Null
    }

    while (!$key -or ($key.Key -ne "Enter")) {

        while (![System.Console]::KeyAvailable) {
            Start-Sleep 0.5
        }

        $key = [System.Console]::ReadKey()
    }
}

function clip($text) {
    Write-Debug "Clipping"
    $text | clip.exe
}


function * ($text) {
    Write-Host "- $text" -ForegroundColor Cyan
}

function ask($text, $answer) {
    Write-Host "? $text" -ForegroundColor Green -NoNewLine
    Write-Host " ($answer)" -ForegroundColor Gray
}

function act($text, [scriptblock]$script) {
    Write-Host "> $text" -ForegroundColor Magenta
    if ($script) {
        Invoke-Command $script -NoNewScope
    }
}

function command($command) {
    execute $command
}

function execute($command) {

    Write-Host " $command" -ForegroundColor Yellow

    if ($Skipping) {
        return
    }

    if ($Replaying) {
        $script = [scriptblock]::Create("& $command")
        Invoke-Command $script -NoNewScope

    }
}

function createFile($fileName, $text) {

    if ($Skipping) {
        return
    }

    if ($Replaying) {
        Set-Content $fileName $text -Encoding UTF8
    }
    else {
        clip $text
    }

    act "Erstelle $fileName"
    wait
}

function addToFile($fileName, $description, $text) {

    if ($Skipping) {
        return
    }

    if ($Replaying) {
        Add-Content $fileName $text -Encoding UTF8
    }
    else {
        clip $text
    }

    act "Füge $description zu $fileName hinzu"
    wait
}

function showSlide($filePath) {

    Write-Debug "Showing slide '$filePath'"

    if ($Replaying -or $Skipping) {
        return
    }

    $filePath = Join-Path $DemoPath $filePath
    Start-Process "$currentDirectory\imgvwr.exe" "`"$filePath`"" -Wait
}

function editFile($fileName, $operation, $lineIndex) {

    if ($Skipping) {
        return
    }

    $content = [System.Collections.ArrayList]::new((Get-Content $fileName))

    if ($Replaying) {

        if ($operation -eq "removeLine") {
            $content.RemoveAt($lineIndex)
        }

        Set-Content $fileName $content -Encoding UTF8
    }

    if ($operation -eq "removeLine") {
        act "Entferne zeile $lineIndex aus '$fileName':"
        0..$content.Count | Foreach-Object {
            $indicator = " "
            if ($_ -eq $lineIndex) {
                $indicator = "> "
            }
            Write-Host "$indicator $($content[$_])"
        }
    }
    wait
}

function demo {
    param([scriptblock]$script)

    $script:DemoScript = $script
}

function reset {
    param([scriptblock]$script)

    $script:ResetScript = $script
}

function checkPoint {

    param([string]$name)

    if (($ReplayCheckPoint -eq $name) -and ($Replaying)) {
        $script:Replaying = $false
        Write-Debug "Replayed to checkpoint '$name'"
    }

    if (($SkipCheckPoint -eq $name) -and ($Skipping)) {
        $script:Skipping = $false
        Write-Debug "Skipped to checkpoint '$name'"
        if ($Replaying) {
            Write-Debug "Replaying to checkpoint '$ReplayCheckPoint'"
        }
    }
}

function Start-Demo {
    param([string]$Path, [string]$ReplayTo, [string]$SkipTo, [switch]$Debug)

    if ($Debug) {
        $DebugPreference = 'Continue'
    }

    $scriptText = Get-Content $path | Out-String
    $script = [scriptblock]::Create($scriptText)
    Invoke-Command $script -NoNewScope

    $script:DemoPath = Resolve-Path (Split-Path $Path -Parent)
    $script:Skipping = [bool]$SkipTo
    $script:Replaying = [bool]$ReplayTo
    $script:SkipCheckPoint = $SkipTo
    $script:ReplayCheckPoint = $ReplayTo

    if ($Skipping) {
        Write-Debug "Skipping to checkpoint '$SkipTo'"
    }
    else {
        if ($Replaying) {
            Write-Debug "Replaying to checkpoint '$ReplayTo'"
        }
    }

    if ($ResetScript -and !$Skipping) {
        try {
            $script:Resetting = $true
            Write-Debug "Starting reset part"
            Invoke-Command $ResetScript -NoNewScope
        }
        finally {
            $script:Resetting = $false
        }
    }

    if ($DemoScript) {
        Write-Debug "Starting demo part"
        Invoke-Command $DemoScript -NoNewScope
    }
}

Export-ModuleMember -Function 'Start-Demo'