// Copyright 2015 The Chromium OS 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 "buffet/dbus_conversion.h"

#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <brillo/type_name_undecorate.h>

namespace buffet {

namespace {

// Helpers for JsonToAny().
template <typename T>
brillo::Any ValueToAny(const base::Value& json,
                       bool (base::Value::*fnc)(T*) const) {
  T val;
  CHECK((json.*fnc)(&val));
  return val;
}

brillo::Any ValueToAny(const base::Value& json);

template <typename T>
brillo::Any ListToAny(const base::Value& list,
                      bool (base::Value::*fnc)(T*) const) {
  CHECK(list.is_list());
  std::vector<T> result;
  result.reserve(list.GetList().size());
  for (const base::Value& v : list.GetList()) {
    T val;
    CHECK((v.*fnc)(&val));
    result.push_back(val);
  }
  return result;
}

brillo::Any DictListToAny(const base::Value& list) {
  CHECK(list.is_list());
  std::vector<brillo::VariantDictionary> result;
  result.reserve(list.GetList().size());
  for (const base::Value& v : list.GetList()) {
    const base::DictionaryValue* dict = nullptr;
    CHECK(v.GetAsDictionary(&dict));
    result.push_back(DictionaryToDBusVariantDictionary(*dict));
  }
  return result;
}

brillo::Any ListListToAny(const base::Value& list) {
  CHECK(list.is_list());
  std::vector<brillo::Any> result;
  result.reserve(list.GetList().size());
  for (const base::Value& v : list.GetList())
    result.push_back(ValueToAny(v));
  return result;
}

// Converts a JSON value into an Any so it can be sent over D-Bus using
// UpdateState D-Bus method from Buffet.
brillo::Any ValueToAny(const base::Value& json) {
  brillo::Any prop_value;
  switch (json.type()) {
    case base::Value::Type::BOOLEAN:
      prop_value = ValueToAny<bool>(json, &base::Value::GetAsBoolean);
      break;
    case base::Value::Type::INTEGER:
      prop_value = ValueToAny<int>(json, &base::Value::GetAsInteger);
      break;
    case base::Value::Type::DOUBLE:
      prop_value = ValueToAny<double>(json, &base::Value::GetAsDouble);
      break;
    case base::Value::Type::STRING:
      prop_value = ValueToAny<std::string>(json, &base::Value::GetAsString);
      break;
    case base::Value::Type::DICTIONARY: {
      const base::DictionaryValue* dict = nullptr;
      CHECK(json.GetAsDictionary(&dict));
      prop_value = DictionaryToDBusVariantDictionary(*dict);
      break;
    }
    case base::Value::Type::LIST: {
      if (json.GetList().empty()) {
        // We don't know type of objects this list intended for, so we just use
        // vector<brillo::Any>.
        prop_value = ListListToAny(json);
        break;
      }
      auto type = json.GetList()[0].type();
      for (const base::Value& v : json.GetList())
        CHECK_EQ(v.type(), type) << "Unsupported different type elements";

      switch (type) {
        case base::Value::Type::BOOLEAN:
          prop_value = ListToAny<bool>(json, &base::Value::GetAsBoolean);
          break;
        case base::Value::Type::INTEGER:
          prop_value = ListToAny<int>(json, &base::Value::GetAsInteger);
          break;
        case base::Value::Type::DOUBLE:
          prop_value = ListToAny<double>(json, &base::Value::GetAsDouble);
          break;
        case base::Value::Type::STRING:
          prop_value = ListToAny<std::string>(json, &base::Value::GetAsString);
          break;
        case base::Value::Type::DICTIONARY:
          prop_value = DictListToAny(json);
          break;
        case base::Value::Type::LIST:
          // We can't support Any{vector<vector<>>} as the type is only known
          // in runtime when we need to instantiate templates in compile time.
          // We can use Any{vector<Any>} instead.
          prop_value = ListListToAny(json);
          break;
        default:
          LOG(FATAL) << "Unsupported JSON value type for list element: "
                     << json.GetList()[0].type();
      }
      break;
    }
    default:
      LOG(FATAL) << "Unexpected JSON value type: " << json.type();
      break;
  }
  return prop_value;
}

template <typename T>
std::unique_ptr<base::Value> CreateValue(const T& value,
                                         brillo::ErrorPtr* error) {
  return std::make_unique<base::Value>(value);
}

template <>
std::unique_ptr<base::Value> CreateValue<std::string>(const std::string& value,
                                                      brillo::ErrorPtr* error) {
  return std::make_unique<base::Value>(value);
}

template <>
std::unique_ptr<base::Value> CreateValue<brillo::VariantDictionary>(
    const brillo::VariantDictionary& value, brillo::ErrorPtr* error) {
  return DictionaryFromDBusVariantDictionary(value, error);
}

template <typename T>
std::unique_ptr<base::ListValue> CreateListValue(const std::vector<T>& value,
                                                 brillo::ErrorPtr* error) {
  std::unique_ptr<base::ListValue> list{new base::ListValue};

  for (const T& i : value) {
    auto item = CreateValue(i, error);
    if (!item)
      return nullptr;
    list->Append(std::move(item));
  }

  return list;
}

// Returns false only in case of error. True can be returned if type is not
// matched.
template <typename T>
bool TryCreateValue(const brillo::Any& any,
                    std::unique_ptr<base::Value>* value,
                    brillo::ErrorPtr* error) {
  if (any.IsTypeCompatible<T>()) {
    *value = CreateValue(any.Get<T>(), error);
    return *value != nullptr;
  }

  if (any.IsTypeCompatible<std::vector<T>>()) {
    *value = CreateListValue(any.Get<std::vector<T>>(), error);
    return *value != nullptr;
  }

  return true;  // Not an error, we will try different type.
}

template <>
std::unique_ptr<base::Value> CreateValue<brillo::Any>(const brillo::Any& any,
                                                      brillo::ErrorPtr* error) {
  std::unique_ptr<base::Value> result;
  if (!TryCreateValue<bool>(any, &result, error) || result)
    return result;

  if (!TryCreateValue<int>(any, &result, error) || result)
    return result;

  if (!TryCreateValue<double>(any, &result, error) || result)
    return result;

  if (!TryCreateValue<std::string>(any, &result, error) || result)
    return result;

  if (!TryCreateValue<brillo::VariantDictionary>(any, &result, error) ||
      result) {
    return result;
  }

  // This will collapse Any{Any{T}} and vector{Any{T}}.
  if (!TryCreateValue<brillo::Any>(any, &result, error) || result)
    return result;

  brillo::Error::AddToPrintf(error, FROM_HERE, "buffet", "unknown_type",
                             "Type '%s' is not supported.",
                             any.GetUndecoratedTypeName().c_str());

  return nullptr;
}

}  // namespace

// TODO(vitalybuka): Use in buffet_client.
brillo::VariantDictionary DictionaryToDBusVariantDictionary(
    const base::DictionaryValue& object) {
  brillo::VariantDictionary result;

  for (base::DictionaryValue::Iterator it(object); !it.IsAtEnd(); it.Advance())
    result.emplace(it.key(), ValueToAny(it.value()));

  return result;
}

std::unique_ptr<base::DictionaryValue> DictionaryFromDBusVariantDictionary(
    const brillo::VariantDictionary& object, brillo::ErrorPtr* error) {
  std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};

  for (const auto& pair : object) {
    auto value = CreateValue(pair.second, error);
    if (!value)
      return nullptr;
    result->Set(pair.first, std::move(value));
  }

  return result;
}

}  // namespace buffet
