// 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 "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/tokenizer.h"
#include "gn/value.h"

namespace {

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() : has_error_(false) {}

Err::Err(const Location& location,
         const std::string& msg,
         const std::string& help)
    : has_error_(true), location_(location), message_(msg), help_text_(help) {}

Err::Err(const LocationRange& range,
         const std::string& msg,
         const std::string& help)
    : has_error_(true),
      location_(range.begin()),
      message_(msg),
      help_text_(help) {
  ranges_.push_back(range);
}

Err::Err(const Token& token, const std::string& msg, const std::string& help)
    : has_error_(true),
      location_(token.location()),
      message_(msg),
      help_text_(help) {
  ranges_.push_back(token.range());
}

Err::Err(const ParseNode* node,
         const std::string& msg,
         const std::string& help_text)
    : has_error_(true), message_(msg), help_text_(help_text) {
  // Node will be null in certain tests.
  if (node) {
    LocationRange range = node->GetRange();
    location_ = range.begin();
    ranges_.push_back(range);
  }
}

Err::Err(const Value& value,
         const std::string msg,
         const std::string& help_text)
    : has_error_(true), message_(msg), help_text_(help_text) {
  if (value.origin()) {
    LocationRange range = value.origin()->GetRange();
    location_ = range.begin();
    ranges_.push_back(range);
  }
}

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

Err::~Err() = default;

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

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

void Err::AppendSubErr(const Err& err) {
  sub_errs_.push_back(err);
}

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

  if (!is_sub_err) {
    if (is_fatal)
      OutputString("ERROR ", DECORATION_RED);
    else
      OutputString("WARNING ", DECORATION_RED);
  }

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

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

  // Optional help text.
  if (!help_text_.empty())
    OutputString(help_text_ + "\n");

  // Sub errors.
  for (const auto& sub_err : sub_errs_)
    sub_err.InternalPrintToStdout(true, is_fatal);
}
