// 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/performance/cpuperf/session_result_spec.h"

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

#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/schema.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/json_parser/rapidjson_validation.h"

namespace cpuperf {

namespace {

// Top-level schema.
const char kRootSchema[] = R"({
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "config_name": {
      "type": "string"
    },
    "model_name": {
      "type": "string"
    },
    "num_iterations": {
      "type": "integer",
      "minimum": 1
    },
    "num_traces": {
      "type": "integer",
      "minimum": 1
    },
    "output_path_prefix": {
      "type": "string"
    }
  }
})";

const char kConfigNameKey[] = "config_name";
const char kModelNameKey[] = "model_name";
const char kNumIterationsKey[] = "num_iterations";
const char kNumTracesKey[] = "num_traces";
const char kOutputPathPrefixKey[] = "output_path_prefix";

}  // namespace

SessionResultSpec::SessionResultSpec(const std::string& config_name, const std::string& model_name,
                                     size_t num_iterations, size_t num_traces,
                                     const std::string& output_path_prefix)
    : config_name(config_name),
      model_name(model_name),
      num_iterations(num_iterations),
      num_traces(num_traces),
      output_path_prefix(output_path_prefix) {}

// Given an iteration number and trace number, return the output file.
std::string SessionResultSpec::GetTraceFilePath(size_t iter_num, size_t trace_num) const {
  return fxl::StringPrintf("%s.%zu.%zu.cpuperf", output_path_prefix.c_str(), iter_num, trace_num);
}

bool DecodeSessionResultSpec(const std::string& json, SessionResultSpec* out_spec) {
  // Initialize schemas for JSON validation.
  auto root_schema_result = json_parser::InitSchema(kRootSchema);
  if (root_schema_result.is_error()) {
    FX_LOGS(ERROR) << "Invalid schema: " << root_schema_result.error_value().ToString();
    return false;
  }

  SessionResultSpec result;
  rapidjson::Document document;
  document.Parse<rapidjson::kParseCommentsFlag>(json.c_str(), json.size());
  if (document.HasParseError()) {
    auto offset = document.GetErrorOffset();
    auto code = document.GetParseError();
    FX_LOGS(ERROR) << "Couldn't parse the session result spec file: offset " << offset << ", "
                   << GetParseError_En(code);
    return false;
  }
  auto root_schema = std::move(root_schema_result.value());
  auto validation_result =
      json_parser::ValidateSchema(document, root_schema, "session result spec");
  if (validation_result.is_error()) {
    FX_LOGS(ERROR) << "json validation failed: " << validation_result.error_value();
    return false;
  }

  if (document.HasMember(kConfigNameKey)) {
    result.config_name = document[kConfigNameKey].GetString();
  }

  if (document.HasMember(kModelNameKey)) {
    result.model_name = document[kModelNameKey].GetString();
  }

  if (document.HasMember(kNumIterationsKey)) {
    result.num_iterations = document[kNumIterationsKey].GetUint();
  }

  if (document.HasMember(kNumTracesKey)) {
    result.num_traces = document[kNumTracesKey].GetUint();
  }

  if (document.HasMember(kOutputPathPrefixKey)) {
    result.output_path_prefix = document[kOutputPathPrefixKey].GetString();
  }

  *out_spec = std::move(result);
  return true;
}

bool WriteSessionResultSpec(const std::string& output_file_path, const SessionResultSpec& spec) {
  rapidjson::StringBuffer string_buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(string_buffer);

  writer.StartObject();

  if (!spec.config_name.empty()) {
    writer.Key(kConfigNameKey);
    writer.String(spec.config_name.c_str());
  }

  if (!spec.model_name.empty()) {
    writer.Key(kModelNameKey);
    writer.String(spec.model_name.c_str());
  }

  writer.Key(kNumIterationsKey);
  writer.Uint(spec.num_iterations);

  writer.Key(kNumTracesKey);
  writer.Uint(spec.num_traces);

  writer.Key(kOutputPathPrefixKey);
  writer.String(spec.output_path_prefix.c_str());

  writer.EndObject();

  std::string encoded = string_buffer.GetString();
  if (!files::WriteFile(output_file_path, encoded.data(), encoded.size())) {
    FX_LOGS(ERROR) << "Error writing to: " << output_file_path;
    return false;
  }
  return true;
}

}  // namespace cpuperf
