// cell update [<locator>] - Update packages from remote sources
//
// Usage:
//   cell update              Update all packages in shop
//   cell update .            Update current directory package
//   cell update <locator>    Update a specific package
//
// Options:
//   --build              Run build after updating
//   --target <triple>    Target platform for build (requires --build)
//   --follow-links       Update link targets instead of origins

var shop = use('internal/shop')
var build = use('build')
var fd = use('fd')

var target_pkg = null
var run_build = false
var target_triple = null
var follow_links = false
var i = 0
var resolved = null

// Parse arguments
for (i = 0; i < length(args); i++) {
  if (args[i] == '--help' || args[i] == '-h') {
    log.console("Usage: cell update [<locator>] [options]")
    log.console("")
    log.console("Update packages from remote sources.")
    log.console("")
    log.console("Options:")
    log.console("  --build              Run build after updating")
    log.console("  --target <triple>    Target platform for build (requires --build)")
    log.console("  --follow-links       Update link targets instead of origins")
    $stop()
  } else if (args[i] == '--build') {
    run_build = true
  } else if (args[i] == '--target' || args[i] == '-t') {
    if (i + 1 < length(args)) {
      target_triple = args[++i]
    } else {
      log.error('--target requires a triple')
      $stop()
    }
  } else if (args[i] == '--follow-links') {
    follow_links = true
  } else if (!starts_with(args[i], '-')) {
    target_pkg = args[i]
    // Resolve relative paths to absolute paths
    if (target_pkg == '.' || starts_with(target_pkg, './') || starts_with(target_pkg, '../') || fd.is_dir(target_pkg)) {
      resolved = fd.realpath(target_pkg)
      if (resolved) {
        target_pkg = resolved
      }
    }
  }
}

// Default target if building
if (run_build && !target_triple) {
  target_triple = build.detect_host_target()
}

var link = use('link')

function update_and_fetch(pkg) {
  var lock = shop.load_lock()
  var old_entry = lock[pkg]
  var old_commit = old_entry ? old_entry.commit : null
  var effective_pkg = pkg
  var link_target = null
  var new_entry = null
  var old_str = null

  // Handle follow-links option
  if (follow_links) {
    link_target = link.get_target(pkg)
    if (link_target) {
      effective_pkg = link_target
      log.console("  Following link: " + pkg + " -> " + effective_pkg)
    }
  }

  new_entry = shop.update(effective_pkg)

  if (new_entry) {
    if (new_entry.commit) {
      old_str = old_commit ? text(old_commit, 0, 8) : "(new)"
      log.console("  " + effective_pkg + " " + old_str + " -> " + text(new_entry.commit, 0, 8))
      shop.fetch(effective_pkg)
    } else {
      // Local package - just ensure symlink is correct
      log.console("  " + effective_pkg + " (local)")
    }
    shop.extract(effective_pkg)
    shop.build_package_scripts(effective_pkg)
    return effective_pkg
  }
  return null
}

var updated_packages = []

var updated = null
var packages = null
var pkg_count = 0
var pkg = null
if (target_pkg) {
  updated = update_and_fetch(target_pkg)
  if (updated) {
    push(updated_packages, updated)
    log.console("Updated " + target_pkg + ".")
  } else {
    log.console(target_pkg + " is up to date.")
  }
} else {
  packages = shop.list_packages()
  pkg_count = length(packages)
  log.console("Checking for updates (" + text(pkg_count) + " package" + (pkg_count == 1 ? "" : "s") + ")...")

  for (i = 0; i < length(packages); i++) {
    pkg = packages[i]
    if (pkg == 'core') continue

    updated = update_and_fetch(pkg)
    if (updated) {
      push(updated_packages, updated)
    }
  }

  if (length(updated_packages) > 0) {
    log.console("Updated " + text(length(updated_packages)) + " package" + (length(updated_packages) == 1 ? "" : "s") + ".")
  } else {
    log.console("All packages are up to date.")
  }
}

// Run build if requested
if (run_build && length(updated_packages) > 0) {
  log.console("")
  log.console("Building updated packages...")

  arrfor(updated_packages, function(pkg) {
    var _build = function() {
      var lib = build.build_dynamic(pkg, target_triple, 'release')
      if (lib)
        log.console("  Built: " + lib)
    } disruption {
      log.error("  Failed to build " + pkg)
    }
    _build()
  })
}

$stop()
