// 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/tint/diagnostic/formatter.h"

#include <algorithm>
#include <iterator>
#include <vector>

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

namespace tint::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 != nullptr) {
    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 && 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();

      bool is_ascii = true;
      for (auto c : line) {
        if (c == '\t') {
          state.repeat(' ', style_.tab_width);
        } else {
          state << c;
        }
        if (c & 0x80) {
          is_ascii = false;
        }
      }

      state.newline();

      // If the line contains non-ascii characters, then we cannot assume that
      // a single utf8 code unit represents a single glyph, so don't attempt to
      // draw squiggles.
      if (!is_ascii) {
        continue;
      }

      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 tint::diag
