# Lowmoor 日本語化パッチ — 適用スクリプト
#
#   右クリック →「PowerShell で実行」でも、
#   PowerShell を開いて  .\適用する.ps1  でも動きます。
#
# やること:
#   1. Steam の中から Lowmoor を自動で探す（見つからなければ聞きます）
#   2. あなたの app.asar を展開する
#   3. 同梱の翻訳データ（tm.json / overrides.json）を当てる
#   4. asar に詰め直して差し替える（元ファイルは app.asar.en.bak に退避）
#
# セーブデータには一切触れません（%APPDATA%\lowmoor-desktop と Steam Cloud）。
# 元に戻すには「元に戻す.ps1」を実行するか、Steam の「ゲームファイルの整合性を確認」を実行してください。
#
# 必要なもの: Node.js 18 以上（https://nodejs.org） — npx で asar を取ってくるため一度だけ通信します。

$ErrorActionPreference = 'Stop'
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
# PowerShell 7.4 以降は、外部コマンドが非ゼロ終了すると即座に例外にする。
# それだとこのスクリプトの親切なエラーメッセージが出ないので、自前の終了コード判定に任せる。
if (Test-Path variable:PSNativeCommandUseErrorActionPreference) { $PSNativeCommandUseErrorActionPreference = $false }
$root = $PSScriptRoot
$GAME_DIR_NAME = "Lowmoor Idle RPG An Adventurer's Chronicle"

function Say($msg, $color = 'Gray') { Write-Host $msg -ForegroundColor $color }
function Die($msg) { Write-Host ''; Write-Host "[中止] $msg" -ForegroundColor Red; Write-Host ''; Read-Host '  Enter キーで閉じます' | Out-Null; exit 1 }

Say ''
Say '=== Lowmoor 日本語化パッチ ===' Cyan
Say ''

# --- 1. Node.js の確認 -------------------------------------------------
try {
  $nodeVer = (& node --version) 2>$null
} catch { $nodeVer = $null }
if (-not $nodeVer) {
  Die @'
Node.js が見つかりません。

  https://nodejs.org/ から LTS 版を入れて、PowerShell を開き直してから
  もう一度このスクリプトを実行してください。
'@
}
Say "Node.js: $nodeVer"

