// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/console/format_table.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/string_util.h"

namespace zxdb {

namespace {

template <typename CellType>
bool SpansRemainingCols(const std::vector<ColSpec>& spec, const std::vector<CellType>& row,
                        size_t column) {
  // The last item in a row will span all remaining columns if there are more
  // in the column spec.
  return column == row.size() - 1 && column < spec.size() - 1;
}

// Character width for both cell types.
int CellWidth(const std::string& str) { return static_cast<int>(UnicodeCharWidth(str)); }
int CellWidth(const OutputBuffer& buf) { return static_cast<int>(buf.UnicodeCharWidth()); }

// Appends the given cell type to the OutputBuffer. The Syntax is ignored
// in the OutputBuffer->OutputBuffer variant because it will contain its own
// syntax.
void AppendCell(const std::string& str, Syntax syntax, OutputBuffer* out) {
  out->Append(syntax, str);
}
void AppendCell(const OutputBuffer& buf, Syntax, OutputBuffer* out) { out->Append(buf); }

// Appends the given string to the output, padding with spaces to the width
// as necessary.
template <typename CellType>
void AppendPadded(const CellType& cell, int width, Align align, Syntax syntax, bool is_last_col,
                  OutputBuffer* out) {
  int pad = std::max(0, width - CellWidth(cell));
  if (pad > 0 && align == Align::kRight)
    out->Append(std::string(pad, ' '));

  AppendCell(cell, syntax, out);

  // Padding on the right. Don't add for the last col.
  if (pad > 0 && !is_last_col && align == Align::kLeft)
    out->Append(std::string(pad, ' '));

  // Separator after columns for all but the last.
  if (!is_last_col)
    out->Append(std::string(1, ' '));
}

// Backend for FormatColumns variants. The requirements are that CellWidth()
// and AppendCell() are define for CellType.
template <typename CellType>
void FormatTableT(const std::vector<ColSpec>& spec, const std::vector<std::vector<CellType>>& rows,
                  OutputBuffer* out) {
  std::vector<int> max;  // Max width of each column.

  // Max widths of headings.
  bool has_head = false;
  for (const auto& col : spec) {
    max.push_back(UnicodeCharWidth(col.head));
    has_head |= !col.head.empty();
  }

  // Max widths of contents.
  for (const auto& row : rows) {
    FX_DCHECK(row.size() <= max.size())
        << "Column spec size is too small (" << row.size() << " vs " << max.size() << ").";
    for (size_t i = 0; i < row.size(); i++) {
      // Only count the ones that don't overflow (either because they span the
      // remaining columns, or because they're beyond max_width).
      if (!SpansRemainingCols(spec, row, i)) {
        int cell_size = CellWidth(row[i]);
        if (spec[i].max_width == 0 || cell_size <= spec[i].max_width)
          max[i] = std::max(max[i], cell_size);
      }
    }
  }

  // Print heading.
  if (has_head) {
    for (size_t i = 0; i < max.size(); i++) {
      const ColSpec& col = spec[i];
      if (col.pad_left)
        out->Append(Syntax::kNormal, std::string(col.pad_left, ' '));
      AppendPadded(col.head, max[i], col.align, Syntax::kHeading, i == max.size() - 1, out);
    }
    out->Append("\n");
  }

  // Print rows.
  for (const auto& row : rows) {
    std::string text;
    for (size_t i = 0; i < row.size(); i++) {
      const ColSpec& col = spec[i];
      if (SpansRemainingCols(spec, row, i)) {
        AppendCell(row[i], col.syntax, out);
      } else {
        if (col.pad_left)
          out->Append(Syntax::kNormal, std::string(col.pad_left, ' '));
        AppendPadded(row[i], max[i], col.align, col.syntax, i == max.size() - 1, out);
      }
    }
    out->Append("\n");
  }
}

}  // namespace

void FormatTable(const std::vector<ColSpec>& spec,
                 const std::vector<std::vector<std::string>>& rows, OutputBuffer* out) {
  FormatTableT<std::string>(spec, rows, out);
}

void FormatTable(const std::vector<ColSpec>& spec,
                 const std::vector<std::vector<OutputBuffer>>& rows, OutputBuffer* out) {
  FormatTableT<OutputBuffer>(spec, rows, out);
}

}  // namespace zxdb
