// Copyright 2016 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/sys/sysmgr/config.h"

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

#include <string>
#include <utility>
#include <vector>

#include "rapidjson/document.h"
#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace sysmgr {
namespace {
using fxl::StringPrintf;

constexpr char kApps[] = "apps";
constexpr char kServices[] = "services";
constexpr char kStartupServices[] = "startup_services";
constexpr char kOptionalServices[] = "optional_services";
constexpr char kUpdateDependencies[] = "update_dependencies";
constexpr char kCriticalComponents[] = "critical_components";
}  // namespace

bool Config::ParseFromDirectory(const std::string& dir) {
  auto cb = [this](rapidjson::Document document) { ParseDocument(std::move(document)); };
  json_parser_.ParseFromDirectory(dir, cb);
  if (json_parser_.HasError()) {
    FX_LOGS(INFO) << json_parser_.error_str();
  }
  return !json_parser_.HasError();
}

void Config::ReadJsonStringArray(const rapidjson::Document& document, const char* member,
                                 std::vector<std::string>* out) {
  auto it = document.FindMember(member);
  if (it != document.MemberEnd()) {
    const auto& value = it->value;
    if (value.IsArray() &&
        std::all_of(value.GetArray().begin(), value.GetArray().end(),
                    [](const rapidjson::Value& val) { return val.IsString(); })) {
      for (const auto& service : value.GetArray()) {
        out->push_back(service.GetString());
      }
    } else {
      json_parser_.ReportError(StringPrintf("'%s' is not an array of strings.", member));
    }
  }
}

bool Config::HasError() const { return json_parser_.HasError(); }

std::string Config::error_str() const { return json_parser_.error_str(); }

void Config::ParseDocument(rapidjson::Document document) {
  if (!document.IsObject()) {
    json_parser_.ReportError("Config file is not a JSON object.");
    return;
  }

  if (!ParseServiceMap(document, kServices, &services_)) {
    return;
  }

  auto apps_it = document.FindMember(kApps);
  if (apps_it != document.MemberEnd()) {
    const auto& value = apps_it->value;
    const auto* name = apps_it->name.GetString();
    if (value.IsArray()) {
      for (const auto& app : value.GetArray()) {
        auto launch_info = GetLaunchInfo(app, name);
        if (launch_info) {
          apps_.push_back(std::move(launch_info));
        }
      }
    } else {
      json_parser_.ReportError(StringPrintf("'%s' is not an array.", name));
    }
  }

  ReadJsonStringArray(document, kStartupServices, &startup_services_);
  ReadJsonStringArray(document, kUpdateDependencies, &update_dependencies_);
  ReadJsonStringArray(document, kOptionalServices, &optional_services_);
  ReadJsonStringArray(document, kCriticalComponents, &critical_components_);
}

bool Config::ParseServiceMap(const rapidjson::Document& document, const std::string& key,
                             Config::ServiceMap* services) {
  auto it = document.FindMember(key);
  if (it != document.MemberEnd()) {
    const auto& value = it->value;
    if (!value.IsObject()) {
      json_parser_.ReportError(StringPrintf("'%s' must be an object.", key.c_str()));
      return false;
    }
    for (const auto& reg : value.GetObject()) {
      if (!reg.name.IsString()) {
        json_parser_.ReportError(StringPrintf("Keys of '%s' must be strings.", key.c_str()));
        continue;
      }
      std::string service_key = reg.name.GetString();
      if (services->find(service_key) != services->end()) {
        json_parser_.ReportError(StringPrintf("Duplicate definition in map for '%s': %s", kServices,
                                              service_key.c_str()));
        continue;
      }
      auto launch_info =
          GetLaunchInfo(reg.value, StringPrintf("%s.%s", key.c_str(), service_key.c_str()));
      if (launch_info) {
        services->emplace(service_key, std::move(launch_info));
      }
    }
  }
  return !json_parser_.HasError();
}

fuchsia::sys::LaunchInfoPtr Config::GetLaunchInfo(const rapidjson::Document::ValueType& value,
                                                  const std::string& name) {
  auto launch_info = fuchsia::sys::LaunchInfo::New();
  if (value.IsString()) {
    launch_info->url = value.GetString();
    return launch_info;
  }

  if (value.IsArray()) {
    const auto& array = value.GetArray();
    // If the element is an array, ensure it is non-empty and all values are
    // strings.
    if (!array.Empty() && std::all_of(array.begin(), array.end(),
                                      [](const rapidjson::Value& val) { return val.IsString(); })) {
      launch_info->url = array[0].GetString();
      launch_info->arguments.emplace();
      for (size_t i = 1; i < array.Size(); ++i) {
        launch_info->arguments->push_back(array[i].GetString());
      }
      return launch_info;
    }
  }

  json_parser_.ReportError(
      StringPrintf("'%s' must be a string or a non-empty array of strings.", name.c_str()));
  return nullptr;
}

}  // namespace sysmgr
