$ErrorActionPreference = "Stop"

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type @"
using System;
using System.Runtime.InteropServices;
public static class Win32Focus {
    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
"@

$AppName = "TaskbarHero Speed Assistant"
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
$PluginSource = Join-Path $Root "payload\TaskbarHeroSpeedMod.dll"
$BepInExSource = Join-Path $Root "payload\bepinex"
$DataRoot = Join-Path $env:APPDATA "TaskbarHeroSpeedAssistant"
$SettingsPath = Join-Path $DataRoot "settings.json"

function Ensure-DataRoot {
    New-Item -ItemType Directory -Force -Path $DataRoot | Out-Null
}

function Read-JsonFile($path, $fallback) {
    if (-not (Test-Path -LiteralPath $path)) { return $fallback }
    try {
        return Get-Content -LiteralPath $path -Raw -Encoding UTF8 | ConvertFrom-Json
    } catch {
        return $fallback
    }
}

function Write-JsonFile($path, $value) {
    Ensure-DataRoot
    $value | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $path -Encoding UTF8
}

function Get-DefaultGamePath {
    if (Test-Path -LiteralPath (Join-Path $Root "TaskBarHero.exe")) {
        return $Root
    }
    $parent = Split-Path -Parent $Root
    if ($parent -and (Test-Path -LiteralPath (Join-Path $parent "TaskBarHero.exe"))) {
        return $parent
    }
    $candidates = @(
        "H:\SteamLibrary\steamapps\common\TaskbarHero",
        "C:\Program Files (x86)\Steam\steamapps\common\TaskbarHero",
        "D:\SteamLibrary\steamapps\common\TaskbarHero",
        "E:\SteamLibrary\steamapps\common\TaskbarHero",
        "F:\SteamLibrary\steamapps\common\TaskbarHero"
    )
    foreach ($candidate in $candidates) {
        if (Test-Path -LiteralPath (Join-Path $candidate "TaskBarHero.exe")) {
            return $candidate
        }
    }
    return ""
}

function Get-Settings {
    $defaultPath = Get-DefaultGamePath
    $settings = Read-JsonFile $SettingsPath ([pscustomobject]@{ gamePath = $defaultPath })
    if ((-not $settings.gamePath) -and $defaultPath) {
        $settings.gamePath = $defaultPath
    }
    if ($settings.gamePath -and (-not (Test-Path -LiteralPath (Join-Path $settings.gamePath "TaskBarHero.exe"))) -and $defaultPath) {
        $settings.gamePath = $defaultPath
    }
    return $settings
}

function Set-Settings($settings) {
    Write-JsonFile $SettingsPath $settings
}

function Assert-GamePath($gamePath) {
    if (-not $gamePath) { throw "请先选择 TaskbarHero 游戏目录。" }
    if (-not (Test-Path -LiteralPath (Join-Path $gamePath "TaskBarHero.exe"))) {
        throw "这个目录里没有找到 TaskBarHero.exe，请重新选择游戏目录。"
    }
}

function Get-PluginTarget($gamePath) {
    return Join-Path $gamePath "BepInEx\plugins\TaskbarHeroSpeedMod.dll"
}

function Copy-DirectoryContents($source, $target) {
    if (-not (Test-Path -LiteralPath $source)) { return }
    New-Item -ItemType Directory -Force -Path $target | Out-Null
    Get-ChildItem -LiteralPath $source -Force | ForEach-Object {
        Copy-Item -LiteralPath $_.FullName -Destination $target -Recurse -Force
    }
}

function Install-BepInExRuntime($gamePath) {
    $runtimeRoot = $BepInExSource
    if (-not (Test-Path -LiteralPath $runtimeRoot)) {
        return
    }
    foreach ($fileName in @("winhttp.dll", "doorstop_config.ini", ".doorstop_version")) {
        $source = Join-Path $runtimeRoot $fileName
        if (Test-Path -LiteralPath $source) {
            Copy-Item -LiteralPath $source -Destination (Join-Path $gamePath $fileName) -Force
        }
    }
    Copy-DirectoryContents (Join-Path $runtimeRoot "BepInEx") (Join-Path $gamePath "BepInEx")
    Copy-DirectoryContents (Join-Path $runtimeRoot "dotnet") (Join-Path $gamePath "dotnet")
}

function Test-BepInExInstalled($gamePath) {
    return (
        (Test-Path -LiteralPath (Join-Path $gamePath "winhttp.dll")) -and
        (Test-Path -LiteralPath (Join-Path $gamePath "doorstop_config.ini")) -and
        (Test-Path -LiteralPath (Join-Path $gamePath "BepInEx\core\BepInEx.Core.dll"))
    )
}

function Test-SpeedPluginInstalled($gamePath) {
    return (
        (Test-BepInExInstalled $gamePath) -and
        (Test-Path -LiteralPath (Get-PluginTarget $gamePath))
    )
}

function Install-Plugin($gamePath) {
    Assert-GamePath $gamePath
    if (Get-Process -Name "TaskBarHero" -ErrorAction SilentlyContinue) {
        throw "请先关闭 TaskbarHero，再安装插件。"
    }
    if (-not (Test-Path -LiteralPath $PluginSource)) {
        throw "安装包缺少 payload\TaskbarHeroSpeedMod.dll。"
    }
    Install-BepInExRuntime $gamePath
    $target = Get-PluginTarget $gamePath
    New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
    Copy-Item -LiteralPath $PluginSource -Destination $target -Force
    if (-not (Test-BepInExInstalled $gamePath)) {
        throw "BepInEx 运行环境没有复制成功。请确认游戏目录不是只读，并用管理员方式重新运行 Run.bat。"
    }
    if (-not (Test-Path -LiteralPath $target)) {
        throw "倍速插件 DLL 没有复制成功。请确认游戏目录不是只读，并重新安装。"
    }
}

function Uninstall-Plugin($gamePath) {
    Assert-GamePath $gamePath
    if (Get-Process -Name "TaskBarHero" -ErrorAction SilentlyContinue) {
        throw "请先关闭 TaskbarHero，再卸载插件。"
    }
    $target = Get-PluginTarget $gamePath
    if (Test-Path -LiteralPath $target) {
        Remove-Item -LiteralPath $target -Force
    }
}

function Get-PluginStatusText($gamePath) {
    if (-not $gamePath) { return "未选择游戏目录" }
    if (-not (Test-Path -LiteralPath (Join-Path $gamePath "TaskBarHero.exe"))) {
        return "所选目录无效，没有找到 TaskBarHero.exe"
    }
    $target = Get-PluginTarget $gamePath
    if (Test-Path -LiteralPath $target) {
        $item = Get-Item -LiteralPath $target
        $runtime = if (Test-BepInExInstalled $gamePath) { "BepInEx 已就绪" } else { "缺少 BepInEx，需重新安装" }
        return "已安装：$($item.LastWriteTime.ToString('yyyy-MM-dd HH:mm'))；$runtime"
    }
    if (Test-BepInExInstalled $gamePath) {
        return "BepInEx 已就绪，但倍速插件未安装"
    }
    return "未安装；请先点击安装倍速插件"
}

function Send-SpeedHotkey($keyName) {
    Assert-GamePath $pathBox.Text
    if (-not (Test-SpeedPluginInstalled $pathBox.Text)) {
        throw "当前目录没有完整安装倍速插件。请先关闭游戏，点击安装倍速插件，再重新打开游戏。"
    }
    $game = Get-Process -Name "TaskBarHero" -ErrorAction SilentlyContinue | Select-Object -First 1
    if (-not $game) {
        throw "没有检测到正在运行的 TaskbarHero。请先打开游戏。"
    }
    if ($game.MainWindowHandle -eq 0) {
        throw "检测到游戏进程，但没有找到游戏窗口。请等游戏完全打开后再点倍速按钮。"
    }
    [Win32Focus]::ShowWindow($game.MainWindowHandle, 9) | Out-Null
    [Win32Focus]::SetForegroundWindow($game.MainWindowHandle) | Out-Null
    Start-Sleep -Milliseconds 180
    [System.Windows.Forms.SendKeys]::SendWait("{$keyName}")
    Start-Sleep -Milliseconds 80
}

function Show-Message($text, $title = $AppName) {
    [System.Windows.Forms.MessageBox]::Show($text, $title, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information) | Out-Null
}

function Show-Error($text) {
    [System.Windows.Forms.MessageBox]::Show($text, $AppName, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
}

Ensure-DataRoot
$settings = Get-Settings

$form = New-Object System.Windows.Forms.Form
$form.Text = $AppName
$form.Width = 720
$form.Height = 500
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false
$form.BackColor = [System.Drawing.Color]::FromArgb(250, 247, 239)
$font = New-Object System.Drawing.Font("Microsoft YaHei UI", 10)
$form.Font = $font

$title = New-Object System.Windows.Forms.Label
$title.Text = "塔斯克巴倍速助手"
$title.Font = New-Object System.Drawing.Font("Microsoft YaHei UI", 18, [System.Drawing.FontStyle]::Bold)
$title.Location = New-Object System.Drawing.Point(24, 18)
$title.Size = New-Object System.Drawing.Size(460, 40)
$form.Controls.Add($title)

$subtitle = New-Object System.Windows.Forms.Label
$subtitle.Text = "本地单机倍速辅助：F6=1x，F7=2x，F8=5x，F9=10x。建议日常使用 2x 或 5x。"
$subtitle.Location = New-Object System.Drawing.Point(26, 62)
$subtitle.Size = New-Object System.Drawing.Size(650, 26)
$form.Controls.Add($subtitle)

$pathLabel = New-Object System.Windows.Forms.Label
$pathLabel.Text = "游戏目录"
$pathLabel.Location = New-Object System.Drawing.Point(28, 110)
$pathLabel.Size = New-Object System.Drawing.Size(100, 24)
$form.Controls.Add($pathLabel)

$pathBox = New-Object System.Windows.Forms.TextBox
$pathBox.Location = New-Object System.Drawing.Point(28, 136)
$pathBox.Size = New-Object System.Drawing.Size(530, 30)
$pathBox.Text = [string]$settings.gamePath
$form.Controls.Add($pathBox)

$chooseButton = New-Object System.Windows.Forms.Button
$chooseButton.Text = "选择目录"
$chooseButton.Location = New-Object System.Drawing.Point(575, 135)
$chooseButton.Size = New-Object System.Drawing.Size(105, 32)
$form.Controls.Add($chooseButton)

$pluginStatus = New-Object System.Windows.Forms.Label
$pluginStatus.Location = New-Object System.Drawing.Point(28, 190)
$pluginStatus.Size = New-Object System.Drawing.Size(650, 28)
$form.Controls.Add($pluginStatus)

$installButton = New-Object System.Windows.Forms.Button
$installButton.Text = "安装倍速插件"
$installButton.Location = New-Object System.Drawing.Point(28, 234)
$installButton.Size = New-Object System.Drawing.Size(150, 42)
$form.Controls.Add($installButton)

$uninstallButton = New-Object System.Windows.Forms.Button
$uninstallButton.Text = "卸载插件"
$uninstallButton.Location = New-Object System.Drawing.Point(195, 234)
$uninstallButton.Size = New-Object System.Drawing.Size(130, 42)
$form.Controls.Add($uninstallButton)

$openGameButton = New-Object System.Windows.Forms.Button
$openGameButton.Text = "打开游戏"
$openGameButton.Location = New-Object System.Drawing.Point(342, 234)
$openGameButton.Size = New-Object System.Drawing.Size(130, 42)
$form.Controls.Add($openGameButton)

$openFolderButton = New-Object System.Windows.Forms.Button
$openFolderButton.Text = "打开游戏目录"
$openFolderButton.Location = New-Object System.Drawing.Point(489, 234)
$openFolderButton.Size = New-Object System.Drawing.Size(150, 42)
$form.Controls.Add($openFolderButton)

$speedLabel = New-Object System.Windows.Forms.Label
$speedLabel.Text = "游戏运行后，也可以直接点下面按钮切换倍速："
$speedLabel.Location = New-Object System.Drawing.Point(28, 292)
$speedLabel.Size = New-Object System.Drawing.Size(650, 24)
$form.Controls.Add($speedLabel)

$speed1Button = New-Object System.Windows.Forms.Button
$speed1Button.Text = "1x"
$speed1Button.Location = New-Object System.Drawing.Point(28, 322)
$speed1Button.Size = New-Object System.Drawing.Size(110, 40)
$form.Controls.Add($speed1Button)

$speed2Button = New-Object System.Windows.Forms.Button
$speed2Button.Text = "2x"
$speed2Button.Location = New-Object System.Drawing.Point(158, 322)
$speed2Button.Size = New-Object System.Drawing.Size(110, 40)
$form.Controls.Add($speed2Button)

$speed5Button = New-Object System.Windows.Forms.Button
$speed5Button.Text = "5x"
$speed5Button.Location = New-Object System.Drawing.Point(288, 322)
$speed5Button.Size = New-Object System.Drawing.Size(110, 40)
$form.Controls.Add($speed5Button)

$speed10Button = New-Object System.Windows.Forms.Button
$speed10Button.Text = "10x"
$speed10Button.Location = New-Object System.Drawing.Point(418, 322)
$speed10Button.Size = New-Object System.Drawing.Size(110, 40)
$form.Controls.Add($speed10Button)

$warning = New-Object System.Windows.Forms.Label
$warning.Text = "提醒：10x 可能导致角色位移异常。如果前排跑出地图，请切回 2x 或 5x。"
$warning.ForeColor = [System.Drawing.Color]::FromArgb(130, 72, 0)
$warning.Location = New-Object System.Drawing.Point(28, 382)
$warning.Size = New-Object System.Drawing.Size(650, 26)
$form.Controls.Add($warning)

function Refresh-Ui {
    $pluginStatus.Text = "插件状态：$(Get-PluginStatusText $pathBox.Text)"
}

$chooseButton.Add_Click({
    $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
    $dialog.Description = "请选择 TaskbarHero 游戏目录"
    if ($pathBox.Text) { $dialog.SelectedPath = $pathBox.Text }
    if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
        $pathBox.Text = $dialog.SelectedPath
        $settings.gamePath = $pathBox.Text
        Set-Settings $settings
        Refresh-Ui
    }
})

$installButton.Add_Click({
    try {
        $settings.gamePath = $pathBox.Text
        Set-Settings $settings
        Install-Plugin $pathBox.Text
        Show-Message "安装完成。现在可以重新打开游戏，在游戏内按 F7/F8/F9 调整倍速。"
        Refresh-Ui
    } catch {
        Show-Error $_.Exception.Message
    }
})

$uninstallButton.Add_Click({
    try {
        Uninstall-Plugin $pathBox.Text
        Show-Message "插件已卸载。"
        Refresh-Ui
    } catch {
        Show-Error $_.Exception.Message
    }
})

$openGameButton.Add_Click({
    try {
        Assert-GamePath $pathBox.Text
        Start-Process -FilePath (Join-Path $pathBox.Text "TaskBarHero.exe") -WorkingDirectory $pathBox.Text
    } catch {
        Show-Error $_.Exception.Message
    }
})

$openFolderButton.Add_Click({
    try {
        Assert-GamePath $pathBox.Text
        Start-Process explorer.exe -ArgumentList "`"$($pathBox.Text)`""
    } catch {
        Show-Error $_.Exception.Message
    }
})

$speed1Button.Add_Click({
    try {
        Send-SpeedHotkey "F6"
        Show-Message "已发送 1x 倍速指令。"
    } catch {
        Show-Error $_.Exception.Message
    }
})

$speed2Button.Add_Click({
    try {
        Send-SpeedHotkey "F7"
        Show-Message "已发送 2x 倍速指令。"
    } catch {
        Show-Error $_.Exception.Message
    }
})

$speed5Button.Add_Click({
    try {
        Send-SpeedHotkey "F8"
        Show-Message "已发送 5x 倍速指令。"
    } catch {
        Show-Error $_.Exception.Message
    }
})

$speed10Button.Add_Click({
    try {
        Send-SpeedHotkey "F9"
        Show-Message "已发送 10x 倍速指令。"
    } catch {
        Show-Error $_.Exception.Message
    }
})

Refresh-Ui
[void]$form.ShowDialog()
