// 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/writer/text_generator.h"

#include <algorithm>
#include <limits>

#include "src/utils/get_or_create.h"

namespace tint {
namespace writer {

TextGenerator::TextGenerator(const Program* program)
    : program_(program), builder_(ProgramBuilder::Wrap(program)) {}

TextGenerator::~TextGenerator() = default;

std::string TextGenerator::UniqueIdentifier(const std::string& prefix) {
  return builder_.Symbols().NameFor(builder_.Symbols().New(prefix));
}

std::string TextGenerator::StructName(const sem::Struct* s) {
  auto name = builder_.Symbols().NameFor(s->Name());
  if (name.size() > 0 && name[0] == '_') {
    name = utils::GetOrCreate(builtin_struct_names_, s,
                              [&] { return UniqueIdentifier(name.substr(1)); });
  }
  return name;
}

std::string TextGenerator::TrimSuffix(std::string str,
                                      const std::string& suffix) {
  if (str.size() >= suffix.size()) {
    if (str.substr(str.size() - suffix.size(), suffix.size()) == suffix) {
      return str.substr(0, str.size() - suffix.size());
    }
  }
  return str;
}

TextGenerator::LineWriter::LineWriter(TextBuffer* buf) : buffer(buf) {}

TextGenerator::LineWriter::LineWriter(LineWriter&& other) {
  buffer = other.buffer;
  other.buffer = nullptr;
}

TextGenerator::LineWriter::~LineWriter() {
  if (buffer) {
    buffer->Append(os.str());
  }
}

TextGenerator::TextBuffer::TextBuffer() = default;
TextGenerator::TextBuffer::~TextBuffer() = default;

void TextGenerator::TextBuffer::IncrementIndent() {
  current_indent += 2;
}

void TextGenerator::TextBuffer::DecrementIndent() {
  current_indent = std::max(2u, current_indent) - 2u;
}

void TextGenerator::TextBuffer::Append(const std::string& line) {
  lines.emplace_back(Line{current_indent, line});
}

void TextGenerator::TextBuffer::Insert(const std::string& line,
                                       size_t before,
                                       uint32_t indent) {
  if (before >= lines.size()) {
    diag::List d;
    TINT_ICE(Writer, d)
        << "TextBuffer::Insert() called with before >= lines.size()\n"
        << "  before:" << before << "\n"
        << "  lines.size(): " << lines.size();
    return;
  }
  lines.insert(lines.begin() + before, Line{indent, line});
}

void TextGenerator::TextBuffer::Append(const TextBuffer& tb) {
  for (auto& line : tb.lines) {
    // TODO(bclayton): inefficent, consider optimizing
    lines.emplace_back(Line{current_indent + line.indent, line.content});
  }
}

void TextGenerator::TextBuffer::Insert(const TextBuffer& tb,
                                       size_t before,
                                       uint32_t indent) {
  if (before >= lines.size()) {
    diag::List d;
    TINT_ICE(Writer, d)
        << "TextBuffer::Insert() called with before >= lines.size()\n"
        << "  before:" << before << "\n"
        << "  lines.size(): " << lines.size();
    return;
  }
  size_t idx = 0;
  for (auto& line : tb.lines) {
    // TODO(bclayton): inefficent, consider optimizing
    lines.insert(lines.begin() + before + idx,
                 Line{indent + line.indent, line.content});
    idx++;
  }
}

std::string TextGenerator::TextBuffer::String(uint32_t indent /* = 0 */) const {
  std::stringstream ss;
  for (auto& line : lines) {
    if (!line.content.empty()) {
      for (uint32_t i = 0; i < indent + line.indent; i++) {
        ss << " ";
      }
      ss << line.content;
    }
    ss << std::endl;
  }
  return ss.str();
}

TextGenerator::ScopedParen::ScopedParen(std::ostream& stream) : s(stream) {
  s << "(";
}
TextGenerator::ScopedParen::~ScopedParen() {
  s << ")";
}

TextGenerator::ScopedIndent::ScopedIndent(TextGenerator* generator)
    : ScopedIndent(generator->current_buffer_) {}

TextGenerator::ScopedIndent::ScopedIndent(TextBuffer* buffer)
    : buffer_(buffer) {
  buffer_->IncrementIndent();
}
TextGenerator::ScopedIndent::~ScopedIndent() {
  buffer_->DecrementIndent();
}

}  // namespace writer
}  // namespace tint
