// 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 "gn/err.h"

#include <stddef.h>

#include <atomic>
#include <mutex>

#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "gn/filesystem_utils.h"
#include "gn/input_file.h"
#include "gn/parse_tree.h"
#include "gn/standard_out.h"
#include "gn/switches.h"
#include "gn/tokenizer.h"
#include "gn/value.h"

namespace {

std::atomic<int> g_num_errors_printed{0};

int GetErrorLimit() {
  static int g_error_limit = 10;
  static std::once_flag flag;
  std::call_once(flag, []() {
    if (base::CommandLine::InitializedForCurrentProcess()) {
      const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
      if (cmdline && cmdline->HasSwitch(switches::kErrorLimit)) {
        std::string limit_str =
            cmdline->GetSwitchValueString(switches::kErrorLimit);
        int parsed_limit;
        if (base::StringToInt(limit_str, &parsed_limit)) {
          g_error_limit = parsed_limit;
        }
      }
    }
  });
  return g_error_limit;
}

std::string GetNthLine(std::string_view data, int n) {
  size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
  size_t end = line_off + 1;
  while (end < data.size() && !Tokenizer::IsNewline(data, end))
    end++;
  return std::string(data.substr(line_off, end - line_off));
}

void FillRangeOnLine(const LocationRange& range,
                     int line_number,
                     std::string* line) {
  // Only bother if the range's begin or end overlaps the line. If the entire
  // line is highlighted as a result of this range, it's not very helpful.
  if (range.begin().line_number() != line_number &&
      range.end().line_number() != line_number)
    return;

  // Watch out, the char offsets in the location are 1-based, so we have to
  // subtract 1.
  int begin_char;
  if (range.begin().line_number() < line_number)
    begin_char = 0;
  else
    begin_char = range.begin().column_number() - 1;

  int end_char;
  if (range.end().line_number() > line_number)
    end_char = static_cast<int>(line->size());  // Ending is non-inclusive.
  else
    end_char = range.end().column_number() - 1;

  CHECK(end_char >= begin_char);
  CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
  CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
  for (int i = begin_char; i < end_char; i++)
    line->at(i) = '-';
}

// The line length is used to clip the maximum length of the markers we'll
// make if the error spans more than one line (like unterminated literals).
void OutputHighlighedPosition(const Location& location,
                              const Err::RangeList& ranges,
                              size_t line_length) {
  // Make a buffer of the line in spaces.
  std::string highlight;
  highlight.resize(line_length);
  for (size_t i = 0; i < line_length; i++)
    highlight[i] = ' ';

  // Highlight all the ranges on the line.
  for (const auto& range : ranges)
    FillRangeOnLine(range, location.line_number(), &highlight);

  // Allow the marker to be one past the end of the line for marking the end.
  highlight.push_back(' ');
  CHECK(location.column_number() - 1 >= 0 &&
        location.column_number() - 1 < static_cast<int>(highlight.size()));
  highlight[location.column_number() - 1] = '^';

  // Trim unused spaces from end of line.
  while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
    highlight.resize(highlight.size() - 1);

  highlight += "\n";
  OutputString(highlight, DECORATION_BLUE);
}

}  // namespace

Err::Err(const Err& other) {
  if (other.info_)
    info_ = std::make_unique<ErrInfo>(*other.info_);
}

Err::Err(const Location& location,
         const std::string& msg,
         const std::string& help)
    : info_(std::make_unique<ErrInfo>(location, msg, help)) {}

Err::Err(const LocationRange& range,
         const std::string& msg,
         const std::string& help)
    : info_(std::make_unique<ErrInfo>(range.begin(), msg, help)) {
  info_->ranges.push_back(range);
}

Err::Err(const Token& token, const std::string& msg, const std::string& help)
    : info_(std::make_unique<ErrInfo>(token.location(), msg, help)) {
  info_->ranges.push_back(token.range());
}

Err::Err(const ParseNode* node,
         const std::string& msg,
         const std::string& help_text)
    : info_(std::make_unique<ErrInfo>(Location(), msg, help_text)) {
  // Node will be null in certain tests.
  if (node) {
    LocationRange range = node->GetRange();
    info_->location = range.begin();
    info_->ranges.push_back(range);
  }
}

Err::Err(const Value& value,
         const std::string& msg,
         const std::string& help_text)
    : info_(std::make_unique<ErrInfo>(Location(), msg, help_text)) {
  if (value.origin()) {
    LocationRange range = value.origin()->GetRange();
    info_->location = range.begin();
    info_->ranges.push_back(range);
  }
}

Err& Err::operator=(const Err& other) {
  if (other.info_) {
    info_ = std::make_unique<ErrInfo>(*other.info_);
  } else {
    info_.reset();
  }
  return *this;
}

bool Err::PrintToStdout() const {
  return InternalPrintToStdout(false, true);
}

bool Err::PrintNonfatalToStdout() const {
  return InternalPrintToStdout(false, false);
}

void Err::AppendSubErr(const Err& err) {
  info_->sub_errs.push_back(err);
}

bool Err::InternalPrintToStdout(bool is_sub_err, bool is_fatal) const {
  DCHECK(info_);

  if (!is_sub_err) {
    int limit = GetErrorLimit();
    if (limit >= 0) {
      int printed = ++g_num_errors_printed;
      if (printed > limit) {
        if (printed == limit + 1) {
          OutputString(
              "Too many errors/warnings. Suppressing further messages.\n"
              "You can change the limit by passing --error-limit=<number>.\n",
              DECORATION_RED);
        }
        return false;
      }
    }

    if (is_fatal)
      OutputString("ERROR ", DECORATION_RED);
    else
      OutputString("WARNING ", DECORATION_MAGENTA);
  }

  // File name and location.
  const InputFile* input_file = info_->location.file();
  std::string loc_str = info_->location.Describe(true);
  if (!loc_str.empty()) {
    if (is_sub_err)
      loc_str.insert(0, "See ");
    else
      loc_str.insert(0, "at ");
    if (!info_->toolchain_label.is_null())
      loc_str += " ";
  }
  std::string toolchain_str;
  if (!info_->toolchain_label.is_null()) {
    toolchain_str +=
        "(" + info_->toolchain_label.GetUserVisibleName(false) + ")";
  }
  std::string colon;
  if (!loc_str.empty() || !toolchain_str.empty())
    colon = ": ";
  OutputString(loc_str + toolchain_str + colon + info_->message + "\n");

  // Quoted line.
  if (input_file) {
    std::string line =
        GetNthLine(input_file->contents(), info_->location.line_number());
    if (!base::ContainsOnlyChars(line, base::kWhitespaceASCII)) {
      OutputString(line + "\n", DECORATION_DIM);
      OutputHighlighedPosition(info_->location, info_->ranges, line.size());
    }
  }

  // Optional help text.
  if (!info_->help_text.empty())
    OutputString(info_->help_text + "\n");

  // Sub errors.
  for (const auto& sub_err : info_->sub_errs)
    sub_err.InternalPrintToStdout(true, is_fatal);

  return true;
}
