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

#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema.h"
#include "src/developer/debug/zxdb/client/setting_store.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/format_table.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

std::vector<std::string> ListToBullet(const std::vector<std::string>& list) {
  std::vector<std::string> output;
  output.reserve(list.size());
  auto bullet = GetBullet();
  for (const std::string& item : list) {
    output.emplace_back(
        fxl::StringPrintf("%s %s", bullet.c_str(), FormatConsoleString(item).c_str()));
  }
  return output;
}

// |add_heading| refers whether it should show the setting name or just list the values.
void AddSettingToTable(ConsoleContext* context, const std::string& name, const SettingValue& value,
                       std::vector<std::vector<OutputBuffer>>* rows, bool add_heading) {
  // TODO(donosoc): We need to check what level the setting comes from so we can highlight it in the
  //                listing.
  if (!value.is_list()) {
    // Normal values as just entered as key-value pairs.
    auto& row = rows->emplace_back();
    if (add_heading)
      row.emplace_back(Syntax::kVariable, name);
    row.emplace_back(FormatSettingValue(context, value));
  } else {
    // List get special treatment so that we can show them as bullet lists. This make reading them
    // much easier when the elements of the lists are long (eg. paths).
    auto bullet_list = ListToBullet(value.get_list());
    // Special case for empty list.
    if (bullet_list.empty()) {
      auto& row = rows->emplace_back();
      if (add_heading)
        row.emplace_back(Syntax::kVariable, name);
      row.emplace_back(Syntax::kComment, "<empty>");
    } else {
      for (size_t i = 0; i < bullet_list.size(); i++) {
        auto& row = rows->emplace_back();

        if (add_heading) {
          // The first entry has the setting name.
          auto title = i == 0 ? OutputBuffer(Syntax::kVariable, name) : OutputBuffer();
          auto it = row.emplace_back(std::move(title));
        }
        row.emplace_back(std::move(bullet_list[i]));
      }
    }
  }
}

}  // namespace

OutputBuffer FormatSettingStore(ConsoleContext* context, const SettingStore& store) {
  std::vector<std::vector<OutputBuffer>> rows;
  for (auto [key, _] : store.schema()->settings()) {
    auto value = store.GetValue(key);
    FX_DCHECK(!value.is_null());
    AddSettingToTable(context, key, value, &rows, true);
  }

  OutputBuffer table;
  FormatTable({ColSpec(Align::kLeft, 0, std::string(), 2), ColSpec()}, rows, &table);
  return table;
}

OutputBuffer FormatSetting(ConsoleContext* context, const std::string& name,
                           const std::string& description, const SettingValue& value) {
  // Heading, type, and help description.
  OutputBuffer out;
  out.Append(Syntax::kHeading, name);
  out.Append(Syntax::kComment, fxl::StringPrintf(" (%s)\n\n", SettingTypeToString(value.type())));

  out.Append(description);
  out.Append(OutputBuffer("\n\n"));

  out.Append(Syntax::kVariable, name);
  out.Append(" = ");

  // Nonempty lists are written on the following line. Everything else goes on the same line.
  if (value.is_list() && !value.get_list().empty())
    out.Append("\n");
  out.Append(FormatSettingShort(context, name, value, 2));

  return out;
}

OutputBuffer FormatSettingShort(ConsoleContext* context, const std::string& name,
                                const SettingValue& value, int list_indent) {
  FX_DCHECK(!value.is_null());

  // Only indent nonempty lists.
  int pad_left = value.is_list() && !value.get_list().empty() ? list_indent : 0;

  OutputBuffer out;
  std::vector<std::vector<OutputBuffer>> rows;
  AddSettingToTable(context, name, value, &rows, false);
  FormatTable(std::vector<ColSpec>{ColSpec(Align::kLeft, 0, std::string(), pad_left)},
              std::move(rows), &out);
  return out;
}

OutputBuffer FormatSettingValue(ConsoleContext* context, const SettingValue& value) {
  switch (value.type()) {
    case SettingType::kBoolean: {
      return OutputBuffer(BoolToString(value.get_bool()));
    }
    case SettingType::kInteger: {
      return std::to_string(value.get_int());
    }
    case SettingType::kString: {
      auto string = value.get_string();
      return string.empty() ? OutputBuffer(Syntax::kComment, "\"\"")
                            : OutputBuffer(FormatConsoleString(string));
    }
    case SettingType::kList: {
      const auto& list = value.get_list();
      std::string result;
      for (size_t i = 0; i < list.size(); i++) {
        if (i > 0)
          result += " ";
        result += FormatConsoleString(list[i]);
      }
      return OutputBuffer(result);
    }
    case SettingType::kExecutionScope: {
      return ExecutionScopeToString(context, value.get_execution_scope());
    }
    case SettingType::kInputLocations: {
      return FormatInputLocations(value.get_input_locations());
    }
    case SettingType::kNull: {
      return OutputBuffer(Syntax::kComment, "<null>");
    }
  }
}

}  // namespace zxdb
