// Copyright 2026 The GN Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/edit_command.h"

#include <iomanip>
#include <sstream>
#include <utility>
#include <vector>

#include "gn/build_file_editor.h"
#include "gn/commands.h"
#include "gn/edit_subcommands.h"
#include "gn/filesystem_utils.h"
#include "gn/setup.h"
#include "gn/source_file.h"
#include "gn/standard_out.h"
#include "gn/value.h"

namespace commands {

const char kEdit[] = "edit";
const char kEdit_HelpShort[] =
    "edit: Edit BUILD.gn files from the command line.";
const char kEdit_Help[] =
    "gn edit <command> <labels/patterns...>\n"
    "\n"
    "  Executes a command to modify a set of targets\n"
    "\n"
    "  Note: Because GN is an imperative language, it's not always entirely\n"
    "  clear what the \"correct\" thing is to do.\n"
    "\n"
    "  In cases of ambiguity (eg. conditionals), `gn edit` will leave notes\n"
    "  in your build files instructing you what to do.\n"
    "\n"
    "Commands:\n"
    "  add <attribute> <value(s)>\n"
    "      Adds <value(s)> to the list attribute <attribute>.\n"
    "      If the attribute does not exist, it is created.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"add deps //base //src/tools:utils\" //src/tools:*\n"
    "\n"
    "  delete\n"
    "      Deletes the matched targets entirely.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"delete\" //src/tools:old_target\n"
    "\n"
    "  move <from_attribute> <to_attribute> <value(s)>\n"
    "      Moves <value(s)> from the list <from_attribute> to <to_attribute>.\n"
    "      If <to_attribute> does not exist, it is created.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"move deps public_deps //base\" //src/tools:*\n"
    "\n"
    "  new <rule_kind> [(before|after) <relative_rule_name>]\n"
    "      Adds a new rule at the end of the BUILD file (or before/after\n"
    "      <relative_rule_name>). The rule name is determined by the target "
    "label.\n"
    "\n"
    "      Examples:\n"
    "        gn edit \"new source_set\" //src/tools:my_target\n"
    "        gn edit \"new static_library before old_target\" "
    "//src/tools:helper\n"
    "\n"
    "  remove <attribute>\n"
    "      Removes <attribute> entirely.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"remove testonly\" //src/tools:*\n"
    "\n"
    "  remove <attribute> <value(s)>\n"
    "      Removes <value(s)> from the list attribute <attribute>.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"remove deps //base\" //src/tools:*\n"
    "\n"
    "  rename <from_attribute> <to_attribute>\n"
    "      Renames <from_attribute> to <to_attribute>.\n"
    "\n"
    "      Example:\n"
    "        gn edit \"rename srcs sources\" //src/tools:*\n"
    "\n"
    "  set <attribute>[:list] <value(s)>\n"
    "      Sets or overwrites the target's <attribute> to <value(s)>.\n"
    "      If multiple values are provided, or if the \":list\" suffix is\n"
    "      appended to the attribute, <value(s)> is interpreted as a list.\n"
    "\n"
    "      Examples:\n"
    "        gn edit \"set testonly true\" //src/tools:*\n"
    "        gn edit \"set srcs:list foo.cc\" //:foo\n"
    "        gn edit \"set deps :bar :baz\" //:foo\n"
    "\n"
    "  shard [sharded_target_type] [group_type]\n"
    "      Splits the target's sources into fine-grained shard targets,\n"
    "      inheriting compilation flags, and updates the parent\n"
    "      target to depend on the newly created shards.\n"
    "      Note: Sharding strips existing deps and clones conditional blocks\n"
    "      into each shard. For conditional sources (e.g. `if (is_win)`),\n"
    "      manual cleanup is often needed, such as:\n"
    "        * Moving the condition to wrap the shard instead of the sources\n"
    "        * Stripping empty conditions\n"
    "\n"
    "      Examples:\n"
    "        gn edit \"shard\" //:large_target\n"
    "        gn edit \"shard source_set static_library\" //:large_target\n";

Result<std::pair<std::vector<SourceFile>, EditState>> RunEditImpl(
    const std::vector<std::string>& args,
    Setup& setup) {
  if (args.size() < 2) {
    return Err(Location(), "Insufficient arguments.",
               "Usage: gn edit <command> <labels...>\n"
               "Example: gn edit \"set testonly true\" //foo:*");
  }

  // We use std::quoted to tokenize the command.
  // eg. set foo "bar baz" -> ["set", "foo", "bar baz"].
  std::stringstream ss(args[0]);
  std::vector<std::string> command_tokens;
  std::string token;
  while (ss >> std::ws && !ss.eof()) {
    if (!(ss >> std::quoted(token))) {
      return Err(Location(), "Unclosed quote in command string.");
    }
    command_tokens.push_back(std::move(token));
  }
  if (command_tokens.empty()) {
    return Err(Location(), "Empty command string.");
  }

  ASSIGN_OR_RETURN(EditCommand command,
                   ParseCommand(std::move(command_tokens)));
  const SourceDir current_dir =
      SourceDirForCurrentDirectory(setup.build_settings().root_path());
  const std::string source_root = setup.build_settings().root_path_utf8();

  std::vector<LabelPattern> patterns;
  for (size_t i = 1; i < args.size(); ++i) {
    Value val(nullptr, args[i]);
    Err err;
    LabelPattern pattern =
        LabelPattern::GetPattern(current_dir, source_root, val, &err);
    if (err.has_error()) {
      return err;
    }
    patterns.push_back(std::move(pattern));
  }

  ASSIGN_OR_RETURN(std::vector<BuildFile> build_files,
                   ::ResolvePatternsToBuildFiles(&setup.build_settings(),
                                                 setup.loader(), patterns));

  EditState state(args[0]);
  for (auto& build_file : build_files) {
    RETURN_IF_ERROR(command(build_file, state));
    RETURN_IF_ERROR(build_file.label_matcher().done());
  }

  std::vector<SourceFile> modified_files;
  for (auto& build_file : build_files) {
    ASSIGN_OR_RETURN(bool wrote, build_file.Write());
    if (wrote) {
      modified_files.push_back(build_file.source_file());
    }
  }

  return std::make_pair(std::move(modified_files), std::move(state));
}

int RunEdit(const std::vector<std::string>& args) {
  Setup setup;
  if (!setup.DoSetupForEditing()) {
    return 1;
  }
  auto result = RunEditImpl(args, setup);
  if (result.has_error()) {
    result.error().PrintToStdout();
    return 1;
  }
  for (const auto& file : result->first) {
    OutputString("Wrote '" + file.value() + "'.\n");
  }
  for (const auto& warning : result->second.warnings) {
    warning.PrintNonfatalToStdout();
  }
  const auto& review_needed = result->second.needs_manual_review;
  if (!review_needed.empty()) {
    OutputString("\nThe following targets need manual review:\n",
                 DECORATION_YELLOW);
    for (const Label& label : review_needed) {
      OutputString("* ");
      OutputString(label.GetUserVisibleName(false) + "\n", DECORATION_GREEN);
    }

    OutputString(
        "\nWhere manual review is required, comments have been added to the "
        "build file of the form:\n'# TODO(gn edit: <command>): ...'\n",
        DECORATION_DIM);
  }
  const auto& needs_fix_deps = result->second.needs_fix_deps;
  if (!needs_fix_deps.empty()) {
    OutputString(
        "\nTo automatically resolve and populate dependencies for sharded "
        "targets, run:\n",
        DECORATION_YELLOW);
    std::string check_cmd = "gn check <out_dir>";
    for (const Label& label : needs_fix_deps) {
      check_cmd += " " + label.GetUserVisibleName(false);
    }
    check_cmd += " --fix\n";
    OutputString(check_cmd, DECORATION_GREEN);
  }
  return 0;
}

}  // namespace commands
