//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "shill/json_store.h"

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cinttypes>
#include <memory>
#include <typeinfo>
#include <utility>
#include <vector>

#include <base/files/important_file_writer.h>
#include <base/files/file_util.h>
#include <base/json/json_string_value_serializer.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/values.h>

#include "shill/crypto_rot47.h"
#include "shill/logging.h"
#include "shill/scoped_umask.h"

using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace shill {

namespace Logging {

static auto kModuleLogScope = ScopeLogger::kStorage;
static string ObjectID(const JsonStore* j) {
  return "(unknown)";
}

}  // namespace Logging

namespace {

static const char kCorruptSuffix[] = ".corrupted";
static const char kCoercedValuePropertyEncodedValue[] = "_encoded_value";
static const char kCoercedValuePropertyNativeType[] = "_native_type";
static const char kNativeTypeNonAsciiString[] = "non_ascii_string";
static const char kNativeTypeUint64[] = "uint64";
static const char kRootPropertyDescription[] = "description";
static const char kRootPropertySettings[] = "settings";

bool DoesGroupContainProperties(
    const brillo::VariantDictionary& group,
    const brillo::VariantDictionary& required_properties) {
  for (const auto& required_property_name_and_value : required_properties) {
    const auto& required_key = required_property_name_and_value.first;
    const auto& required_value = required_property_name_and_value.second;
    const auto& group_it = group.find(required_key);
    if (group_it == group.end() || group_it->second != required_value) {
      return false;
    }
  }
  return true;
}

// Deserialization helpers.

// A coerced value is used to represent values that base::Value does
// not directly support.  A coerced value has the form
//   {'_native_type': <type-as-string>, '_encoded_value': <value-as-string>}
bool IsCoercedValue(const base::DictionaryValue& value) {
  return value.HasKey(kCoercedValuePropertyNativeType) &&
      value.HasKey(kCoercedValuePropertyEncodedValue);
}

unique_ptr<brillo::Any> DecodeCoercedValue(
    const base::DictionaryValue& coerced_value) {
  string native_type;
  if (!coerced_value.GetStringWithoutPathExpansion(
          kCoercedValuePropertyNativeType, &native_type)) {
    LOG(ERROR) << "Property |" << kCoercedValuePropertyNativeType
               << "| is not a string.";
    return nullptr;
  }

  string encoded_value;
  if (!coerced_value.GetStringWithoutPathExpansion(
          kCoercedValuePropertyEncodedValue, &encoded_value)) {
    LOG(ERROR) << "Property |" << kCoercedValuePropertyEncodedValue
               << "| is not a string.";
    return nullptr;
  }

  if (native_type == kNativeTypeNonAsciiString) {
    vector<uint8_t> native_value;
    if (base::HexStringToBytes(encoded_value, &native_value)) {
      return base::MakeUnique<brillo::Any>(
          string(native_value.begin(), native_value.end()));
    } else {
      LOG(ERROR) << "Failed to decode hex data from |" << encoded_value << "|.";
      return nullptr;
    }
  } else if (native_type == kNativeTypeUint64) {
    uint64_t native_value;
    if (base::StringToUint64(encoded_value, &native_value)) {
      return base::MakeUnique<brillo::Any>(native_value);
    } else {
      LOG(ERROR) << "Failed to parse uint64 from |" << encoded_value << "|.";
      return nullptr;
    }
  } else {
    LOG(ERROR) << "Unsupported native type |" << native_type << "|.";
    return nullptr;
  }
}

unique_ptr<string> MakeStringFromValue(const base::Value& value) {
  const auto value_type = value.GetType();

  if (value_type == base::Value::TYPE_STRING) {
    auto unwrapped_string = base::MakeUnique<string>();
    value.GetAsString(unwrapped_string.get());
    return unwrapped_string;
  } else if (value_type == base::Value::TYPE_DICTIONARY) {
    const base::DictionaryValue* dictionary_value;
    value.GetAsDictionary(&dictionary_value);
    unique_ptr<brillo::Any> decoded_value(
        DecodeCoercedValue(*dictionary_value));
    if (!decoded_value) {
      LOG(ERROR) << "Failed to decode coerced value.";
      return nullptr;
    }

    if (!decoded_value->IsTypeCompatible<string>()) {
      LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<string>()
                 << "| from |" << decoded_value->GetUndecoratedTypeName()
                 << ".";
      return nullptr;
    }
    return base::MakeUnique<string>(decoded_value->Get<string>());
  } else {
    LOG(ERROR) << "Got unexpected type |" << value_type << "|.";
    return nullptr;
  }
}

unique_ptr<vector<string>> ConvertListValueToStringVector(
    const base::ListValue& list_value) {
  const size_t list_len = list_value.GetSize();
  for (size_t i = 0; i < list_len; ++i) {
    const base::Value* list_item;
    list_value.Get(i, &list_item);
    const auto item_type = list_item->GetType();
    if (item_type != base::Value::TYPE_STRING &&
        item_type != base::Value::TYPE_DICTIONARY) {
      LOG(ERROR) << "Element " << i << " has type " << item_type << ", "
                 << "instead of expected types "
                 << base::Value::TYPE_STRING << "  or "
                 << base::Value::TYPE_DICTIONARY << ".";
      return nullptr;
    }
  }

  auto result = base::MakeUnique<vector<string>>();
  for (size_t i = 0; i < list_len; ++i) {
    const base::Value* list_item;
    list_value.Get(i, &list_item);
    unique_ptr<string> native_string = MakeStringFromValue(*list_item);
    if (!native_string) {
      LOG(ERROR) << "Failed to parse string from element " << i << ".";
      return nullptr;
    }
    result->push_back(*native_string);
  }
  return result;
}

unique_ptr<brillo::VariantDictionary>
ConvertDictionaryValueToVariantDictionary(
    const base::DictionaryValue& dictionary_value) {
  base::DictionaryValue::Iterator it(dictionary_value);
  auto variant_dictionary = base::MakeUnique<brillo::VariantDictionary>();
  while (!it.IsAtEnd()) {
    const string& key = it.key();
    const base::Value& value = it.value();
    switch (value.GetType()) {
      case base::Value::TYPE_NULL:
        LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_NULL.";
        return nullptr;
      case base::Value::TYPE_BOOLEAN: {
        bool native_bool;
        value.GetAsBoolean(&native_bool);
        (*variant_dictionary)[key] = native_bool;
        break;
      }
      case base::Value::TYPE_INTEGER: {
        int native_int;
        value.GetAsInteger(&native_int);
        (*variant_dictionary)[key] = native_int;
        break;
      }
      case base::Value::TYPE_DOUBLE:
        LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_DOUBLE.";
        return nullptr;
      case base::Value::TYPE_STRING: {
        string native_string;
        value.GetAsString(&native_string);
        (*variant_dictionary)[key] = native_string;
        break;
      }
      case base::Value::TYPE_BINARY:
        /* The JSON parser should never create Values of this type. */
        LOG(ERROR) << "Key |" << key << "| has unexpected TYPE_BINARY.";
        return nullptr;
      case base::Value::TYPE_DICTIONARY: {
        const base::DictionaryValue* dictionary_value;
        value.GetAsDictionary(&dictionary_value);
        if (!IsCoercedValue(*dictionary_value)) {
          LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_DICTIONARY.";
          return nullptr;
        }
        unique_ptr<brillo::Any> decoded_coerced_value(
            DecodeCoercedValue(*dictionary_value));
        if (!decoded_coerced_value) {
          LOG(ERROR) << "Key |" << key << "| could not be decoded.";
          return nullptr;
        }
        (*variant_dictionary)[key] = *decoded_coerced_value;
        break;
      }
      case base::Value::TYPE_LIST: {  // Only string lists, for now.
        const base::ListValue* list_value;
        value.GetAsList(&list_value);

        unique_ptr<vector<string>> string_list(
            ConvertListValueToStringVector(*list_value));
        if (!string_list) {
          LOG(ERROR) << "Key |" << key << "| could not be decoded.";
          return nullptr;
        }
        (*variant_dictionary)[key] = *string_list;
        break;
      }
    }
    it.Advance();
  }
  return variant_dictionary;
}

// Serialization helpers.

unique_ptr<base::DictionaryValue> MakeCoercedValue(
    const string& native_type, const string& encoded_value) {
  auto coerced_value = base::MakeUnique<base::DictionaryValue>();
  coerced_value->SetStringWithoutPathExpansion(
      kCoercedValuePropertyNativeType, native_type);
  coerced_value->SetStringWithoutPathExpansion(
      kCoercedValuePropertyEncodedValue, encoded_value);
  return coerced_value;
}

unique_ptr<base::Value> MakeValueForString(const string& native_string) {
  // Strictly speaking, we don't need to escape non-ASCII text, if
  // that text is UTF-8.  Practically speaking, however, it'll be
  // easier to inspect config files if all non-ASCII strings are
  // presented as byte sequences. (Unicode has many code points with
  // similar-looking glyphs.)
  if (base::IsStringASCII(native_string) &&
      native_string.find('\0') == string::npos) {
    return base::MakeUnique<base::StringValue>(native_string);
  } else {
    const string hex_encoded_string(
        base::HexEncode(native_string.data(), native_string.size()));
    return MakeCoercedValue(kNativeTypeNonAsciiString, hex_encoded_string);
  }
}

unique_ptr<base::DictionaryValue> ConvertVariantDictionaryToDictionaryValue(
    const brillo::VariantDictionary& variant_dictionary) {
  auto dictionary_value = base::MakeUnique<base::DictionaryValue>();
  for (const auto& key_and_value : variant_dictionary) {
    const auto& key = key_and_value.first;
    const auto& value = key_and_value.second;
    if (value.IsTypeCompatible<bool>()) {
      dictionary_value->SetBooleanWithoutPathExpansion(key, value.Get<bool>());
    } else if (value.IsTypeCompatible<int32_t>()) {
      dictionary_value->SetIntegerWithoutPathExpansion(key, value.Get<int>());
    } else if (value.IsTypeCompatible<string>()) {
      dictionary_value->SetWithoutPathExpansion(
          key, MakeValueForString(value.Get<string>()));
    } else if (value.IsTypeCompatible<uint64_t>()) {
      const string encoded_value(
          base::StringPrintf("%" PRIu64, value.Get<uint64_t>()));
      dictionary_value->SetWithoutPathExpansion(
          key, MakeCoercedValue(kNativeTypeUint64, encoded_value));
    } else if (value.IsTypeCompatible<vector<string>>()) {
      auto list_value = base::MakeUnique<base::ListValue>();
      for (const auto& string_list_item : value.Get<vector<string>>()) {
        list_value->Append(MakeValueForString(string_list_item));
      }
      dictionary_value->SetWithoutPathExpansion(key, std::move(list_value));
    } else {
      LOG(ERROR) << "Failed to convert element with key |" << key << "|.";
      return nullptr;
    }
  }
  return dictionary_value;
}

}  // namespace

JsonStore::JsonStore(const base::FilePath& path)
    : path_(path) {
  CHECK(!path_.empty());
}

bool JsonStore::IsNonEmpty() const {
  int64_t file_size = 0;
  return base::GetFileSize(path_, &file_size) && file_size != 0;
}

bool JsonStore::Open() {
  if (!IsNonEmpty()) {
    LOG(INFO) << "Creating a new key file at |" << path_.value() << "|.";
    return true;
  }

  string json_string;
  if (!base::ReadFileToString(path_, &json_string)) {
    LOG(ERROR) << "Failed to read data from |" << path_.value() << "|.";
    return false;
  }

  JSONStringValueDeserializer json_deserializer(json_string);
  json_deserializer.set_allow_trailing_comma(true);
  string json_error;
  unique_ptr<base::Value> json_value =
      json_deserializer.Deserialize(nullptr, &json_error);
  if (!json_value) {
    LOG(ERROR) << "Failed to parse JSON data from |" << path_.value() <<"|.";
    SLOG(this, 5) << json_error;
    return false;
  }

  const base::DictionaryValue* root_dictionary;
  if (!json_value->GetAsDictionary(&root_dictionary)) {
    LOG(ERROR) << "JSON value is not a dictionary.";
    return false;
  }

  CHECK(root_dictionary);
  if (root_dictionary->HasKey(kRootPropertyDescription) &&
      !root_dictionary->GetStringWithoutPathExpansion(
          kRootPropertyDescription, &file_description_)) {
    LOG(WARNING) << "Property |" << kRootPropertyDescription
                 << "| is not a string.";
    // Description is non-critical, so continue processing.
  }

  if (!root_dictionary->HasKey(kRootPropertySettings)) {
    LOG(ERROR) << "Property |" << kRootPropertySettings << "| is missing.";
    return false;
  }

  const base::DictionaryValue* settings_dictionary;
  if (!root_dictionary->GetDictionaryWithoutPathExpansion(
          kRootPropertySettings, &settings_dictionary)) {
    LOG(ERROR) << "Property |" << kRootPropertySettings
               << "| is not a dictionary.";
    return false;
  }

  if (!group_name_to_settings_.empty()) {
    LOG(INFO) << "Clearing existing settings on open.";
    group_name_to_settings_.clear();
  }

  base::DictionaryValue::Iterator it(*settings_dictionary);
  while (!it.IsAtEnd()) {
    const string& group_name = it.key();
    const base::DictionaryValue* group_settings_as_values;
    if (!it.value().GetAsDictionary(&group_settings_as_values)) {
      LOG(ERROR) << "Group |" << group_name << "| is not a dictionary.";
      return false;
    }

    unique_ptr<brillo::VariantDictionary> group_settings_as_variants =
        ConvertDictionaryValueToVariantDictionary(*group_settings_as_values);
    if (!group_settings_as_variants) {
      LOG(ERROR) << "Failed to convert group |" << group_name
                 << "| to variants.";
      return false;
    }

    group_name_to_settings_[group_name] = *group_settings_as_variants;
    it.Advance();
  }

  return true;
}

bool JsonStore::Close() {
  return Flush();
}

bool JsonStore::Flush() {
  auto groups = base::MakeUnique<base::DictionaryValue>();
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    unique_ptr<base::DictionaryValue> group_settings(
        ConvertVariantDictionaryToDictionaryValue(
            group_name_and_settings.second));
    if (!group_settings) {
      // This class maintains the invariant that anything placed in
      // |group_settings| is convertible. So abort if conversion fails.
      LOG(FATAL) << "Failed to convert group |" << group_name << "|.";
      return false;
    }
    groups->SetWithoutPathExpansion(group_name, std::move(group_settings));
  }

  base::DictionaryValue root;
  root.SetStringWithoutPathExpansion(
      kRootPropertyDescription, file_description_);
  root.SetWithoutPathExpansion(kRootPropertySettings, std::move(groups));

  string json_string;
  JSONStringValueSerializer json_serializer(&json_string);
  json_serializer.set_pretty_print(true);
  if (!json_serializer.Serialize(root)) {
    LOG(ERROR) << "Failed to serialize to JSON.";
    return false;
  }

  ScopedUmask owner_only_umask(~(S_IRUSR | S_IWUSR) & 0777);
  if (!base::ImportantFileWriter::WriteFileAtomically(path_, json_string)) {
    LOG(ERROR) << "Failed to write JSON file: |" << path_.value() << "|.";
    return false;
  }

  return true;
}

