# Serves the offline copy of robertducky.fr at http://localhost:<port>.
# Usage: .\serve.ps1 [-Port 8000]
# Uses .NET's HttpListener directly so no dependency should be required
param(
    [int]$Port = 8000
)

$ErrorActionPreference = "Stop"

$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$SiteDir = Join-Path $ScriptDir "pocketpond"
$Url = "http://localhost:$Port/"

$MimeTypes = @{
    ".html" = "text/html; charset=utf-8"; ".htm" = "text/html; charset=utf-8"
    ".css" = "text/css; charset=utf-8"; ".js" = "application/javascript; charset=utf-8"
    ".json" = "application/json; charset=utf-8"; ".xml" = "application/xml; charset=utf-8"
    ".txt" = "text/plain; charset=utf-8"
    ".png" = "image/png"; ".jpg" = "image/jpeg"; ".jpeg" = "image/jpeg"
    ".gif" = "image/gif"; ".svg" = "image/svg+xml"; ".webp" = "image/webp"
    ".ico" = "image/x-icon"; ".woff" = "font/woff"; ".woff2" = "font/woff2"
    ".mp3" = "audio/mpeg"; ".mp4" = "video/mp4"; ".webm" = "video/webm"
}

$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add($Url)

try {
    $listener.Start()
} catch {
    Write-Error "Could not start server on port $Port. Try a different port: .\serve.ps1 -Port $($Port + 1)"
    exit 1
}

Write-Host "Serving robertducky.fr offline at $Url"
Write-Host "Press Ctrl+C to stop."
Start-Process $Url

try {
    while ($listener.IsListening) {
        $context = $listener.GetContext()
        $request = $context.Request
        $response = $context.Response

        $requestPath = [System.Uri]::UnescapeDataString($request.Url.AbsolutePath)
        if ($requestPath -eq "/") { $requestPath = "/index.html" }

        $relative = $requestPath.TrimStart("/") -replace "/", [IO.Path]::DirectorySeparatorChar
        $filePath = Join-Path $SiteDir $relative

        if (Test-Path $filePath -PathType Container) {
            $filePath = Join-Path $filePath "index.html"
        } elseif ((-not (Test-Path $filePath)) -and (-not [IO.Path]::HasExtension($filePath))) {
            $candidate = Join-Path $filePath "index.html"
            if (Test-Path $candidate) { $filePath = $candidate }
        }

        if (Test-Path $filePath -PathType Leaf) {
            $ext = [IO.Path]::GetExtension($filePath)
            $contentType = $MimeTypes[$ext]
            if (-not $contentType) { $contentType = "application/octet-stream" }
            $bytes = [IO.File]::ReadAllBytes($filePath)
            $response.ContentType = $contentType
            $response.ContentLength64 = $bytes.Length
            $response.OutputStream.Write($bytes, 0, $bytes.Length)
        } else {
            $response.StatusCode = 404
            $notFound = Join-Path $SiteDir "404.html"
            if (Test-Path $notFound -PathType Leaf) {
                $bytes = [IO.File]::ReadAllBytes($notFound)
                $response.ContentType = "text/html; charset=utf-8"
                $response.OutputStream.Write($bytes, 0, $bytes.Length)
            }
        }
        $response.OutputStream.Close()
    }
} finally {
    $listener.Stop()
}
