// cell add <locator> [alias] - Add a dependency to the current package
//
// Usage:
//   cell add <locator>         Add a dependency using default alias
//   cell add <locator> <alias> Add a dependency with custom alias
//   cell add -r <directory>    Recursively find and add all packages in directory
//
// This adds the dependency to cell.toml and installs it to the shop.

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

var locator = null
var alias = null
var resolved = null
var parts = null
var cwd = null
var build_target = null
var recursive = false
var locators = null
var added = 0
var failed = 0
var summary = null

array(args, function(arg) {
  if (arg == '--help' || arg == '-h') {
    log.console("Usage: cell add <locator> [alias]")
    log.console("")
    log.console("Add a dependency to the current package.")
    log.console("")
    log.console("Examples:")
    log.console("  cell add gitea.pockle.world/john/prosperon")
    log.console("  cell add gitea.pockle.world/john/cell-image image")
    log.console("  cell add ../local-package")
    log.console("  cell add -r ../packages")
    $stop()
  } else if (arg == '-r') {
    recursive = true
  } else if (!starts_with(arg, '-')) {
    if (!locator) {
      locator = arg
    } else if (!alias) {
      alias = arg
    }
  }
})

if (!locator && !recursive) {
  log.console("Usage: cell add <locator> [alias]")
  $stop()
}

// Resolve relative paths to absolute paths
if (locator && (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator))) {
  resolved = fd.realpath(locator)
  if (resolved) {
    locator = resolved
  }
}

// Generate default alias from locator
if (!alias && locator) {
  // Use the last component of the locator as alias
  parts = array(locator, '/')
  alias = parts[length(parts) - 1]
  // Remove any version suffix
  if (search(alias, '@') != null) {
    alias = array(alias, '@')[0]
  }
}

// Check we're in a package directory
cwd = fd.realpath('.')
if (!fd.is_file(cwd + '/cell.toml')) {
  log.error("Not in a package directory (no cell.toml found)")
  $stop()
}

// Recursively find all cell packages in a directory
function find_packages(dir) {
  var found = []
  var list = fd.readdir(dir)
  if (!list) return found
  if (fd.is_file(dir + '/cell.toml')) {
    push(found, dir)
  }
  arrfor(list, function(item) {
    if (item == '.' || item == '..' || item == '.cell' || item == '.git') return
    var full = dir + '/' + item
    var st = fd.stat(full)
    var sub = null
    if (st && st.isDirectory) {
      sub = find_packages(full)
      arrfor(sub, function(p) {
        push(found, p)
      })
    }
  })
  return found
}

// If -r flag, find all packages recursively and add each
if (recursive) {
  if (!locator) {
    locator = '.'
  }
  resolved = fd.realpath(locator)
  if (!resolved || !fd.is_dir(resolved)) {
    log.error(`${locator} is not a directory`)
    $stop()
  }
  locators = find_packages(resolved)
  if (length(locators) == 0) {
    log.console("No packages found in " + resolved)
    $stop()
  }
  log.console(`Found ${text(length(locators))} package(s) in ${resolved}`)

  arrfor(locators, function(loc) {
    // Generate alias from directory name
    var loc_parts = array(loc, '/')
    var loc_alias = loc_parts[length(loc_parts) - 1]

    log.console("  Adding " + loc + " as '" + loc_alias + "'...")
    var _add = function() {
      pkg.add_dependency(null, loc, loc_alias)
      shop.get(loc)
      shop.extract(loc)
      shop.build_package_scripts(loc)
      var _build_c = function() {
        build_target = build.detect_host_target()
        build.build_dynamic(loc, build_target, 'release')
      } disruption {
        // Not all packages have C code
      }
      _build_c()
      added++
    } disruption {
      log.console(`  Warning: Failed to add ${loc}`)
      failed++
    }
    _add()
  })

  summary = "Added " + text(added) + " package(s)."
  if (failed > 0) {
    summary += " Failed: " + text(failed) + "."
  }
  log.console(summary)
  $stop()
}

log.console("Adding " + locator + " as '" + alias + "'...")

// Add to local project's cell.toml
var _add_dep = function() {
  pkg.add_dependency(null, locator, alias)
  log.console("  Added to cell.toml")
} disruption {
  log.error("Failed to update cell.toml")
  $stop()
}
_add_dep()

// Install to shop
var _install = function() {
  shop.get(locator)
  shop.extract(locator)

  // Build scripts
  var script_result = shop.build_package_scripts(locator)
  if (length(script_result.errors) > 0) {
    log.console("  Warning: " + text(length(script_result.errors)) + " script(s) failed to compile")
  }

  // Build C code if any
  var _build_c = function() {
    build_target = build.detect_host_target()
    build.build_dynamic(locator, build_target, 'release')
  } disruption {
    // Not all packages have C code
  }
  _build_c()

  log.console("  Installed to shop")
} disruption {
  log.error("Failed to install")
  $stop()
}
_install()

log.console("Added " + alias + " (" + locator + ")")

$stop()