bool JsonStore::MarkAsCorrupted() {
  LOG(INFO) << "In " << __func__ << " for " << path_.value();
  string corrupted_path = path_.value() + kCorruptSuffix;
  int ret = rename(path_.value().c_str(), corrupted_path.c_str());
  if (ret != 0) {
    PLOG(ERROR) << "File rename failed.";
    return false;
  }
  return true;
}

set<string> JsonStore::GetGroups() const {
  set<string> matching_groups;
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    matching_groups.insert(group_name_and_settings.first);
  }
  return matching_groups;
}

// Returns a set so that caller can easily test whether a particular group
// is contained within this collection.
set<string> JsonStore::GetGroupsWithKey(const string& key) const {
  set<string> matching_groups;
  // iterate over groups, find ones with matching key
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    const auto& group_settings = group_name_and_settings.second;
    if (group_settings.find(key) != group_settings.end()) {
      matching_groups.insert(group_name);
    }
  }
  return matching_groups;
}

set<string> JsonStore::GetGroupsWithProperties(const KeyValueStore& properties)
    const {
  set<string> matching_groups;
  const brillo::VariantDictionary& properties_dict(properties.properties());
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    const auto& group_settings = group_name_and_settings.second;
    if (DoesGroupContainProperties(group_settings, properties_dict)) {
      matching_groups.insert(group_name);
    }
  }
  return matching_groups;
}

