// cell clone <origin> <path>
// Clones a cell package <origin> to the local <path>, and links it.

var shop = use('internal/shop')
var link = use('link')
var fd = use('fd')
var http = use('http')
var miniz = use('miniz')

var resolved = null
var cwd = null
var parent = null

if (length(args) < 2) {
  log.console("Usage: cell clone <origin> <path>")
  log.console("Clones a cell package to a local path and links it.")
  $stop()
}

var origin = args[0]
var target_path = args[1]

// Resolve target path to absolute
if (target_path == '.' || starts_with(target_path, './') || starts_with(target_path, '../')) {
  resolved = fd.realpath(target_path)
  if (resolved) {
    target_path = resolved
  } else {
    // Path doesn't exist yet, resolve relative to cwd
    cwd = fd.realpath('.')
    if (target_path == '.') {
      target_path = cwd
    } else if (starts_with(target_path, './')) {
      target_path = cwd + text(target_path, 1)
    } else if (starts_with(target_path, '../')) {
      // Go up one directory from cwd
      parent = fd.dirname(cwd)
      target_path = parent + text(target_path, 2)
    }
  }
}

// Check if target already exists
if (fd.is_dir(target_path)) {
  log.console("Error: " + target_path + " already exists")
  $stop()
}

log.console("Cloning " + origin + " to " + target_path + "...")

// Get the latest commit
var info = shop.resolve_package_info(origin)
if (!info || info == 'local') {
  log.console("Error: " + origin + " is not a remote package")
  $stop()
}

// Update to get the commit hash
var update_result = shop.update(origin)
if (!update_result) {
  log.console("Error: Could not fetch " + origin)
  $stop()
}

// Fetch and extract to the target path
var lock = shop.load_lock()
var entry = lock[origin]
if (!entry || !entry.commit) {
  log.console("Error: No commit found for " + origin)
  $stop()
}

var download_url = shop.get_download_url(origin, entry.commit)
log.console("Downloading from " + download_url)

var zip_blob = null
var zip = null
var count = 0
var i = 0
var filename = null
var first_slash = null
var rel_path = null
var full_path = null
var dir_path = null

var _clone = function() {
  zip_blob = http.fetch(download_url)

  // Extract zip to target path
  zip = miniz.read(zip_blob)
  if (!zip) {
    log.console("Error: Failed to read zip archive")
    $stop()
  }

  // Create target directory
  fd.mkdir(target_path)

  count = zip.count()
  for (i = 0; i < count; i++) {
    if (zip.is_directory(i)) continue
    filename = zip.get_filename(i)
    first_slash = search(filename, '/')
    if (first_slash == null) continue
    if (first_slash + 1 >= length(filename)) continue

    rel_path = text(filename, first_slash + 1)
    full_path = target_path + '/' + rel_path
    dir_path = fd.dirname(full_path)

    // Ensure directory exists
    if (!fd.is_dir(dir_path)) {
      fd.mkdir(dir_path)
    }
    fd.slurpwrite(full_path, zip.slurp(filename))
  }

  log.console("Extracted to " + target_path)

  // Link the origin to the cloned path
  link.add(origin, target_path, shop)
  log.console("Linked " + origin + " -> " + target_path)
} disruption {
  log.console("Error during clone")
}
_clone()

$stop()
