// Copyright (c) 2013 The Chromium 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 <stddef.h>

#include <utility>

#include "gn/build_settings.h"
#include "gn/filesystem_utils.h"
#include "gn/functions.h"
#include "gn/parse_tree.h"
#include "gn/scope.h"
#include "gn/settings.h"
#include "gn/source_dir.h"
#include "gn/source_file.h"
#include "gn/value.h"

namespace functions {

namespace {

// We want the output to match the input in terms of ending in a slash or not.
// Through all the transformations, these can get added or removed in various
// cases.
void MakeSlashEndingMatchInput(const std::string& input, std::string* output) {
  if (EndsWithSlash(input)) {
    if (!EndsWithSlash(*output))  // Preserve same slash type as input.
      output->push_back(input[input.size() - 1]);
  } else {
    if (EndsWithSlash(*output))
      output->resize(output->size() - 1);
  }
}

// Returns true if the given value looks like a directory, otherwise we'll
// assume it's a file.
bool ValueLooksLikeDir(const std::string& value) {
  if (value.empty())
    return true;
  size_t value_size = value.size();

  // Count the number of dots at the end of the string.
  size_t num_dots = 0;
  while (num_dots < value_size && value[value_size - num_dots - 1] == '.')
    num_dots++;

  if (num_dots == value.size())
    return true;  // String is all dots.

  if (IsSlash(value[value_size - num_dots - 1]))
    return true;  // String is a [back]slash followed by 0 or more dots.

  // Anything else.
  return false;
}

void AddCallLocationToError(const ParseNode* blame_node, Err* err) {
  if (blame_node && err->has_error()) {
    Err new_err(blame_node, err->message(), err->help_text());
    new_err.AppendSubErr(
        Err(err->location(), "The value that caused the error."));
    *err = std::move(new_err);
  }
}

Value ConvertOnePath(const Scope* scope,
                     const FunctionCallNode* function,
                     const Value& value,
                     const SourceDir& from_dir,
                     const SourceDir& to_dir,
                     bool convert_to_system_absolute,
                     Err* err) {
  Value result;  // Ensure return value optimization.

  if (!value.VerifyTypeIs(Value::STRING, err))
    return result;
  const std::string& string_value = value.string_value();

  bool looks_like_dir = ValueLooksLikeDir(string_value);

  // System-absolute output special case.
  if (convert_to_system_absolute) {
    base::FilePath system_path;
    if (looks_like_dir) {
      system_path = scope->settings()->build_settings()->GetFullPath(
          from_dir.ResolveRelativeDir(
              value, err,
              scope->settings()->build_settings()->root_path_utf8()));
    } else {
      system_path = scope->settings()->build_settings()->GetFullPath(
          from_dir.ResolveRelativeFile(
              value, err,
              scope->settings()->build_settings()->root_path_utf8()));
    }
    if (err->has_error())
      return Value();

    result = Value(function, FilePathToUTF8(system_path));
    if (looks_like_dir)
      MakeSlashEndingMatchInput(string_value, &result.string_value());
    return result;
  }

  result = Value(function, Value::STRING);
  if (looks_like_dir) {
    SourceDir resolved = from_dir.ResolveRelativeDir(
        value, err, scope->settings()->build_settings()->root_path_utf8());
    if (err->has_error()) {
      return Value();
    }
    result.string_value() =
        RebasePath(resolved.value(), to_dir,
                   scope->settings()->build_settings()->root_path_utf8());
    MakeSlashEndingMatchInput(string_value, &result.string_value());
  } else {
    SourceFile resolved_file = from_dir.ResolveRelativeFile(
        value, err, scope->settings()->build_settings()->root_path_utf8());
    if (err->has_error()) {
      return Value();
    }
    result.string_value() =
        RebasePath(resolved_file.value(), to_dir,
                   scope->settings()->build_settings()->root_path_utf8());
  }

  return result;
}

}  // namespace

const char kRebasePath[] = "rebase_path";
const char kRebasePath_HelpShort[] =
    "rebase_path: Rebase a file or directory to another location.";
const char kRebasePath_Help[] =
    R"(rebase_path: Rebase a file or directory to another location.

  converted = rebase_path(input,
                          new_base = "",
                          current_base = ".")

  Takes a string argument representing a file name, or a list of such strings
  and converts it/them to be relative to a different base directory.

  When invoking the compiler or scripts, GN will automatically convert sources
  and include directories to be relative to the build directory. However, if
  you're passing files directly in the "args" array or doing other manual
  manipulations where GN doesn't know something is a file name, you will need
  to convert paths to be relative to what your tool is expecting.

  The common case is to use this to convert paths relative to the current
  directory to be relative to the build directory (which will be the current
  directory when executing scripts).

  If you want to convert a file path to be source-absolute (that is, beginning
  with a double slash like "//foo/bar"), you should use the get_path_info()
  function. This function won't work because it will always make relative
  paths, and it needs to support making paths relative to the source root, so
  it can't also generate source-absolute paths without more special-cases.

Arguments

