# web_server.ps1
# Static file server - listens on port 9998, opens browser on start

$port    = 9998
$baseDir = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)

# Generate js\htmlfiles.js (递归扫描 baseDir 及其任意深度子文件夹, 跳过 js/、geogebra/ 资源目录, 只排除根目录下的 index.html)
$jsDir = Join-Path $baseDir "js"
if (-not (Test-Path $jsDir)) { New-Item -ItemType Directory -Path $jsDir | Out-Null }

$excludeDirs = @('js', 'geogebra')
$htmlFiles   = Get-ChildItem -Path $baseDir -Filter "*.html" -Recurse -File |
               ForEach-Object {
                   $rel = ($_.FullName.Substring($baseDir.Length).TrimStart('\', '/')) -replace '\\', '/'
                   [PSCustomObject]@{ Rel = $rel }
               } |
               Where-Object {
                   $topDir = $_.Rel.Split('/')[0]
                   (-not ($excludeDirs -contains $topDir)) -and ($_.Rel -ne "index.html")
               } |
               ForEach-Object { "'$($_.Rel)'" }
$listContent = "let html_files = [$($htmlFiles -join ', ')];"
[System.IO.File]::WriteAllText((Join-Path $jsDir "htmlfiles.js"), $listContent)

# Exit if port is already in use
$inUse = netstat -ano | Select-String ":$port "
if ($inUse) { exit 0 }

$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add("http://localhost:$port/")
$listener.Start()

Start-Process "http://localhost:$port/index.html"

$mimeMap = @{
    ".html" = "text/html; charset=utf-8"
    ".css"  = "text/css"
    ".js"   = "application/javascript"
    ".txt"  = "text/plain; charset=utf-8"
    ".png"  = "image/png"
    ".jpg"  = "image/jpeg"
    ".jpeg" = "image/jpeg"
    ".gif"  = "image/gif"
    ".svg"  = "image/svg+xml"
    ".ico"  = "image/x-icon"
    ".json" = "application/json"
}

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

    if ($request.HttpMethod -ne "GET") {
        $response.StatusCode = 405
        $response.Close()
        continue
    }

    $urlPath  = $request.Url.LocalPath.TrimStart("/")
    $fullPath = Join-Path $baseDir $urlPath

    if (Test-Path $fullPath -PathType Container) {
        $fullPath = Join-Path $fullPath "index.html"
    }

    if (Test-Path $fullPath) {
        $ext = [System.IO.Path]::GetExtension($fullPath).ToLower()
        $ct  = if ($mimeMap.ContainsKey($ext)) { $mimeMap[$ext] } else { "application/octet-stream" }
        $response.ContentType     = $ct
        $data                     = [System.IO.File]::ReadAllBytes($fullPath)
        $response.ContentLength64 = $data.Length
        $response.OutputStream.Write($data, 0, $data.Length)
    } else {
        $response.StatusCode = 404
    }

    $response.Close()
}