# --- 2. ゲームフォルダを探す -------------------------------------------
function Find-SteamLibraries {
  $libs = @()
  $steam = $null
  foreach ($key in @('HKCU:\Software\Valve\Steam', 'HKLM:\SOFTWARE\WOW6432Node\Valve\Steam')) {
    try {
      $p = (Get-ItemProperty -Path $key -ErrorAction Stop)
      if ($p.SteamPath)    { $steam = $p.SteamPath }
      elseif ($p.InstallPath) { $steam = $p.InstallPath }
      if ($steam) { break }
    } catch { }
  }
  if (-not $steam) { return $libs }
  $steam = $steam -replace '/', '\'
  $libs += $steam

  # libraryfolders.vdf に他ドライブのライブラリが列挙されている
  $vdf = Join-Path $steam 'steamapps\libraryfolders.vdf'
  if (Test-Path $vdf) {
    foreach ($line in (Get-Content $vdf)) {
      if ($line -match '"path"\s*"([^"]+)"') {
        $libs += ($matches[1] -replace '\\\\', '\')
      }
    }
  }
  return ($libs | Select-Object -Unique)
}

$game = $null
foreach ($lib in (Find-SteamLibraries)) {
  $candidate = Join-Path $lib "steamapps\common\$GAME_DIR_NAME"
  if (Test-Path (Join-Path $candidate 'resources\app.asar')) { $game = $candidate; break }
}

if (-not $game) {
  Say ''
  Say 'Steam のライブラリから Lowmoor を見つけられませんでした。' Yellow
  Say 'Steam で Lowmoor を右クリック →「管理」→「ローカルファイルを閲覧」で開いた'
  Say 'フォルダのパスを貼り付けてください（何も入れずに Enter で中止）。'
  Say ''
  $typed = Read-Host '  ゲームフォルダ'
  if (-not $typed) { Die 'ゲームフォルダが指定されませんでした。' }
  $game = $typed.Trim('"').Trim()
  if (-not (Test-Path (Join-Path $game 'resources\app.asar'))) {
    Die "そのフォルダに resources\app.asar がありません: $game"
  }
}
Say "ゲーム: $game" Green

$res    = Join-Path $game 'resources'
$target = Join-Path $res 'app.asar'
$backup = Join-Path $res 'app.asar.en.bak'

# asar から版番号を取り出す。退避が「本当に今の版の原文か」を確かめるのに使う。
# 4MBずつ読んで境目をまたぐ文字列も拾えるよう、末尾64文字を持ち越す。
function Get-AsarVersion([string]$path) {
  if (-not (Test-Path $path)) { return $null }
  $fs = [System.IO.File]::OpenRead($path)
  try {
    $buf = New-Object byte[] 4194304
    $tail = ''
    while (($n = $fs.Read($buf, 0, $buf.Length)) -gt 0) {
      $s = $tail + [System.Text.Encoding]::UTF8.GetString($buf, 0, $n)
      $m = [regex]::Match($s, 'const GAME_VERSION = "([^"]+)"')
      if ($m.Success) { return $m.Groups[1].Value }
      $keep = [Math]::Min(64, $s.Length)
      $tail = $s.Substring($s.Length - $keep)
    }
  } finally { $fs.Dispose() }
  return $null
}
$unpackedSrc = Join-Path $res 'app.asar.unpacked'

# --- 3. 起動中でないか -------------------------------------------------
if (Get-Process -Name 'Lowmoor' -ErrorAction SilentlyContinue) {
  Die 'Lowmoor.exe が起動中です。ゲームを終了してから実行してください。'
}

# --- 4. 展開 -----------------------------------------------------------
$tools = Join-Path $root 'tools'
if (-not (Test-Path (Join-Path $tools 'patch.mjs'))) { Die "tools フォルダが見つかりません: $tools" }

Push-Location $tools
try {
  $app = Join-Path $tools 'app'
  if (Test-Path $app) { Remove-Item $app -Recurse -Force }

  Say ''
  Say 'app.asar を展開しています（初回は asar の取得で少し待ちます）...'
  & npx --yes '@electron/asar' extract "$target" "$app"
  if ($LASTEXITCODE -ne 0) { Die 'asar の展開に失敗しました。' }
  if (-not (Test-Path (Join-Path $app 'game\index.html'))) {
    Die '展開できましたが game\index.html がありません。ゲームの構成が変わった可能性があります。'
  }

  # --- 5. 翻訳を当てる -------------------------------------------------
  Say ''
  Say '翻訳を適用しています...'
  & node 'build-ja.mjs'
  if ($LASTEXITCODE -ne 0) { Die '翻訳の適用に失敗しました。' }

  $built = Join-Path $tools 'build\index.html'
  if (-not (Test-Path $built)) { Die 'build\index.html が作られませんでした。' }
  Copy-Item $built (Join-Path $app 'game\index.html') -Force

  # --- 6. 詰め直す -----------------------------------------------------
  # 開発者のビルドツール（steamcmd 約150MB）が誤って同梱されている。
  # ゲームコードからは参照されていないので、詰める前に外してよい。
  foreach ($junk in @('steam\builder', 'steam\output')) {
    $j = Join-Path $app $junk
    if (Test-Path $j) { Remove-Item $j -Recurse -Force; Say "  除外: $junk" }
  }

  # asar の外に置かれているネイティブモジュールを一度中に戻してから、
  # --unpack-dir で同じ形に外し直す。こうしないと steamworks.js が読めなくなる。
  if (Test-Path $unpackedSrc) {
    Say '  ネイティブモジュールを合流させています...'
    Copy-Item (Join-Path $unpackedSrc '*') $app -Recurse -Force -ErrorAction SilentlyContinue
  }

  Say ''
  Say 'asar に詰め直しています...'
  $newAsar = Join-Path $tools 'app.asar.new'
  if (Test-Path $newAsar) { Remove-Item $newAsar -Force }
  & npx --yes '@electron/asar' pack "$app" "$newAsar" --unpack-dir 'node_modules/steamworks.js/**'
  if ($LASTEXITCODE -ne 0) { Die 'asar の再構築に失敗しました。' }

  # --- 7. 差し替え -----------------------------------------------------
  #
  # **「退避が既にあれば何もしない」ではいけない。**
  # ゲームが更新されて app.asar が新しい英語版に入れ替わったあとにこれを流すと、
  # 古い版の退避が残ったまま新しい英語の原文が上書きされて失われる。
  # 実際 1.6.0 でこれが起き、退避が 1.5.2 のままだったせいで 1.6.0 の原文を
  # 取り戻せず、Steam に再取得させるはめになった（1.6.1 で修正）。
  #
  # 退避を取り直すのは「今入っているのが英語版で、かつ退避と版が違う」ときだけ。
  # 上書きする前の退避は app.asar.en.<版>.bak として残す。
  $curVer = Get-AsarVersion $target
  $bakVer = Get-AsarVersion $backup
  if (-not (Test-Path $backup)) {
    Say ''
    Say "オリジナルを退避しています: app.asar -> app.asar.en.bak (版 $curVer)"
    Copy-Item $target $backup
  } elseif ($curVer -and $bakVer -and $curVer -ne $bakVer) {
    Say ''
    Say "ゲームが更新されています（退避 $bakVer / 現在 $curVer）。退避を取り直します。"
    Copy-Item $backup (Join-Path $res "app.asar.en.$bakVer.bak") -Force
    Copy-Item $target $backup -Force
  } else {
    Say ''
    Say "退避済みのオリジナルは今の版と同じです（$bakVer）。そのままにします。"
  }
  Copy-Item $newAsar $target -Force
  Remove-Item $newAsar -Force
  $newUnpacked = "$newAsar.unpacked"
  if (Test-Path $newUnpacked) { Remove-Item $newUnpacked -Recurse -Force }

  Say ''
  Say '日本語化パッチを適用しました。' Green
  Say ("  app.asar -> {0:N1} MB" -f ((Get-Item $target).Length / 1MB))
  Say ''
  Say '注意: Steam がゲームを更新すると app.asar は上書きされ、英語に戻ります。'
  Say '      その場合はこのスクリプトを再実行してください。'
  Say ''
}
finally { Pop-Location }

Read-Host '  Enter キーで閉じます' | Out-Null
