// Execution of the optional pre_install / post_install scripts.
//
// The script body is stored verbatim inside the manifest together with the
// platform it targets. At unpack time the script is written into the
// destination directory and executed with the interpreter that matches the
// host; a script for a different platform is skipped.
//
// The script receives:
//   - the destination directory as its working directory
//   - $LUNAPACK_DEST pointing at the destination directory
//   - $LUNAPACK_PHASE set to "pre_install" or "post_install"

///|
/// Does a script targeting `script_platform` apply on `host`?
///
/// "any" always applies, "posix" covers Linux and macOS.
pub fn script_applies(script_platform : String, host : String) -> Bool {
  if script_platform == "any" {
    true
  } else if script_platform == host {
    true
  } else if script_platform == "posix" {
    host == "linux" || host == "macos"
  } else {
    false
  }
}

///|
/// Infer the target platform of a script from its file extension.
pub fn script_platform_of(path : String) -> String {
  let lower = path.to_lower()
  if lower.has_suffix(".cmd") || lower.has_suffix(".bat") {
    "windows"
  } else if lower.has_suffix(".sh") {
    "posix"
  } else if lower.has_suffix(".ps1") {
    "windows"
  } else {
    "any"
  }
}

///|
/// Write `script` into `dest` as a runnable file for `platform`.
async fn write_script(
  platform : String,
  kind : String,
  script : Script,
  dest : String,
) -> String {
  let (_, _, ext) = shell_for(platform)
  let path = dest + "/.lunapack_" + kind + ext
  @fs.write_file(path, string_to_utf8_bytes(script.body))
  // Make the script executable on POSIX; a no-op on Windows.
  set_permissions(platform, path, 0o755)
  path
}

///|
/// Run an install script of `kind` inside `dest` and return its exit status.
///
/// `platform` selects the interpreter, which makes the POSIX path testable on
/// any host.
pub async fn run_install_script(
  platform : String,
  kind : String,
  script : Script,
  dest : String,
) -> Int32 {
  let (interp, extra, _) = shell_for(platform)
  let path = write_script(platform, kind, script, dest)
  let args = []
  for a in extra {
    args.push(a)
  }
  args.push(path)
  @env.set_env_var("LUNAPACK_DEST", dest)
  @env.set_env_var("LUNAPACK_PHASE", kind)
  // `status` inherits stdout/stderr so the user sees the script output.
  let st = @shell.Cmd(interp, args, cwd=dest).status()
  // Clean up the temporary script file; leaving it behind would pollute the
  // installation directory.
  @fs.remove(path) catch {
    _ => ()
  }
  st
}