// Copyright 2020 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 "weave_config_manager.h"

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

#include <vector>

#include <Weave/Support/NLDLLUtil.h>

#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "src/lib/files/file.h"
#include "src/lib/json_parser/json_parser.h"
#include "third_party/modp_b64/modp_b64.h"
#include "weave_device_platform_error.h"

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

NL_DLL_EXPORT
const char kEnvironmentStorePath[] = "/data/environment.json";

WeaveConfigManager& WeaveConfigManager::GetInstance() {
  static WeaveConfigManager manager;
  return manager;
}

WeaveConfigManager::WeaveConfigManager() : WeaveConfigManager(kEnvironmentStorePath) {}

WeaveConfigManager::WeaveConfigManager(const std::string& path) : config_store_path_(path) {
  json::JSONParser json_parser_;
  if (files::IsFile(config_store_path_)) {
    config_ = json_parser_.ParseFromFile(config_store_path_);
  } else {
    config_.SetObject();
  }
  FX_CHECK(!json_parser_.HasError())
      << "Failed to load configuration: " << json_parser_.error_str();
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValue(const std::string& key, bool* value) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsBool()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }
  *value = config_value.GetBool();
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValue(const std::string& key, uint16_t* value) const {
  uint32_t int_value;
  WEAVE_ERROR error = ReadConfigValue(key, &int_value);
  if (error != WEAVE_NO_ERROR) {
    return error;
  } else if (int_value > UINT16_MAX) {
    return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
  }
  *value = (uint16_t)int_value;
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValue(const std::string& key, uint32_t* value) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsUint()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }
  *value = config_value.GetUint();
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValue(const std::string& key, uint64_t* value) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsUint64()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }
  *value = config_value.GetUint64();
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValueStr(const std::string& key, char* value,
                                                   size_t value_size, size_t* out_size) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsString()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }
  const std::string string_value(config_value.GetString());
  *out_size = string_value.size() + 1;
  if (value == nullptr) {
    return WEAVE_NO_ERROR;
  } else if (value_size < *out_size) {
    return WEAVE_ERROR_BUFFER_TOO_SMALL;
  }
  strncpy(value, string_value.c_str(), *out_size);
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValueBin(const std::string& key, uint8_t* value,
                                                   size_t value_size, size_t* out_size) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsString()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }
  std::string string_value(config_value.GetString());
  const std::string decoded_value(modp_b64_decode(string_value));
  *out_size = decoded_value.size();
  if (value == nullptr) {
    return WEAVE_NO_ERROR;
  } else if (value_size < *out_size) {
    return WEAVE_ERROR_BUFFER_TOO_SMALL;
  }
  memcpy(value, decoded_value.c_str(), decoded_value.size());
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::ReadConfigValueArray(const std::string& key,
                                                     std::vector<std::string>& out) const {
  rapidjson::Value config_value;
  WEAVE_ERROR error = WEAVE_NO_ERROR;
  if ((error = ReadKVPair(key, config_value)) != WEAVE_NO_ERROR) {
    return error;
  } else if (!config_value.IsArray()) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
  }

  for (rapidjson::SizeType i = 0; i < config_value.Size(); i++) {
    if (!config_value[i].IsString()) {
      return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_TYPE_MISMATCH;
    }
    out.push_back(config_value[i].GetString());
  }
  return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValue(const std::string& key, bool value) {
  return WriteKVPair(key, rapidjson::Value(value).Move());
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValue(const std::string& key, uint32_t value) {
  return WriteKVPair(key, rapidjson::Value(value).Move());
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValue(const std::string& key, uint64_t value) {
  return WriteKVPair(key, rapidjson::Value(value).Move());
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValueStr(const std::string& key, const char* value,
                                                    size_t value_size) {
  rapidjson::Value string_value;
  {
    const std::lock_guard<std::mutex> write_lock(config_mutex_);
    string_value.SetString(value, value_size, config_.GetAllocator());
  }
  return WriteKVPair(key, string_value.Move());
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValueBin(const std::string& key, const uint8_t* value,
                                                    size_t value_size) {
  std::string binary_string((const char*)value, value_size);
  std::string encoded_string(modp_b64_encode(binary_string));
  return WriteConfigValueStr(key, encoded_string.c_str(), encoded_string.size());
}

WEAVE_ERROR WeaveConfigManager::WriteConfigValueArray(const std::string& key,
                                                      std::vector<std::string>& value) {
  rapidjson::Value array_value(rapidjson::kArrayType);
  {
    const std::lock_guard<std::mutex> write_lock(config_mutex_);
    for (size_t i = 0; i < value.size(); i++) {
      rapidjson::Value string_value;
      string_value.SetString(value[i].c_str(), value[i].size(), config_.GetAllocator());
      array_value.PushBack(string_value, config_.GetAllocator());
    }
  }
  return WriteKVPair(key, array_value.Move());
}

WEAVE_ERROR WeaveConfigManager::ClearConfigValue(const std::string& key) {
  const std::lock_guard<std::mutex> write_lock(config_mutex_);
  config_.RemoveMember(key);
  return CommitKVPairs();
}

bool WeaveConfigManager::ConfigValueExists(const std::string& key) const {
  rapidjson::Value value;
  return ReadKVPair(key, value) == WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::FactoryResetConfig() {
  const std::lock_guard<std::mutex> write_lock(config_mutex_);
  config_.RemoveAllMembers();
  return CommitKVPairs();
}

WEAVE_ERROR WeaveConfigManager::ReadKVPair(const std::string& key, rapidjson::Value& value) const {
  const std::lock_guard<std::mutex> read_lock(config_mutex_);
  if (!config_.HasMember(key)) {
    return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND;
  }
  value.CopyFrom(config_[key], config_.GetAllocator());
  return value.IsNull() ? WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND : WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveConfigManager::WriteKVPair(const std::string& key, rapidjson::Value& value) {
  const std::lock_guard<std::mutex> write_lock(config_mutex_);
  rapidjson::Value key_value;
  key_value.SetString(key.c_str(), key.size(), config_.GetAllocator());
  rapidjson::Value::MemberIterator it = config_.FindMember(key_value);
  if (it != config_.MemberEnd()) {
    it->value = value;
  } else {
    config_.AddMember(key_value, value, config_.GetAllocator());
  }
  return CommitKVPairs();
}

WEAVE_ERROR WeaveConfigManager::CommitKVPairs() {
  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  config_.Accept(writer);

  const std::string output(buffer.GetString());
  return files::WriteFile(config_store_path_.c_str(), output.c_str(), output.size())
             ? WEAVE_NO_ERROR
             : WEAVE_ERROR_PERSISTED_STORAGE_FAIL;
}

WEAVE_ERROR WeaveConfigManager::SetConfiguration(const std::string& path,
                                                 const std::string& schema_path,
                                                 bool should_replace) {
  json::JSONParser json_parser;
  rapidjson::Document default_config;
  rapidjson::Document schema_config;

  if (!files::IsFile(path)) {
    FX_LOGS(ERROR) << "Default configuration file not found at " << path;
    return WEAVE_ERROR_PERSISTED_STORAGE_FAIL;
  }

  if (!files::IsFile(schema_path)) {
    FX_LOGS(ERROR) << "Schema configuration file not found at " << schema_path;
    return WEAVE_ERROR_PERSISTED_STORAGE_FAIL;
  }

  default_config = json_parser.ParseFromFile(path);
  if (json_parser.HasError()) {
    FX_LOGS(ERROR) << "Failed to parse default configuration file: " << json_parser.error_str();
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_INVALID;
  }

  schema_config = json_parser.ParseFromFile(schema_path);
  if (json_parser.HasError()) {
    FX_LOGS(ERROR) << "Failed to parse schema configuration file: " << json_parser.error_str();
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_INVALID;
  }

  rapidjson::SchemaDocument schema(schema_config);
  rapidjson::SchemaValidator validator(schema);
  if (!default_config.Accept(validator)) {
    return WEAVE_DEVICE_PLATFORM_ERROR_CONFIG_INVALID;
  }

  for (rapidjson::Value::MemberIterator it = default_config.MemberBegin();
       it != default_config.MemberEnd(); ++it) {
    rapidjson::Value::MemberIterator config_it = config_.FindMember(it->name);
    if (config_it == config_.MemberEnd()) {
      config_.AddMember(it->name, it->value, config_.GetAllocator());
    } else if (should_replace) {
      config_.RemoveMember(config_it->name);
      config_.AddMember(it->name, it->value, config_.GetAllocator());
    }
  }
  return CommitKVPairs();
}

}  // namespace Internal
}  // namespace DeviceLayer
}  // namespace Weave
}  // namespace nl
