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

#include <sstream>

#include "garnet/bin/mdns/service/mdns_names.h"
#include "garnet/public/lib/rapidjson_utils/rapidjson_validation.h"
#include "src/lib/fxl/logging.h"

namespace mdns {
namespace {

const char kSchema[] = R"({
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "perform_host_name_probe": {
      "type": "boolean"
    },
    "publications": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "service": {
            "type": "string",
            "maxLength": 22
          },
          "instance": {
            "type": "string",
            "maxLength": 63
          },
          "port": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535
          },
          "text": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 255
            }
          },
          "perform_probe": {
            "type": "boolean"
          }
        },
        "required": ["service","port"]
      }
    }
  }
})";

const char kPerformHostNameProbeKey[] = "perform_host_name_probe";
const char kPublicationsKey[] = "publications";
const char kServiceKey[] = "service";
const char kInstanceKey[] = "instance";
const char kPortKey[] = "port";
const char kTextKey[] = "text";
const char kPerformProbeKey[] = "perform_probe";

}  // namespace

//  static
const char Config::kConfigDir[] = "/config/data";

void Config::ReadConfigFiles(const std::string& host_name,
                             const std::string& config_dir) {
  FXL_DCHECK(MdnsNames::IsValidHostName(host_name));

  auto schema = rapidjson_utils::InitSchema(kSchema);
  parser_.ParseFromDirectory(
      config_dir, [this, &schema, &host_name](rapidjson::Document document) {
        if (!rapidjson_utils::ValidateSchema(document, *schema)) {
          parser_.ReportError("Schema validation failure.");
          return;
        }

        IntegrateDocument(document, host_name);
      });
}

void Config::IntegrateDocument(const rapidjson::Document& document,
                               const std::string& host_name) {
  FXL_DCHECK(document.IsObject());

  if (document.HasMember(kPerformHostNameProbeKey)) {
    FXL_DCHECK(document[kPerformHostNameProbeKey].IsBool());
    SetPerformHostNameProbe(document[kPerformHostNameProbeKey].GetBool());
    if (parser_.HasError()) {
      return;
    }
  }

  if (document.HasMember(kPublicationsKey)) {
    FXL_DCHECK(document[kPublicationsKey].IsArray());
    for (auto& item : document[kPublicationsKey].GetArray()) {
      IntegratePublication(item, host_name);
      if (parser_.HasError()) {
        return;
      }
    }
  }
}

void Config::IntegratePublication(const rapidjson::Value& value,
                                  const std::string& host_name) {
  FXL_DCHECK(value.IsObject());
  FXL_DCHECK(value.HasMember(kServiceKey));
  FXL_DCHECK(value[kServiceKey].IsString());
  FXL_DCHECK(value.HasMember(kPortKey));
  FXL_DCHECK(value[kPortKey].IsUint());
  FXL_DCHECK(value[kPortKey].GetUint() >= 1);
  FXL_DCHECK(value[kPortKey].GetUint() <= 65535);

  auto service = value[kServiceKey].GetString();
  if (!MdnsNames::IsValidServiceName(service)) {
    parser_.ReportError((std::stringstream()
                         << kServiceKey << " value " << service
                         << " is not a valid service name.")
                            .str());
    return;
  }

  std::string instance;
  if (value.HasMember(kInstanceKey)) {
    instance = value[kInstanceKey].GetString();
    if (!MdnsNames::IsValidInstanceName(instance)) {
      parser_.ReportError((std::stringstream()
                           << kInstanceKey << " value " << instance
                           << " is not a valid instance name.")
                              .str());
      return;
    }
  } else {
    instance = host_name;
    if (!MdnsNames::IsValidInstanceName(instance)) {
      parser_.ReportError((std::stringstream()
                           << "Publication of service " << service
                           << " specifies that the host name should be "
                              "used as the instance name, but "
                           << host_name << "is not a valid instance name.")
                              .str());
      return;
    }
  }

  std::vector<std::string> text;
  if (value.HasMember(kTextKey)) {
    FXL_DCHECK(value[kTextKey].IsArray());
    for (auto& item : value[kTextKey].GetArray()) {
      FXL_DCHECK(item.IsString());
      if (!MdnsNames::IsValidTextString(item.GetString())) {
        parser_.ReportError((std::stringstream()
                             << kTextKey << " item value " << item.GetString()
                             << " is not avalid text string.")
                                .str());
        return;
      }

      text.push_back(item.GetString());
    }
  }

  bool perform_probe = true;
  if (value.HasMember(kPerformProbeKey)) {
    FXL_DCHECK(value[kPerformProbeKey].IsBool());
    perform_probe = value[kPerformProbeKey].GetBool();
  }

  publications_.emplace_back(Publication{
      .service_ = service,
      .instance_ = instance,
      .publication_ = Mdns::Publication::Create(
          inet::IpPort::From_uint16_t(value[kPortKey].GetUint()), text),
      .perform_probe_ = perform_probe});
}

void Config::SetPerformHostNameProbe(bool perform_host_name_probe) {
  if (perform_host_name_probe_.has_value() &&
      perform_host_name_probe_.value() != perform_host_name_probe) {
    parser_.ReportError((std::stringstream()
                         << "Conflicting " << kPerformHostNameProbeKey
                         << " value.")
                            .str());
    return;
  }

  perform_host_name_probe_ = perform_host_name_probe;
}

}  // namespace mdns
