// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/diagnostic/formatter.h"

#include <algorithm>
#include <sstream>
#include <vector>

#include "src/diagnostic/diagnostic.h"
#include "src/diagnostic/printer.h"

namespace tint {
namespace diag {
namespace {

const char* to_str(Severity severity) {
  switch (severity) {
    case Severity::Info:
      return "info";
    case Severity::Warning:
      return "warning";
    case Severity::Error:
      return "error";
    case Severity::InternalCompilerError:
      return "internal compiler error";
    case Severity::Fatal:
      return "fatal";
  }
  return "";
}

std::string to_str(const Source::Location& location) {
  std::stringstream ss;
  if (location.line > 0) {
    ss << location.line;
    if (location.column > 0) {
      ss << ":" << location.column;
    }
  }
  return ss.str();
}

}  // namespace

/// State holds the internal formatter state for a format() call.
struct Formatter::State {
  /// Constructs a State associated with the given printer.
  /// @param p the printer to write formatted messages to.
  explicit State(Printer* p) : printer(p) {}
  ~State() { flush(); }

  /// set_style() sets the current style to new_style, flushing any pending
  /// messages to the printer if the style changed.
  /// @param new_style the new style to apply for future written messages.
  void set_style(const diag::Style& new_style) {
    if (style.color != new_style.color || style.bold != new_style.bold) {
      flush();
      style = new_style;
    }
  }

  /// flush writes any pending messages to the printer, clearing the buffer.
  void flush() {
    auto str = stream.str();
    if (str.length() > 0) {
      printer->write(str, style);
      std::stringstream reset;
      stream.swap(reset);
    }
  }

  /// operator<< queues msg to be written to the printer.
  /// @param msg the value or string to write to the printer
  /// @returns this State so that calls can be chained
  template <typename T>
  State& operator<<(const T& msg) {
    stream << msg;
    return *this;
  }

  /// newline queues a newline to be written to the printer.
  void newline() { stream << std::endl; }

  /// repeat queues the character c to be written to the printer n times.
  /// @param c the character to print `n` times
  /// @param n the number of times to print character `c`
  void repeat(char c, size_t n) {
    while (n-- > 0) {
      stream << c;
    }
  }

 private:
  Printer* printer;
  diag::Style style;
  std::stringstream stream;
};

Formatter::Formatter() {}
Formatter::Formatter(const Style& style) : style_(style) {}

void Formatter::format(const List& list, Printer* printer) const {
  State state{printer};

  bool please_report_bug = false;
  bool first = true;
  for (auto diag : list) {
    state.set_style({});
    if (!first) {
      state.newline();
    }
    format(diag, state);
    first = false;

    if (static_cast<int>(diag.severity) > static_cast<int>(Severity::Error)) {
      please_report_bug = true;
    }
  }
  if (please_report_bug) {
    state.set_style({Color::kRed, true});
    state << R"(
********************************************************************
*  The tint shader compiler has encountered an unexpected error.   *
*                                                                  *
*  Please help us fix this issue by submitting a bug report at     *
*  crbug.com/tint with the source program that triggered the bug.  *
********************************************************************
)";
  }

  if (style_.print_newline_at_end) {
    state.newline();
  }
}

void Formatter::format(const Diagnostic& diag, State& state) const {
  auto const& src = diag.source;
  auto const& rng = src.range;
  bool has_code = diag.code != nullptr && diag.code[0] != '\0';

  state.set_style({Color::kDefault, true});

  struct TextAndColor {
    std::string text;
    Color color;
    bool bold = false;
  };
  std::vector<TextAndColor> prefix;
  prefix.reserve(6);

  if (style_.print_file && !src.file_path.empty()) {
    if (rng.begin.line > 0) {
      prefix.emplace_back(TextAndColor{src.file_path + ":" + to_str(rng.begin),
                                       Color::kDefault});
    } else {
      prefix.emplace_back(TextAndColor{src.file_path, Color::kDefault});
    }
  } else if (rng.begin.line > 0) {
    prefix.emplace_back(TextAndColor{to_str(rng.begin), Color::kDefault});
  }

  Color severity_color = Color::kDefault;
  switch (diag.severity) {
    case Severity::Info:
      break;
    case Severity::Warning:
      severity_color = Color::kYellow;
      break;
    case Severity::Error:
      severity_color = Color::kRed;
      break;
    case Severity::Fatal:
    case Severity::InternalCompilerError:
      severity_color = Color::kMagenta;
      break;
  }
  if (style_.print_severity) {
    prefix.emplace_back(
        TextAndColor{to_str(diag.severity), severity_color, true});
  }
  if (has_code) {
    prefix.emplace_back(TextAndColor{diag.code, severity_color});
  }

  for (size_t i = 0; i < prefix.size(); i++) {
    if (i > 0) {
      state << " ";
    }
    state.set_style({prefix[i].color, prefix[i].bold});
    state << prefix[i].text;
  }

  state.set_style({Color::kDefault, true});
  if (!prefix.empty()) {
    state << ": ";
  }
  state << diag.message;

  if (style_.print_line && src.file_content != nullptr && rng.begin.line > 0) {
    state.newline();
    state.set_style({Color::kDefault, false});

    for (size_t line = rng.begin.line; line <= rng.end.line; line++) {
      if (line < src.file_content->lines.size() + 1) {
        auto len = src.file_content->lines[line - 1].size();

        state << src.file_content->lines[line - 1];

        state.newline();
        state.set_style({Color::kCyan, false});

        if (line == rng.begin.line && line == rng.end.line) {
          // Single line
          state.repeat(' ', rng.begin.column - 1);
          state.repeat('^',
                       std::max<size_t>(rng.end.column - rng.begin.column, 1));
        } else if (line == rng.begin.line) {
          // Start of multi-line
          state.repeat(' ', rng.begin.column - 1);
          state.repeat('^', len - (rng.begin.column - 1));
        } else if (line == rng.end.line) {
          // End of multi-line
          state.repeat('^', rng.end.column - 1);
        } else {
          // Middle of multi-line
          state.repeat('^', len);
        }
        state.newline();
      }
    }

    state.set_style({});
  }
}

std::string Formatter::format(const List& list) const {
  StringPrinter printer;
  format(list, &printer);
  return printer.str();
}

Formatter::~Formatter() = default;

}  // namespace diag
}  // namespace tint
