// 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 "garnet/bin/sysmgr/config.h"

#include <string>
#include <utility>

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

namespace sysmgr {
namespace {

using fxl::StringPrintf;

constexpr char kApps[] = "apps";
constexpr char kServices[] = "services";
constexpr char kStartupServices[] = "startup_services";
constexpr char kUpdateDependencies[] = "update_dependencies";

}  // namespace

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

bool Config::ParseFromString(const std::string& data,
                             const std::string& pseudo_file) {
  rapidjson::Document document =
      json_parser_.ParseFromString(data, pseudo_file);
  if (!json_parser_.HasError()) {
    ParseDocument(std::move(document));
  }
  return !json_parser_.HasError();
}

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));
    }
  }

  auto startup_services_it = document.FindMember(kStartupServices);
  if (startup_services_it != document.MemberEnd()) {
    const auto& value = startup_services_it->value;
    const auto* name = startup_services_it->name.GetString();
    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()) {
        startup_services_.push_back(service.GetString());
      }
    } else {
      json_parser_.ReportError(
          StringPrintf("'%s' is not an array of strings.", name));
    }
  }

  auto update_dependencies_it = document.FindMember(kUpdateDependencies);
  if (update_dependencies_it != document.MemberEnd()) {
    const auto& value = update_dependencies_it->value;
    const auto* name = update_dependencies_it->name.GetString();
    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()) {
        update_dependencies_.push_back(service.GetString());
      }
    } else {
      json_parser_.ReportError(
          StringPrintf("'%s' is not an array of strings.", name));
    }
  }
}

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();
      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();
      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
