// 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 <vector>

#include <chromeos/type_name_undecorate.h>

namespace buffet {

namespace {

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

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

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

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

chromeos::Any ListListToAny(const base::ListValue& list) {
  std::vector<chromeos::Any> result;
  result.reserve(list.GetSize());
  for (const base::Value* v : list)
    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.
chromeos::Any ValueToAny(const base::Value& json) {
  chromeos::Any prop_value;
  switch (json.GetType()) {
    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: {
      const base::ListValue* list = nullptr;
      CHECK(json.GetAsList(&list));
      if (list->empty()) {
        // We don't know type of objects this list intended for, so we just use
        // vector<chromeos::Any>.
        prop_value = ListListToAny(*list);
        break;
      }
      auto type = (*list->begin())->GetType();
      for (const base::Value* v : *list)
        CHECK_EQ(v->GetType(), type) << "Unsupported different type elements";

      switch (type) {
        case base::Value::TYPE_BOOLEAN:
          prop_value = ListToAny<bool>(*list, &base::Value::GetAsBoolean);
          break;
        case base::Value::TYPE_INTEGER:
          prop_value = ListToAny<int>(*list, &base::Value::GetAsInteger);
          break;
        case base::Value::TYPE_DOUBLE:
          prop_value = ListToAny<double>(*list, &base::Value::GetAsDouble);
          break;
        case base::Value::TYPE_STRING:
          prop_value = ListToAny<std::string>(*list, &base::Value::GetAsString);
          break;
        case base::Value::TYPE_DICTIONARY:
          prop_value = DictListToAny(*list);
          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(*list);
          break;
        default:
          LOG(FATAL) << "Unsupported JSON value type for list element: "
                     << (*list->begin())->GetType();
      }
      break;
    }
    default:
      LOG(FATAL) << "Unexpected JSON value type: " << json.GetType();
      break;
  }
  return prop_value;
}

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

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

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

template <typename T>
std::unique_ptr<base::ListValue> CreateListValue(const std::vector<T>& value,
                                                 chromeos::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(item.release());
  }

  return list;
}

// Returns false only in case of error. True can be returned if type is not
// matched.
template <typename T>
bool TryCreateValue(const chromeos::Any& any,
                    std::unique_ptr<base::Value>* value,
                    chromeos::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<chromeos::Any>(
    const chromeos::Any& any,
    chromeos::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<chromeos::VariantDictionary>(any, &result, error) ||
      result) {
    return result;
  }

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

  chromeos::Error::AddToPrintf(
      error, FROM_HERE, "buffet", "unknown_type", "Type '%s' is not supported.",
      chromeos::UndecorateTypeName(any.GetType().name()).c_str());

  return nullptr;
}

}  // namespace

// TODO(vitalybuka): Use in buffet_client.
chromeos::VariantDictionary DictionaryToDBusVariantDictionary(
    const base::DictionaryValue& object) {
  chromeos::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 chromeos::VariantDictionary& object,
    chromeos::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->SetWithoutPathExpansion(pair.first, value.release());
  }

  return result;
}

}  // namespace buffet
