#!/usr/bin/osascript -l JavaScript

ObjC.import("stdlib")

// String -> String
function envVar(varName) {
  return $.NSProcessInfo.processInfo.environment.objectForKey(varName).js
}

// [String] -> Object
function runCommand(arguments) {
  const task = $.NSTask.alloc.init
  const stdout = $.NSPipe.pipe

  task.executableURL = $.NSURL.alloc.initFileURLWithPath(arguments[0])
  task.arguments = arguments.slice(1)
  task.standardOutput = stdout
  task.launchAndReturnError(false)

  const dataOut = stdout.fileHandleForReading.readDataToEndOfFile
  const stringOut = $.NSString.alloc.initWithDataEncoding(dataOut, $.NSUTF8StringEncoding).js

  return { stdout: stringOut, exitStatus: task.terminationStatus }
}

// String, String -> [Object]
function getOutdated(muCLI, hideNonUpdatable) {
  const command = runCommand([muCLI, "list", "--json", "--hide-uptodate-apps"])

  if (command.exitStatus === 255) return [{ suitableLicense: false }]

  const all = JSON.parse(command.stdout)["apps"]

  if (hideNonUpdatable) return all.filter(app => app["auto_updatable"])

  return all
}

// String, [String], String -> ()
function updateApp(muCLI, flags, appPath) {
  runCommand([muCLI, "update", flags, appPath].flat())
}

// Constants
const muCLI = runCommand(["/usr/bin/mdfind", "kMDItemCFBundleIdentifier", "=", "com.corecode.MacUpdater"]).stdout.trim() + "/Contents/Resources/macupdater_client"
const updateOptions = envVar("update_options")?.split(" ").filter(opt => opt) || []
const hideNonUpdatable = !(envVar("hide_non_automatic") === "0")

// Main
function run(argv) {
  switch (argv[0]) {
    case "show_outdated":
      const outdated = getOutdated(muCLI, hideNonUpdatable)

      // Check for suitable license
      if (outdated[0]?.["unsuitableLicense"]) {
        return JSON.stringify({ items : [{
          title: "Requires MacUpdater Pro or Business License",
          subtitle: "This Workflow depends on the command-line tool, not available in Standard",
          valid: false
        }]})
      }

      // Check if there is anything to update
      if (outdated.length === 0) {
        return JSON.stringify({ items: [{ title: "Everything is up-to-date!", valid: false }] })
      }

      // Show outdated
      const firstItem = {
        title: "Update All",
        arg: "update_all"
      }

      const items = outdated.map(app => {
        return {
          title: app["name"],
          subtitle: `${app["installed_version"]} → ${app["newest_version"]}`,
          icon: { type: 'fileicon', path: app["installed_path"] },
          valid: app["auto_updatable"],
          arg: app["installed_path"]
        }
      })

      return JSON.stringify({ items: [firstItem, items].flat() })
    case "update_all":
      return getOutdated(muCLI, true).map(app => app["installed_path"]).forEach(appPath => updateApp(muCLI, updateOptions, appPath))
    default:
      return updateApp(muCLI, updateOptions, argv[0])
  }
}