bool JsonStore::ContainsGroup(const string& group) const {
  const auto& it = group_name_to_settings_.find(group);
  return it != group_name_to_settings_.end();
}

bool JsonStore::DeleteKey(const string& group, const string& key) {
  const auto& group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    LOG(ERROR) << "Could not find group |" << group << "|.";
    return false;
  }

  auto& group_settings = group_name_and_settings->second;
  auto property_it = group_settings.find(key);
  if (property_it != group_settings.end()) {
    group_settings.erase(property_it);
  }

  return true;
}

bool JsonStore::DeleteGroup(const string& group) {
  auto group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings != group_name_to_settings_.end()) {
    group_name_to_settings_.erase(group_name_and_settings);
  }
  return true;
}

bool JsonStore::SetHeader(const string& header) {
  file_description_ = header;
  return true;
}

bool JsonStore::GetString(const string& group,
                          const string& key,
                          string* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetString(
    const string& group, const string& key, const string& value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetBool(const string& group, const string& key, bool* value)
    const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetBool(const string& group, const string& key, bool value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetInt(
    const string& group, const string& key, int* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetInt(const string& group, const string& key, int value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetUint64(
    const string& group, const string& key, uint64_t* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetUint64(
    const string& group, const string& key, uint64_t value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetStringList(
    const string& group, const string& key, vector<string>* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetStringList(
    const string& group, const string& key, const vector<string>& value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetCryptedString(
    const string& group, const string& key, string* value) {
  string encrypted_value;
  if (!GetString(group, key, &encrypted_value)) {
    return false;
  }

  // TODO(quiche): Once we've removed the glib dependency in
  // CryptoProvider, move to using CryptoProvider, instead of
  // CryptoROT47 directly. This change should be done before using
  // JsonStore in production, as the on-disk format of crypted strings
  // will change.
  CryptoROT47 rot47;
  string decrypted_value;
  if (!rot47.Decrypt(encrypted_value, &decrypted_value)) {
    LOG(ERROR) << "Failed to decrypt value for |" << group << "|"
               << ":|" << key << "|.";
    return false;
  }

  if (value) {
    *value = decrypted_value;
  }
  return true;
}

bool JsonStore::SetCryptedString(
    const string& group, const string& key, const string& value) {
  CryptoROT47 rot47;
  string encrypted_value;
  if (!rot47.Encrypt(value, &encrypted_value)) {
    LOG(ERROR) << "Failed to encrypt value for |" << group << "|"
               << ":|" << key << "|.";
    return false;
  }

  return SetString(group, key, encrypted_value);
}

// Private methods.
template<typename T>
bool JsonStore::ReadSetting(
    const string& group, const string& key, T* out) const {
  const auto& group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    SLOG(this, 10) << "Could not find group |" << group << "|.";
    return false;
  }

  const auto& group_settings = group_name_and_settings->second;
  const auto& property_name_and_value = group_settings.find(key);
  if (property_name_and_value == group_settings.end()) {
    SLOG(this, 10) << "Could not find property |" << key << "|.";
    return false;
  }

  if (!property_name_and_value->second.IsTypeCompatible<T>()) {
    // We assume that the reader and the writer agree on the exact
    // type. So we do not allow implicit conversion.
    LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<T>()
               << "| from |"
               << property_name_and_value->second.GetUndecoratedTypeName()
               << "|.";
    return false;
  }

  if (out) {
    return property_name_and_value->second.GetValue(out);
  } else {
    return true;
  }
}

template<typename T>
bool JsonStore::WriteSetting(
    const string& group, const string& key, const T& new_value) {
  auto group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    group_name_to_settings_[group][key] = new_value;
    return true;
  }

  auto& group_settings = group_name_and_settings->second;
  auto property_name_and_value = group_settings.find(key);
  if (property_name_and_value == group_settings.end()) {
    group_settings[key] = new_value;
    return true;
  }

  if (!property_name_and_value->second.IsTypeCompatible<T>()) {
    SLOG(this, 10) << "New type |" << brillo::GetUndecoratedTypeName<T>()
                   << "| differs from current type |"
                   << property_name_and_value->second.GetUndecoratedTypeName()
                   << "|.";
    return false;
  } else {
    property_name_and_value->second = new_value;
    return true;
  }
}

}  // namespace shill
