// Copyright 2017 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/network_time/time_server_config.h"

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

#include <fstream>
#include <sstream>
#include <string>
#include <vector>

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

#define MULTILINE(...) #__VA_ARGS__

namespace time_server {

const char* config_schema = MULTILINE({
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "properties" : {
    "servers" : {
      "items" : {
        "properties" : {
          "addresses" : {
            "items" : {
              "properties" : {"address" : {"type" : "string"}},
              "required" : ["address"],
              "type" : "object"
            },
            "minItems" : 1,
            "type" : "array"
          },
          "name" : {"type" : "string"},
          "publicKey" : {"maxLength" : 64, "minLength" : 64, "type" : "string"}
        },
        "required" : [ "publicKey", "addresses", "name" ],
        "type" : "object"
      },
      "minItems" : 1,
      "type" : "array"
    }
  },
  "required" : ["servers"],
  "type" : "object"
});

static bool readFile(std::string* out_contents, const char* filename) {
  std::ifstream serverFile;
  serverFile.open(filename);
  if ((serverFile.rdstate() & std::ifstream::failbit) != 0) {
    FX_LOGS(ERROR) << "Opening " << filename << ": " << strerror(errno);
    return false;
  }
  std::stringstream strStream;
  strStream << serverFile.rdbuf();
  out_contents->assign(strStream.str());
  return true;
}

std::vector<RoughTimeServer> TimeServerConfig::ServerList() { return server_list_; }

bool checkSchema(rapidjson::Document& d) {
  rapidjson::Document sd;
  if (sd.Parse(config_schema).HasParseError()) {
    FX_LOGS(WARNING) << "Schema not valid";
    return false;
  }
  rapidjson::SchemaDocument schema(sd);
  rapidjson::SchemaValidator validator(schema);
  if (!d.Accept(validator)) {
    // Input JSON is invalid according to the schema
    // Output diagnostic information
    rapidjson::StringBuffer sb;
    validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
    FX_LOGS(WARNING) << "Invalid schema: " << sb.GetString();
    FX_LOGS(WARNING) << "Invalid keyword: " << validator.GetInvalidSchemaKeyword();
    sb.Clear();
    validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
    FX_LOGS(WARNING) << "Invalid document: " << sb.GetString();
    return false;
  }
  return true;
}

bool TimeServerConfig::Parse(std::string config_file) {
  std::string json;
  if (!readFile(&json, config_file.c_str())) {
    return false;
  }

  rapidjson::Document doc;
  rapidjson::ParseResult ok = doc.Parse(json.c_str());
  if (!ok) {
    FX_LOGS(WARNING) << "JSON parse error: " << rapidjson::GetParseError_En(ok.Code()) << "("
                     << ok.Offset() << ")";
    return false;
  }
  if (!checkSchema(doc)) {
    return false;
  }

  const rapidjson::Value& servers = doc["servers"];
  for (rapidjson::SizeType i = 0; i < servers.Size(); i++) {
    const rapidjson::Value& server = servers[i];

    const rapidjson::Value& addresses = server["addresses"];
    std::string name = server["name"].GetString();
    std::string public_key_str = server["publicKey"].GetString();
    for (rapidjson::SizeType j = 0; j < addresses.Size(); j++) {
      const rapidjson::Value& address = addresses[j];

      std::string address_str = address["address"].GetString();
      uint8_t public_key[roughtime::kPublicKeyLength];
      if (public_key_str.length() != roughtime::kPublicKeyLength * 2) {
        FX_LOGS(WARNING) << "Invalid public key: " << public_key_str;
        return false;
      }
      for (unsigned int k = 0; k < roughtime::kPublicKeyLength; k++) {
        char hex[3] = {0};
        hex[0] = public_key_str.at(k * 2);
        hex[1] = public_key_str.at(k * 2 + 1);
        public_key[k] = strtoul(hex, NULL, 16);
      }

      RoughTimeServer server(std::move(name), std::move(address_str), public_key,
                             roughtime::kPublicKeyLength);
      server_list_.push_back(server);
    }
  }
  return true;
}

}  // namespace time_server
