/*
 * Copyright 2017 The Cobalt Authors. All Rights Reserved.
 *
 * 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 "cobalt/browser/memory_settings/pretty_print.h"

#include <algorithm>
#include <string>
#include <vector>

#include "base/string_split.h"
#include "cobalt/browser/memory_settings/memory_settings.h"
#include "cobalt/browser/memory_settings/table_printer.h"
#include "starboard/log.h"
#include "starboard/string.h"

namespace cobalt {
namespace browser {
namespace memory_settings {
namespace {

std::string StringifyMemoryType(const MemorySetting& setting) {
  switch (setting.memory_type()) {
    case MemorySetting::kCPU: {
      return "CPU";
    }
    case MemorySetting::kGPU: {
      return "GPU";
    }
    case MemorySetting::kNotApplicable: {
      return "N/A";
    }
  }

  SB_NOTIMPLEMENTED() << "Unimplemented string for memory type: "
                      << setting.memory_type();
  return "UNKNOWN";
}

std::string StringifyValue(const MemorySetting* setting) {
  if (!setting->valid()) {
    return "N/A";
  }
  return setting->ValueToString();
}

void FillStream(size_t count, const char fill_ch, std::stringstream* ss) {
  for (size_t i = 0; i < count; ++i) {
    (*ss) << fill_ch;
  }
}

}  // namespace

std::string GeneratePrettyPrintTable(
    bool use_color_ascii,
    const std::vector<const MemorySetting*>& settings) {
  TablePrinter printer;
  if (use_color_ascii) {
    printer.set_text_color(TablePrinter::kGreen);
  }
  std::vector<std::string> header;
  header.push_back("SETTING NAME");
  header.push_back("VALUE");
  header.push_back("");
  header.push_back("TYPE");
  header.push_back("SOURCE");
  printer.AddRow(header);

  for (size_t i = 0; i < settings.size(); ++i) {
    const MemorySetting* setting = settings[i];

    std::vector<std::string> row;
    row.push_back(setting->name());
    row.push_back(StringifyValue(setting));
    if (setting->valid()) {
      row.push_back(ToMegabyteString(setting->MemoryConsumption(), 1));
    } else {
      row.push_back("N/A");
    }
    row.push_back(StringifyMemoryType(*setting));
    row.push_back(StringifySourceType(*setting));
    printer.AddRow(row);
  }

  std::string table_string = printer.ToString();
  return table_string;
}

std::string GenerateMemoryTable(bool use_color_ascii,
                                const IntSetting& total_cpu_memory,
                                const IntSetting& total_gpu_memory,
                                int64_t settings_cpu_consumption,
                                int64_t settings_gpu_consumption) {
  TablePrinter printer;
  if (use_color_ascii) {
    printer.set_text_color(TablePrinter::kGreen);
  }
  std::vector<std::string> header;
  header.push_back("MEMORY");
  header.push_back("SOURCE");
  header.push_back("TOTAL");
  header.push_back("SETTINGS CONSUME");
  printer.AddRow(header);

  std::vector<std::string> data_row;
  data_row.push_back(total_cpu_memory.name());
  data_row.push_back(StringifySourceType(total_cpu_memory));
  data_row.push_back(ToMegabyteString(total_cpu_memory.value(), 1));
  data_row.push_back(ToMegabyteString(settings_cpu_consumption, 1));
  printer.AddRow(data_row);
  data_row.clear();

  data_row.push_back(total_gpu_memory.name());
  data_row.push_back(StringifySourceType(total_gpu_memory));
  std::string total_gpu_consumption_str;

  const bool available_gpu_settings_invalid = (total_gpu_memory.value() <= 0);

  if (available_gpu_settings_invalid) {
    total_gpu_consumption_str = "<UNKNOWN>";
  } else {
    total_gpu_consumption_str = ToMegabyteString(total_gpu_memory.value(), 1);
  }

  data_row.push_back(total_gpu_consumption_str);
  data_row.push_back(ToMegabyteString(settings_gpu_consumption, 1));
  printer.AddRow(data_row);
  data_row.clear();
  return printer.ToString();
}

std::string ToMegabyteString(int64_t bytes, int decimal_places) {
  float megabytes = bytes / (1024.0f * 1024.0f);

  std::stringstream ss_fmt;
  // e.g. "%.1f MB"
  ss_fmt << "%." << decimal_places << "f MB";

  char buff[128];
  SbStringFormatF(buff, sizeof(buff), ss_fmt.str().c_str(), megabytes);
  // Use 16
  return std::string(buff);
}

std::string MakeBorder(const std::string& body, const char border_ch) {
  std::vector<std::string> lines;
  base::SplitStringDontTrim(body, '\n', &lines);

  size_t max_span = 0;
  for (size_t i = 0; i < lines.size(); ++i) {
    max_span = std::max(max_span, lines[i].size());
  }

  std::stringstream ss;
  ss << "\n\n";

  FillStream(max_span + 4, border_ch, &ss);
  ss << "\n";
  for (size_t i = 0; i < lines.size(); ++i) {
    const std::string& line = lines[i];

    ss << border_ch << ' ' << line;
    FillStream(max_span - line.size() + 1, ' ', &ss);
    ss << border_ch;
    ss << "\n";
  }
  FillStream(max_span + 4, border_ch, &ss);
  ss << "\n\n";
  return ss.str();
}

std::string StringifySourceType(const MemorySetting& setting) {
  if (setting.memory_type() == MemorySetting::kNotApplicable) {
    return "N/A";
  }

  switch (setting.source_type()) {
    case MemorySetting::kUnset: {
      return "Unset";
    }
    case MemorySetting::kStarboardAPI: {
      return "Starboard API";
    }
    case MemorySetting::kBuildSetting: {
      return "Build";
    }
    case MemorySetting::kCmdLine: {
      return "CmdLine";
    }
    case MemorySetting::kAutoSet: {
      return "AutoSet";
    }
    case MemorySetting::kAutosetConstrained: {
      return "AutoSet (Constrained)";
    }
  }

  SB_NOTIMPLEMENTED() << "Unimplemented string for type: "
                      << setting.source_type();
  return "UNKNOWN";
}

}  // namespace memory_settings
}  // namespace browser
}  // namespace cobalt
