// Copyright 2019 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/modular/lib/modular_config/modular_config.h"

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

#include <rapidjson/document.h>
#include <rapidjson/error/en.h>

#include "src/lib/files/directory.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/lib/fxl/strings/substitute.h"
#include "src/modular/lib/fidl/clone.h"
#include "src/modular/lib/fidl/json_xdr.h"
#include "src/modular/lib/modular_config/modular_config_constants.h"
#include "src/modular/lib/modular_config/modular_config_xdr.h"

// Flags passed to RapidJSON that control JSON parsing behavior.
// This is used to enable parsing non-standard JSON syntax, like comments.
constexpr unsigned kModularConfigParseFlags = rapidjson::kParseCommentsFlag;

namespace modular {
namespace {

rapidjson::Document GetSectionAsDoc(const rapidjson::Document& doc,
                                    const std::string& section_name) {
  rapidjson::Document section_doc;

  auto config_json = doc.FindMember(section_name);
  if (config_json != doc.MemberEnd()) {
    section_doc.CopyFrom(config_json->value, section_doc.GetAllocator());
  } else {
    // |section_name| was not found; return an empty object
    section_doc.SetObject();
  }

  return section_doc;
}

std::string StripLeadingSlash(std::string str) {
  if (str.find("/") == 0)
    return str.substr(1);
  return str;
}

}  // namespace

fit::result<fuchsia::modular::session::ModularConfig, std::string> ParseConfig(
    std::string_view config_json) {
  rapidjson::Document doc;

  doc.Parse<kModularConfigParseFlags>(config_json.data(), config_json.length());
  if (doc.HasParseError()) {
    auto error = std::stringstream();
    error << "Failed to parse JSON: " << rapidjson::GetParseError_En(doc.GetParseError()) << " ("
          << doc.GetErrorOffset() << ")";
    return fit::error(error.str());
  }

  fuchsia::modular::session::ModularConfig config;
  if (!XdrRead(&doc, &config, XdrModularConfig)) {
    return fit::error("Failed to read JSON as Modular configuration (does not follow schema?)");
  }

  return fit::ok(std::move(config));
}

// Returns the default Modular configuration.
fuchsia::modular::session::ModularConfig DefaultConfig() {
  rapidjson::Document doc;
  doc.SetObject();

  fuchsia::modular::session::ModularConfig config;
  auto ok = XdrRead(&doc, &config, XdrModularConfig);
  FX_DCHECK(ok);

  return config;
}

std::string ConfigToJsonString(const fuchsia::modular::session::ModularConfig& config) {
  std::string json;
  auto config_copy = CloneStruct(config);
  XdrWrite(&json, &config_copy, XdrModularConfig);
  return json;
}

ModularConfigReader::ModularConfigReader(fbl::unique_fd dir_fd) {
  FX_CHECK(dir_fd.get() >= 0);

  // 1. Figure out where the config file is.
  std::string config_path = files::JoinPath(StripLeadingSlash(modular_config::kOverriddenConfigDir),
                                            modular_config::kStartupConfigFilePath);
  if (!files::IsFileAt(dir_fd.get(), config_path)) {
    config_path = files::JoinPath(StripLeadingSlash(modular_config::kDefaultConfigDir),
                                  modular_config::kStartupConfigFilePath);
  }

  // 2. Read the file
  std::string config;
  if (!files::ReadFileToStringAt(dir_fd.get(), config_path, &config)) {
    FX_LOGS(ERROR) << "Failed to read file: " << config_path;
    UseDefaults();
    return;
  }

  // 3. Parse the JSON
  ParseConfig(config, config_path);
}

ModularConfigReader::ModularConfigReader(std::string config) {
  constexpr char kPathForErrorStrings[] = ".";

  ParseConfig(config, kPathForErrorStrings);
}

// static
ModularConfigReader ModularConfigReader::CreateFromNamespace() {
  return ModularConfigReader(fbl::unique_fd(open("/", O_RDONLY)));
}

// static
std::string ModularConfigReader::GetOverriddenConfigPath() {
  return files::JoinPath(StripLeadingSlash(modular_config::kOverriddenConfigDir),
                         modular_config::kStartupConfigFilePath);
}

// static
bool ModularConfigReader::OverriddenConfigExists() {
  return files::IsFile(GetOverriddenConfigPath());
}

void ModularConfigReader::ParseConfig(const std::string& config, const std::string& config_path) {
  rapidjson::Document doc;

  doc.Parse<kModularConfigParseFlags>(config);
  if (doc.HasParseError()) {
    FX_LOGS(ERROR) << "Failed to parse " << config_path << ": "
                   << rapidjson::GetParseError_En(doc.GetParseError()) << " ("
                   << doc.GetErrorOffset() << ")";
    UseDefaults();
    return;
  }

  // Parse the `basemgr` and `sessionmgr` sections out of the config.
  rapidjson::Document basemgr_doc = GetSectionAsDoc(doc, modular_config::kBasemgrConfigName);
  rapidjson::Document sessionmgr_doc = GetSectionAsDoc(doc, modular_config::kSessionmgrConfigName);
  if (!XdrRead(&basemgr_doc, &basemgr_config_, XdrBasemgrConfig)) {
    FX_LOGS(ERROR) << "Unable to parse 'basemgr' from " << config_path;
  }
  if (!XdrRead(&sessionmgr_doc, &sessionmgr_config_, XdrSessionmgrConfig)) {
    FX_LOGS(ERROR) << "Unable to parse 'sessionmgr' from " << config_path;
  }
}

void ModularConfigReader::UseDefaults() {
  rapidjson::Document doc;
  doc.SetObject();
  XdrRead(&doc, &basemgr_config_, XdrBasemgrConfig);
  XdrRead(&doc, &sessionmgr_config_, XdrSessionmgrConfig);
}

fuchsia::modular::session::BasemgrConfig ModularConfigReader::GetBasemgrConfig() const {
  fuchsia::modular::session::BasemgrConfig result;
  basemgr_config_.Clone(&result);
  return result;
}

fuchsia::modular::session::SessionmgrConfig ModularConfigReader::GetSessionmgrConfig() const {
  fuchsia::modular::session::SessionmgrConfig result;
  sessionmgr_config_.Clone(&result);
  return result;
}

// static
std::string ModularConfigReader::GetConfigAsString(
    fuchsia::modular::session::BasemgrConfig* basemgr_config,
    fuchsia::modular::session::SessionmgrConfig* sessionmgr_config) {
  std::string basemgr_json;
  std::string sessionmgr_json;
  XdrWrite(&basemgr_json, basemgr_config, XdrBasemgrConfig);
  XdrWrite(&sessionmgr_json, sessionmgr_config, XdrSessionmgrConfig);

  return fxl::Substitute(R"({
      "$0": $1,
      "$2": $3
    })",
                         modular_config::kBasemgrConfigName, basemgr_json,
                         modular_config::kSessionmgrConfigName, sessionmgr_json);
}

}  // namespace modular
