// Copyright 2014 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 "gn/substitution_pattern.h"

#include <stddef.h>

#include "base/strings/string_number_conversions.h"
#include "gn/build_settings.h"
#include "gn/err.h"
#include "gn/filesystem_utils.h"
#include "gn/value.h"

SubstitutionPattern::Subrange::Subrange() : type(&SubstitutionLiteral) {}

SubstitutionPattern::Subrange::Subrange(const Substitution* t,
                                        const std::string& l)
    : type(t), literal(l) {}

SubstitutionPattern::Subrange::~Subrange() = default;

SubstitutionPattern::SubstitutionPattern() : origin_(nullptr) {}

SubstitutionPattern::SubstitutionPattern(const SubstitutionPattern& other) =
    default;

SubstitutionPattern::~SubstitutionPattern() = default;

bool SubstitutionPattern::Parse(const Value& value, Err* err) {
  if (!value.VerifyTypeIs(Value::STRING, err))
    return false;
  return Parse(value.string_value(), value.origin(), err);
}

bool SubstitutionPattern::Parse(const std::string& str,
                                const ParseNode* origin,
                                Err* err) {
  DCHECK(ranges_.empty());  // Should only be called once.

  size_t cur = 0;
  while (true) {
    size_t next = str.find("{{", cur);

    // Pick up everything from the previous spot to here as a literal.
    if (next == std::string::npos) {
      if (cur != str.size())
        ranges_.push_back(Subrange(&SubstitutionLiteral, str.substr(cur)));
      break;
    } else if (next > cur) {
      ranges_.push_back(
          Subrange(&SubstitutionLiteral, str.substr(cur, next - cur)));
    }

    // Find which specific pattern this corresponds to.
    bool found_match = false;
    for (const SubstitutionTypes* types : AllSubstitutions) {
      for (const Substitution* sub : *types) {
        const char* cur_pattern = sub->name;
        size_t cur_len = strlen(cur_pattern);
        if (str.compare(next, cur_len, cur_pattern) == 0) {
          ranges_.push_back(Subrange(sub));
          cur = next + cur_len;
          found_match = true;
          break;
        }
      }
    }

    // Expect all occurrences of {{ to resolve to a pattern.
    if (!found_match) {
      // Could make this error message more friendly if it comes up a lot. But
      // most people will not be writing substitution patterns and the code
      // to exactly indicate the error location is tricky.
      *err = Err(origin, "Unknown substitution pattern",
                 "Found a {{ at offset " + base::NumberToString(next) +
                     " and did not find a known substitution following it.");
      ranges_.clear();
      return false;
    }
  }

  origin_ = origin;

  // Fill required types vector.
  SubstitutionBits bits;
  FillRequiredTypes(&bits);
  bits.FillVector(&required_types_);
  return true;
}

// static
SubstitutionPattern SubstitutionPattern::MakeForTest(const char* str) {
  Err err;
  SubstitutionPattern pattern;
  CHECK(pattern.Parse(str, nullptr, &err)) << err.message() << "\n"
                                           << err.help_text();
  return pattern;
}

std::string SubstitutionPattern::AsString() const {
  std::string result;
  for (const auto& elem : ranges_) {
    if (elem.type == &SubstitutionLiteral)
      result.append(elem.literal);
    else
      result.append(elem.type->name);
  }
  return result;
}

void SubstitutionPattern::FillRequiredTypes(SubstitutionBits* bits) const {
  for (const auto& elem : ranges_) {
    if (elem.type != &SubstitutionLiteral)
      bits->used.insert(elem.type);
  }
}

bool SubstitutionPattern::IsInOutputDir(const BuildSettings* build_settings,
                                        Err* err) const {
  if (ranges_.empty()) {
    *err = Err(origin_, "This is empty but I was expecting an output file.");
    return false;
  }

  if (ranges_[0].type == &SubstitutionLiteral) {
    // If the first thing is a literal, it must start with the output dir.
    if (!EnsureStringIsInOutputDir(build_settings->build_dir(),
                                   ranges_[0].literal, origin_, err))
      return false;
  } else {
    // Otherwise, the first subrange must be a pattern that expands to
    // something in the output directory.
    if (!SubstitutionIsInOutputDir(ranges_[0].type)) {
      *err =
          Err(origin_, "File is not inside output directory.",
              "The given file should be in the output directory. Normally you\n"
              "would specify\n\"$target_out_dir/foo\" or "
              "\"{{source_gen_dir}}/foo\".");
      return false;
    }
  }

  return true;
}
