// 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(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;
}

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

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

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

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

  if (!is_sub_err) {
    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);
}
