// cell clean [<scope>] - Remove cached material to force refetch/rebuild
//
// Usage:
//   cell clean              Clean build outputs for current directory package
//   cell clean .            Clean build outputs for current directory package
//   cell clean <locator>    Clean build outputs for specific package
//   cell clean shop         Clean entire shop
//   cell clean world        Clean all world packages
//
// Options:
//   --build      Remove build outputs only (default)
//   --fetch      Remove fetched sources only
//   --all        Remove both build outputs and fetched sources
//   --deep       Apply to full dependency closure
//   --dry-run    Show what would be deleted

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

var scope = null
var clean_build = false
var clean_fetch = false
var deep = false
var dry_run = false
var i = 0
var deps = null

var run = function() {
  for (i = 0; i < length(args); i++) {
    if (args[i] == '--build') {
      clean_build = true
    } else if (args[i] == '--fetch') {
      clean_fetch = true
    } else if (args[i] == '--all') {
      clean_build = true
      clean_fetch = true
    } else if (args[i] == '--deep') {
      deep = true
    } else if (args[i] == '--dry-run') {
      dry_run = true
    } else if (args[i] == '--help' || args[i] == '-h') {
      log.console("Usage: cell clean [<scope>] [options]")
      log.console("")
      log.console("Remove cached material to force refetch/rebuild.")
      log.console("")
      log.console("Scopes:")
      log.console("  <locator>  Clean specific package")
      log.console("  shop       Clean entire shop")
      log.console("  world      Clean all world packages")
      log.console("")
      log.console("Options:")
      log.console("  --build    Remove build outputs only (default)")
      log.console("  --fetch    Remove fetched sources only")
      log.console("  --all      Remove both build outputs and fetched sources")
      log.console("  --deep     Apply to full dependency closure")
      log.console("  --dry-run  Show what would be deleted")
      return
    } else if (!starts_with(args[i], '-')) {
      scope = args[i]
    }
  }

// Default to --build if nothing specified
if (!clean_build && !clean_fetch) {
  clean_build = true
}

// Default scope to current directory
if (!scope) {
  scope = '.'
}

// Resolve local paths for single package scope
var is_shop_scope = (scope == 'shop')
var is_world_scope = (scope == 'world')

if (!is_shop_scope && !is_world_scope) {
  scope = shop.resolve_locator(scope)
}

var files_to_delete = []
var dirs_to_delete = []

// Gather packages to clean
var packages_to_clean = []
var _gather = null

if (is_shop_scope) {
  packages_to_clean = shop.list_packages()
} else if (is_world_scope) {
  // For now, world is the same as shop
  packages_to_clean = shop.list_packages()
} else {
  // Single package
  push(packages_to_clean, scope)

  if (deep) {
    _gather = function() {
      deps = pkg.gather_dependencies(scope)
      arrfor(deps, function(dep) {
        push(packages_to_clean, dep)
      })
    } disruption {
      // Skip if can't read dependencies
    }
    _gather()
  }
}

// Gather files to clean
var lib_dir = shop.get_lib_dir()
var build_dir = shop.get_build_dir()
var packages_dir = replace(shop.get_package_dir(''), /\/$/, '') // Get base packages dir

if (clean_build) {
  // Nuke entire build cache (content-addressed, per-package clean impractical)
  if (fd.is_dir(build_dir)) {
    push(dirs_to_delete, build_dir)
  }
  // Clean orphaned lib/ directory if it exists (legacy)
  if (fd.is_dir(lib_dir)) {
    push(dirs_to_delete, lib_dir)
  }
}

if (clean_fetch) {
  if (is_shop_scope) {
    // Clean entire packages directory (dangerous!)
    if (fd.is_dir(packages_dir)) {
      push(dirs_to_delete, packages_dir)
    }
  } else {
    // Clean specific package directories
    arrfor(packages_to_clean, function(p) {
      if (p == 'core') return

      var pkg_dir = shop.get_package_dir(p)
      if (fd.is_dir(pkg_dir) || fd.is_link(pkg_dir)) {
        push(dirs_to_delete, pkg_dir)
      }
    })
  }
}

// Execute or report
var deleted_count = 0
if (dry_run) {
  log.console("Would delete:")
  if (length(files_to_delete) == 0 && length(dirs_to_delete) == 0) {
    log.console("  (nothing to clean)")
  } else {
    arrfor(files_to_delete, function(f) {
      log.console("  [file] " + f)
    })
    arrfor(dirs_to_delete, function(d) {
      log.console("  [dir]  " + d)
    })
  }
} else {
  arrfor(files_to_delete, function(f) {
    var _del = function() {
      fd.unlink(f)
      log.console("Deleted: " + f)
      deleted_count++
    } disruption {
      log.error("Failed to delete " + f)
    }
    _del()
  })

  arrfor(dirs_to_delete, function(d) {
    var _del = function() {
      if (fd.is_link(d)) {
        fd.unlink(d)
      } else {
        fd.rmdir(d, 1) // recursive
      }
      log.console("Deleted: " + d)
      deleted_count++
    } disruption {
      log.error("Failed to delete " + d)
    }
    _del()
  })

  if (deleted_count == 0) {
    log.console("Nothing to clean.")
  } else {
    log.console("")
    log.console("Clean complete: " + text(deleted_count) + " item(s) deleted.")
  }
}
}
run()

$stop()
