// 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 <iterator>
#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::Note:
      return "note";
    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) {
    std::fill_n(std::ostream_iterator<char>(stream), n, 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 first = true;
  for (auto diag : list) {
    state.set_style({});
    if (!first) {
      state.newline();
    }
    format(diag, state);
    first = false;
  }

  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::Note:
      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_num = rng.begin.line;
         (line_num <= rng.end.line) &&
         (line_num <= src.file_content->lines.size());
         line_num++) {
      auto& line = src.file_content->lines[line_num - 1];
      auto line_len = line.size();

      for (auto c : line) {
        if (c == '\t') {
          state.repeat(' ', style_.tab_width);
        } else {
          state << c;
        }
      }

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

      // Count the number of glyphs in the line span.
      // start and end use 1-based indexing .
      auto num_glyphs = [&](size_t start, size_t end) {
        size_t count = 0;
        start = (start > 0) ? (start - 1) : 0;
        end = (end > 0) ? (end - 1) : 0;
        for (size_t i = start; (i < end) && (i < line_len); i++) {
          count += (line[i] == '\t') ? style_.tab_width : 1;
        }
        return count;
      };

      if (line_num == rng.begin.line && line_num == rng.end.line) {
        // Single line
        state.repeat(' ', num_glyphs(1, rng.begin.column));
        state.repeat('^', std::max<size_t>(
                              num_glyphs(rng.begin.column, rng.end.column), 1));
      } else if (line_num == rng.begin.line) {
        // Start of multi-line
        state.repeat(' ', num_glyphs(1, rng.begin.column));
        state.repeat('^', num_glyphs(rng.begin.column, line_len + 1));
      } else if (line_num == rng.end.line) {
        // End of multi-line
        state.repeat('^', num_glyphs(1, rng.end.column));
      } else {
        // Middle of multi-line
        state.repeat('^', num_glyphs(1, line_len + 1));
      }
      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
