// cell explain — Query the semantic index for a source file.
//
// Usage:
//   cell explain --span file.ce:10:5       Find symbol at position
//   cell explain --symbol add_node         Find symbol by name
//   cell explain --symbol add_node file.ce Limit to specific file
//   cell explain --help                    Show this help

var fd = use('fd')
var json = use('json')
var tokenize_mod = use('tokenize')
var parse_mod = use('parse')
var fold_mod = use('fold')
var index_mod = use('index')
var explain_mod = use('explain')
var shop = use('internal/shop')

// Resolve import paths on an index in-place.
var resolve_imports = function(idx_obj, fname) {
  var fi = shop.file_info(fd.realpath(fname))
  var ctx = fi.package
  var ri = 0
  var rp = null
  var lp = null
  while (ri < length(idx_obj.imports)) {
    rp = shop.resolve_use_path(idx_obj.imports[ri].module_path, ctx)
    // Fallback: check sibling files in the same directory.
    if (rp == null) {
      lp = fd.dirname(fd.realpath(fname)) + '/' + idx_obj.imports[ri].module_path + '.cm'
      if (fd.is_file(lp)) {
        rp = lp
      }
    }
    if (rp != null) {
      idx_obj.imports[ri].resolved_path = rp
    }
    ri = ri + 1
  }
}

var mode = null
var span_arg = null
var symbol_name = null
var files = []
var i = 0
var parts = null
var filename = null
var line = null
var col = null
var src = null
var idx = null
var indexes = []
var explain = null
var result = null
var pipeline = {tokenize: tokenize_mod, parse: parse_mod, fold: fold_mod}

for (i = 0; i < length(args); i++) {
  if (args[i] == '--span') {
    mode = "span"
    if (i + 1 < length(args)) {
      span_arg = args[i + 1]
      i = i + 1
    } else {
      log.error('--span requires file:line:col')
      $stop()
    }
  } else if (args[i] == '--symbol') {
    mode = "symbol"
    if (i + 1 < length(args)) {
      symbol_name = args[i + 1]
      i = i + 1
    } else {
      log.error('--symbol requires a name')
      $stop()
    }
  } else if (args[i] == '--help' || args[i] == '-h') {
    log.console("Usage: cell explain [options]")
    log.console("")
    log.console("Query the semantic index for a source file.")
    log.console("")
    log.console("Options:")
    log.console("  --span file:line:col   Find symbol at position")
    log.console("  --symbol name <file>...  Find symbol by name across files")
    $stop()
  } else if (!starts_with(args[i], '-')) {
    files[] = args[i]
  }
}

if (mode == null) {
  log.error('Specify --span or --symbol. Use --help for usage.')
  $stop()
}

if (mode == "span") {
  parts = array(span_arg, ":")
  if (length(parts) < 3) {
    log.error('--span requires file:line:col format')
    $stop()
  }

  filename = parts[0]
  line = number(parts[1])
  col = number(parts[2])

  if (!fd.is_file(filename)) {
    log.error('File not found: ' + filename)
    $stop()
  }

  src = text(fd.slurp(filename))
  idx = index_mod.index_file(src, filename, pipeline)
  resolve_imports(idx, filename)
  explain = explain_mod.make(idx)
  result = explain.at_span(line, col)

  if (result == null) {
    log.console("Nothing found at " + filename + ":" + text(line) + ":" + text(col))
  } else {
    print(json.encode(result, true))
    print("\n")
  }
}

if (mode == "symbol") {
  if (length(files) == 0) {
    log.error('--symbol requires at least one file argument')
    $stop()
  }

  // Validate all files exist.
  i = 0
  while (i < length(files)) {
    if (!fd.is_file(files[i])) {
      log.error('File not found: ' + files[i])
      $stop()
    }
    i = i + 1
  }

  if (length(files) == 1) {
    // Single file: use by_symbol for a focused result.
    filename = files[0]
    src = text(fd.slurp(filename))
    idx = index_mod.index_file(src, filename, pipeline)
    resolve_imports(idx, filename)
    explain = explain_mod.make(idx)
    result = explain.by_symbol(symbol_name)

    if (result == null || length(result.symbols) == 0) {
      log.console("Symbol '" + symbol_name + "' not found in " + filename)
    } else {
      print(json.encode(result, true))
      print("\n")
    }
  } else if (length(files) > 1) {
    // Multiple files: index each and search across all.
    indexes = []
    i = 0
    while (i < length(files)) {
      src = text(fd.slurp(files[i]))
      idx = index_mod.index_file(src, files[i], pipeline)
      resolve_imports(idx, files[i])
      indexes[] = idx
      i = i + 1
    }
    result = explain_mod.explain_across(indexes, symbol_name)

    if (result == null || length(result.symbols) == 0) {
      log.console("Symbol '" + symbol_name + "' not found in " + text(length(files)) + " files")
    } else {
      print(json.encode(result, true))
      print("\n")
    }
  }
}

$stop()
