// cell list [<scope>] - List packages and dependencies
//
// Usage:
//   cell list              List dependencies of current package
//   cell list shop         List all packages in shop with status
//   cell list <locator>    List dependency tree for a package

var shop = use('internal/shop')
var pkg = use('package')
var link = use('link')
var fd = use('fd')

var mode = 'local'
var target_pkg = null
var resolved = null
var i = 0
var deps = null
var packages = null
var local_pkgs = null
var linked_pkgs = null
var remote_pkgs = null

if (args && length(args) > 0) {
  if (args[0] == 'shop') {
    mode = 'shop'
  } else if (args[0] == '--help' || args[0] == '-h') {
    log.console("Usage: cell list [<scope>]")
    log.console("")
    log.console("List packages and dependencies.")
    log.console("")
    log.console("Scopes:")
    log.console("  (none)     List dependencies of current package")
    log.console("  shop       List all packages in shop with status")
    log.console("  <locator>  List dependency tree for a package")
    $stop()
  } else {
    mode = 'package'
    target_pkg = args[0]

    // Resolve local 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
      }
    }
  }
}

var links = link.load()
var lock = shop.load_lock()

function print_deps(ctx, raw_indent) {
  var aliases = null
  var indent = raw_indent || ""
  deps = null
  var _read = function() {
    deps = pkg.dependencies(ctx)
  } disruption {
    log.console(indent + "  (could not read dependencies)")
    return
  }
  _read()

  if (!deps) {
    log.console(indent + "  (none)")
    return
  }

  aliases = array(deps)
  aliases = sort(aliases)

  if (length(aliases) == 0) {
    log.console(indent + "  (none)")
    return
  }

  var j = 0
  var alias = null
  var locator = null
  var link_target = null
  var lock_entry = null
  var line = null
  var status = null
  for (j = 0; j < length(aliases); j++) {
    alias = aliases[j]
    locator = deps[alias]
    link_target = links[locator]
    lock_entry = lock[locator]

    line = indent + "  " + alias
    if (alias != locator) {
      line += " -> " + locator
    }

    // Add status indicators
    status = []
    if (link_target) {
      push(status, "linked -> " + link_target)
    }
    if (lock_entry && lock_entry.commit) {
      push(status, "@" + text(lock_entry.commit, 0, 8))
    }
    if (lock_entry && lock_entry.type == 'local') {
      push(status, "local")
    }
    if (!lock_entry) {
      push(status, "not installed")
    }

    if (length(status) > 0) {
      line += " [" + text(status, ", ") + "]"
    }

    log.console(line)
  }
}

if (mode == 'local') {
  log.console("Dependencies:")
  print_deps(null)
} else if (mode == 'package') {
  log.console("Dependencies for " + target_pkg + ":")
  print_deps(target_pkg)
} else if (mode == 'shop') {
  log.console("Shop packages:")
  log.console("")

  packages = shop.list_packages()
  if (length(packages) == 0) {
    log.console("  (none)")
  } else {
    packages = sort(packages)

    // Group by type
    local_pkgs = []
    linked_pkgs = []
    remote_pkgs = []

    arrfor(packages, function(p) {
      if (p == 'core') return
      var lock_entry = lock[p]
      var link_target = links[p]

      if (link_target) {
        push(linked_pkgs, p)
      } else if (lock_entry && lock_entry.type == 'local') {
        push(local_pkgs, p)
      } else {
        push(remote_pkgs, p)
      }
    })

    if (length(linked_pkgs) > 0) {
      log.console("Linked packages:")
      arrfor(linked_pkgs, function(p) {
        var target = links[p]
        log.console("  " + p + " -> " + target)
      })
      log.console("")
    }

    if (length(local_pkgs) > 0) {
      log.console("Local packages:")
      arrfor(local_pkgs, function(p) {
        log.console("  " + p)
      })
      log.console("")
    }

    if (length(remote_pkgs) > 0) {
      log.console("Remote packages:")
      arrfor(remote_pkgs, function(p) {
        var lock_entry = lock[p]
        var commit = lock_entry && lock_entry.commit ? " @" + text(lock_entry.commit, 0, 8) : ""
        log.console("  " + p + commit)
      })
      log.console("")
    }

    log.console("Total: " + text(length(packages)) + " package(s)")
  }
}

$stop()
