/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmDocumentationFormatter.h"

#include <algorithm> // IWYU pragma: keep
#include <cassert>
#include <iomanip>
#include <ostream>
#include <string>
#include <vector>

#include "cmDocumentationEntry.h"
#include "cmDocumentationSection.h"

namespace {
const char* skipSpaces(const char* ptr)
{
  assert(ptr);
  for (; *ptr == ' '; ++ptr) {
    ;
  }
  return ptr;
}
const char* skipToSpace(const char* ptr)
{
  assert(ptr);
  for (; *ptr && (*ptr != '\n') && (*ptr != ' '); ++ptr) {
    ;
  }
  return ptr;
}
}

void cmDocumentationFormatter::PrintFormatted(std::ostream& os,
                                              std::string const& text) const
{
  if (text.empty()) {
    return;
  }

  struct Buffer
  {
    // clang-format off
    using PrinterFn = void (cmDocumentationFormatter::*)(
        std::ostream&, std::string const&
      ) const;
    // clang-format on
    std::string collected;
    const PrinterFn printer;
  };
  // const auto NORMAL_IDX = 0u;
  const auto PREFORMATTED_IDX = 1u;
  const auto HANDLERS_SIZE = 2u;
  Buffer buffers[HANDLERS_SIZE] = {
    { {}, &cmDocumentationFormatter::PrintParagraph },
    { {}, &cmDocumentationFormatter::PrintPreformatted }
  };

  const auto padding = std::string(this->TextIndent, ' ');

  for (std::size_t pos = 0u, eol = 0u; pos < text.size(); pos = eol) {
    const auto current_idx = std::size_t(text[pos] == ' ');
    // size_t(!bool(current_idx))
    const auto other_idx = current_idx ^ 1u;

    // Flush the other buffer if anything has been collected
    if (!buffers[other_idx].collected.empty()) {
      // NOTE Whatever the other index is, the current buffered
      // string expected to be empty.
      assert(buffers[current_idx].collected.empty());

      (this->*buffers[other_idx].printer)(os, buffers[other_idx].collected);
      buffers[other_idx].collected.clear();
    }

    // ATTENTION The previous implementation had called `PrintParagraph()`
    // **for every processed (char by char) input line**.
    // The method unconditionally append the `\n' character after the
    // printed text. To keep the backward-compatible behavior it's needed to
    // add the '\n' character to the previously collected line...
    if (!buffers[current_idx].collected.empty() &&
        current_idx != PREFORMATTED_IDX) {
      buffers[current_idx].collected += '\n';
    }

    // Lookup EOL
    eol = text.find('\n', pos);
    if (current_idx == PREFORMATTED_IDX) {
      buffers[current_idx].collected.append(padding);
    }
    buffers[current_idx].collected.append(
      text, pos, eol == std::string::npos ? eol : ++eol - pos);
  }

  for (auto& buf : buffers) {
    if (!buf.collected.empty()) {
      (this->*buf.printer)(os, buf.collected);
    }
  }
}

void cmDocumentationFormatter::PrintPreformatted(std::ostream& os,
                                                 std::string const& text) const
{
  os << text << '\n';
}

void cmDocumentationFormatter::PrintParagraph(std::ostream& os,
                                              std::string const& text) const
{
  if (this->TextIndent) {
    os << std::string(this->TextIndent, ' ');
  }
  this->PrintColumn(os, text);
  os << '\n';
}

void cmDocumentationFormatter::PrintColumn(std::ostream& os,
                                           std::string const& text) const
{
  // Print text arranged in an indented column of fixed width.
  bool newSentence = false;
  bool firstLine = true;

  assert(this->TextIndent < this->TextWidth);
  const std::ptrdiff_t width = this->TextWidth - this->TextIndent;
  std::ptrdiff_t column = 0;

  // Loop until the end of the text.
  for (const char *l = text.c_str(), *r = skipToSpace(text.c_str()); *l;
       l = skipSpaces(r), r = skipToSpace(l)) {
    // Does it fit on this line?
    if (r - l < width - column - std::ptrdiff_t(newSentence)) {
      // Word fits on this line.
      if (r > l) {
        if (column) {
          // Not first word on line.  Separate from the previous word
          // by a space, or two if this is a new sentence.
          os << &("  "[std::size_t(!newSentence)]);
          column += 1u + std::ptrdiff_t(newSentence);
        } else if (!firstLine && this->TextIndent) {
          // First word on line.  Print indentation unless this is the
          // first line.
          os << std::string(this->TextIndent, ' ');
        }

        // Print the word.
        os.write(l, r - l);
        newSentence = (*(r - 1) == '.');
      }

      if (*r == '\n') {
        // Text provided a newline.  Start a new line.
        os << '\n';
        ++r;
        column = 0;
        firstLine = false;
      } else {
        // No provided newline.  Continue this line.
        column += r - l;
      }
    } else {
      // Word does not fit on this line.  Start a new line.
      os << '\n';
      firstLine = false;
      if (r > l) {
        os << std::string(this->TextIndent, ' ');
        os.write(l, r - l);
        column = r - l;
        newSentence = (*(r - 1) == '.');
      } else {
        column = 0;
      }
    }
    // Move to beginning of next word.  Skip over whitespace.
  }
}

void cmDocumentationFormatter::PrintSection(
  std::ostream& os, cmDocumentationSection const& section)
{
  const std::size_t PREFIX_SIZE =
    sizeof(cmDocumentationEntry::CustomNamePrefix) + 1u;
  // length of the "= " literal (see below)
  const std::size_t SUFFIX_SIZE = 2u;
  // legacy magic number ;-)
  const std::size_t NAME_SIZE = 29u;

  const std::size_t PADDING_SIZE = PREFIX_SIZE + SUFFIX_SIZE;
  const std::size_t TITLE_SIZE = NAME_SIZE + PADDING_SIZE;

  const auto savedIndent = this->TextIndent;

  os << section.GetName() << '\n';

  for (cmDocumentationEntry const& entry : section.GetEntries()) {
    if (!entry.Name.empty()) {
      this->TextIndent = TITLE_SIZE;
      os << std::setw(PREFIX_SIZE) << std::left << entry.CustomNamePrefix
         << std::setw(int(std::max(NAME_SIZE, entry.Name.size())))
         << entry.Name;
      if (entry.Name.size() > NAME_SIZE) {
        os << '\n' << std::setw(int(this->TextIndent - PREFIX_SIZE)) << ' ';
      }
      os << "= ";
      this->PrintColumn(os, entry.Brief);
      os << '\n';
    } else {
      os << '\n';
      this->TextIndent = 0u;
      this->PrintFormatted(os, entry.Brief);
    }
  }

  os << '\n';

  this->TextIndent = savedIndent;
}