  input
      A string or list of strings representing file or directory names. These
      can be relative paths ("foo/bar.txt"), system absolute paths
      ("/foo/bar.txt"), or source absolute paths ("//foo/bar.txt").

  new_base
      The directory to convert the paths to be relative to. This can be an
      absolute path or a relative path (which will be treated as being relative
      to the current BUILD-file's directory).

      As a special case, if new_base is the empty string (the default), all
      paths will be converted to system-absolute native style paths with system
      path separators. This is useful for invoking external programs.

  current_base
      Directory representing the base for relative paths in the input. If this
      is not an absolute path, it will be treated as being relative to the
      current build file. Use "." (the default) to convert paths from the
      current BUILD-file's directory.

Return value

  The return value will be the same type as the input value (either a string or
  a list of strings). All relative and source-absolute file names will be
  converted to be relative to the requested output System-absolute paths will
  be unchanged.

  Whether an output path will end in a slash will match whether the
  corresponding input path ends in a slash. It will return "." or "./"
  (depending on whether the input ends in a slash) to avoid returning empty
  strings. This means if you want a root path ("//" or "/") not ending in a
  slash, you can add a dot ("//.").

Example

  # Convert a file in the current directory to be relative to the build
  # directory (the current dir when executing compilers and scripts).
  foo = rebase_path("myfile.txt", root_build_dir)
  # might produce "../../project/myfile.txt".

  # Convert a file to be system absolute:
  foo = rebase_path("myfile.txt")
  # Might produce "D:\\source\\project\\myfile.txt" on Windows or
  # "/home/you/source/project/myfile.txt" on Linux.

  # Typical usage for converting to the build directory for a script.
  action("myscript") {
    # Don't convert sources, GN will automatically convert these to be relative
    # to the build directory when it constructs the command line for your
    # script.
    sources = [ "foo.txt", "bar.txt" ]

    # Extra file args passed manually need to be explicitly converted
    # to be relative to the build directory:
    args = [
      "--data",
      rebase_path("//mything/data/input.dat", root_build_dir),
      "--rel",
      rebase_path("relative_path.txt", root_build_dir)
    ] + rebase_path(sources, root_build_dir)
  }
)";

Value RunRebasePath(Scope* scope,
                    const FunctionCallNode* function,
                    const std::vector<Value>& args,
                    Err* err) {
  Value result;

  // Argument indices.
  static const size_t kArgIndexInputs = 0;
  static const size_t kArgIndexDest = 1;
  static const size_t kArgIndexFrom = 2;

  // Inputs.
  if (args.size() < 1 || args.size() > 3) {
    *err = Err(function->function(), "Wrong # of arguments for rebase_path.");
    return result;
  }
  const Value& inputs = args[kArgIndexInputs];
  const ParseNode* inputs_origin = nullptr;
  if (function->args() &&
      function->args()->contents().size() > kArgIndexInputs) {
    inputs_origin = function->args()->contents()[kArgIndexInputs].get();
  }

  // To path.
  bool convert_to_system_absolute = true;
  SourceDir to_dir;
  const SourceDir& current_dir = scope->GetSourceDir();
  if (args.size() > kArgIndexDest) {
    if (!args[kArgIndexDest].VerifyTypeIs(Value::STRING, err))
      return result;
    if (!args[kArgIndexDest].string_value().empty()) {
      to_dir = current_dir.ResolveRelativeDir(
          args[kArgIndexDest], err,
          scope->settings()->build_settings()->root_path_utf8());
      if (err->has_error())
        return Value();
      convert_to_system_absolute = false;
    }
  }

  // From path.
  SourceDir from_dir;
  if (args.size() > kArgIndexFrom) {
    if (!args[kArgIndexFrom].VerifyTypeIs(Value::STRING, err))
      return result;
    from_dir = current_dir.ResolveRelativeDir(
        args[kArgIndexFrom], err,
        scope->settings()->build_settings()->root_path_utf8());
    if (err->has_error())
      return Value();
  } else {
    // Default to current directory if unspecified.
    from_dir = current_dir;
  }

  // Path conversion.
  if (inputs.type() == Value::STRING) {
    Value ret = ConvertOnePath(scope, function, inputs, from_dir, to_dir,
                               convert_to_system_absolute, err);
    if (err->has_error()) {
      AddCallLocationToError(inputs_origin, err);
    }
    return ret;

  } else if (inputs.type() == Value::LIST) {
    result = Value(function, Value::LIST);
    result.list_value().reserve(inputs.list_value().size());

    for (const auto& input : inputs.list_value()) {
      result.list_value().push_back(
          ConvertOnePath(scope, function, input, from_dir, to_dir,
                         convert_to_system_absolute, err));
      if (err->has_error()) {
        AddCallLocationToError(inputs_origin, err);
        result = Value();
        return result;
      }
    }
    return result;
  }

  *err = Err(function->function(), "rebase_path requires a list or a string.");
  return result;
}

}  // namespace functions
