// Copyright 2015 The Weave 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 "src/commands/object_schema.h"

#include <algorithm>
#include <limits>

#include <base/logging.h>
#include <base/values.h>
#include <weave/enum_to_string.h>

#include "src/commands/prop_types.h"
#include "src/commands/prop_values.h"
#include "src/commands/schema_constants.h"
#include "src/string_utils.h"

namespace weave {

namespace {

// Helper function for to create a PropType based on type string.
// Generates an error if the string identifies an unknown type.
std::unique_ptr<PropType> CreatePropType(const std::string& type_name,
                                         ErrorPtr* error) {
  auto parts = SplitAtFirst(type_name, ".", false);
  const std::string& primary_type = parts.first;
  const std::string& array_type = parts.second;

  std::unique_ptr<PropType> prop;
  ValueType type;
  if (PropType::GetTypeFromTypeString(primary_type, &type)) {
    prop = PropType::Create(type);
    if (prop && type == ValueType::Array && !array_type.empty()) {
      auto items_type = CreatePropType(array_type, error);
      if (items_type) {
        prop->GetArray()->SetItemType(std::move(items_type));
      } else {
        prop.reset();
        return prop;
      }
    }
  }
  if (!prop) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                       errors::commands::kUnknownType, "Unknown type %s",
                       type_name.c_str());
  }
  return prop;
}

// Generates "no_type_info" error.
void ErrorInvalidTypeInfo(ErrorPtr* error) {
  Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
               errors::commands::kNoTypeInfo,
               "Unable to determine parameter type");
}

// Helper function for PropFromJson to handle the case of parameter being
// defined as a JSON string like this:
//   "prop":"..."
std::unique_ptr<PropType> PropFromJsonString(const base::Value& value,
                                             const PropType* base_schema,
                                             ErrorPtr* error) {
  std::string type_name;
  CHECK(value.GetAsString(&type_name)) << "Unable to get string value";
  std::unique_ptr<PropType> prop = CreatePropType(type_name, error);
  base::DictionaryValue empty;
  if (prop && !prop->FromJson(&empty, base_schema, error))
    prop.reset();

  return prop;
}

// Detects a type based on JSON array. Inspects the first element of the array
// to deduce the PropType from. Returns the string name of the type detected
// or empty string is type detection failed.
std::string DetectArrayType(const base::ListValue* list,
                            const PropType* base_schema,
                            bool allow_arrays) {
  std::string type_name;
  if (base_schema) {
    type_name = base_schema->GetTypeAsString();
  } else if (list->GetSize() > 0) {
    const base::Value* first_element = nullptr;
    if (list->Get(0, &first_element)) {
      switch (first_element->GetType()) {
        case base::Value::TYPE_BOOLEAN:
          type_name = PropType::GetTypeStringFromType(ValueType::Boolean);
          break;
        case base::Value::TYPE_INTEGER:
          type_name = PropType::GetTypeStringFromType(ValueType::Int);
          break;
        case base::Value::TYPE_DOUBLE:
          type_name = PropType::GetTypeStringFromType(ValueType::Double);
          break;
        case base::Value::TYPE_STRING:
          type_name = PropType::GetTypeStringFromType(ValueType::String);
          break;
        case base::Value::TYPE_DICTIONARY:
          type_name = PropType::GetTypeStringFromType(ValueType::Object);
          break;
        case base::Value::TYPE_LIST: {
          if (allow_arrays) {
            type_name = PropType::GetTypeStringFromType(ValueType::Array);
            const base::ListValue* first_element_list = nullptr;
            if (first_element->GetAsList(&first_element_list)) {
              // We do not allow arrays of arrays.
              auto child_type =
                  DetectArrayType(first_element_list, nullptr, false);
              if (child_type.empty()) {
                type_name.clear();
              } else {
                type_name += '.' + child_type;
              }
            }
          }
          break;
        }
        default:
          // The rest are unsupported.
          break;
      }
    }
  }
  return type_name;
}

// Helper function for PropFromJson to handle the case of parameter being
// defined as a JSON array like this:
//   "prop":[...]
std::unique_ptr<PropType> PropFromJsonArray(const base::Value& value,
                                            const PropType* base_schema,
                                            ErrorPtr* error) {
  std::unique_ptr<PropType> prop;
  const base::ListValue* list = nullptr;
  CHECK(value.GetAsList(&list)) << "Unable to get array value";
  std::string type_name = DetectArrayType(list, base_schema, true);
  if (type_name.empty()) {
    ErrorInvalidTypeInfo(error);
    return prop;
  }
  base::DictionaryValue array_object;
  array_object.SetWithoutPathExpansion(commands::attributes::kOneOf_Enum,
                                       list->DeepCopy());
  prop = CreatePropType(type_name, error);
  if (prop && !prop->FromJson(&array_object, base_schema, error))
    prop.reset();

  return prop;
}

// Detects a type based on JSON object definition of type. Looks at various
// members such as minimum/maximum constraints, default and enum values to
// try to deduce the underlying type of the element. Returns the string name of
// the type detected or empty string is type detection failed.
std::string DetectObjectType(const base::DictionaryValue* dict,
                             const PropType* base_schema) {
  bool has_min_max = dict->HasKey(commands::attributes::kNumeric_Min) ||
                     dict->HasKey(commands::attributes::kNumeric_Max);

  // Here we are trying to "detect the type and read in the object based on
  // the deduced type". Later, we'll verify that this detected type matches
  // the expectation of the base schema, if applicable, to make sure we are not
  // changing the expected type. This makes the vendor-side (re)definition of
  // standard and custom commands behave exactly the same.
  // The only problem with this approach was the double-vs-int types.
  // If the type is meant to be a double we want to allow its definition as
  // "min:0, max:0" instead of just forcing it to be only "min:0.0, max:0.0".
  // If we have "minimum" or "maximum", and we have a Double schema object,
  // treat this object as a Double (even if both min and max are integers).
  if (has_min_max && base_schema && base_schema->GetType() == ValueType::Double)
    return PropType::GetTypeStringFromType(ValueType::Double);

  // If we have at least one "minimum" or "maximum" that is Double,
  // it's a Double.
  const base::Value* value = nullptr;
  if (dict->Get(commands::attributes::kNumeric_Min, &value) &&
      value->IsType(base::Value::TYPE_DOUBLE))
    return PropType::GetTypeStringFromType(ValueType::Double);
  if (dict->Get(commands::attributes::kNumeric_Max, &value) &&
      value->IsType(base::Value::TYPE_DOUBLE))
    return PropType::GetTypeStringFromType(ValueType::Double);

  // If we have "minimum" or "maximum", it's an Integer.
  if (has_min_max)
    return PropType::GetTypeStringFromType(ValueType::Int);

  // If we have "minLength" or "maxLength", it's a String.
  if (dict->HasKey(commands::attributes::kString_MinLength) ||
      dict->HasKey(commands::attributes::kString_MaxLength))
    return PropType::GetTypeStringFromType(ValueType::String);

  // If we have "properties", it's an object.
  if (dict->HasKey(commands::attributes::kObject_Properties))
    return PropType::GetTypeStringFromType(ValueType::Object);

  // If we have "items", it's an array.
  if (dict->HasKey(commands::attributes::kItems))
    return PropType::GetTypeStringFromType(ValueType::Array);

  // If we have "enum", it's an array. Detect type from array elements.
  const base::ListValue* list = nullptr;
  if (dict->GetListWithoutPathExpansion(commands::attributes::kOneOf_Enum,
                                        &list))
    return DetectArrayType(list, base_schema, true);

  // If we have "default", try to use it for type detection.
  if (dict->Get(commands::attributes::kDefault, &value)) {
    if (value->IsType(base::Value::TYPE_DOUBLE))
      return PropType::GetTypeStringFromType(ValueType::Double);
    if (value->IsType(base::Value::TYPE_INTEGER))
      return PropType::GetTypeStringFromType(ValueType::Int);
    if (value->IsType(base::Value::TYPE_BOOLEAN))
      return PropType::GetTypeStringFromType(ValueType::Boolean);
    if (value->IsType(base::Value::TYPE_STRING))
      return PropType::GetTypeStringFromType(ValueType::String);
    if (value->IsType(base::Value::TYPE_LIST)) {
      CHECK(value->GetAsList(&list)) << "List value expected";
      std::string child_type = DetectArrayType(list, base_schema, false);
      if (!child_type.empty()) {
        return PropType::GetTypeStringFromType(ValueType::Array) + '.' +
               child_type;
      }
    }
  }

  return std::string{};
}

// Helper function for PropFromJson to handle the case of parameter being
// defined as a JSON object like this:
//   "prop":{...}
std::unique_ptr<PropType> PropFromJsonObject(const base::Value& value,
                                             const PropType* base_schema,
                                             ErrorPtr* error) {
  std::unique_ptr<PropType> prop;
  const base::DictionaryValue* dict = nullptr;
  CHECK(value.GetAsDictionary(&dict)) << "Unable to get dictionary value";
  std::string type_name;
  if (dict->HasKey(commands::attributes::kType)) {
    if (!dict->GetString(commands::attributes::kType, &type_name)) {
      ErrorInvalidTypeInfo(error);
      return prop;
    }
  } else {
    type_name = DetectObjectType(dict, base_schema);
  }
  if (type_name.empty()) {
    if (!base_schema) {
      ErrorInvalidTypeInfo(error);
      return prop;
    }
    type_name = base_schema->GetTypeAsString();
  }
  prop = CreatePropType(type_name, error);
  if (prop && !prop->FromJson(dict, base_schema, error))
    prop.reset();

  return prop;
}

const EnumToStringMap<base::Value::Type>::Map kMap[] = {
    {base::Value::TYPE_NULL, "Null"},
    {base::Value::TYPE_BOOLEAN, "Boolean"},
    {base::Value::TYPE_INTEGER, "Integer"},
    {base::Value::TYPE_DOUBLE, "Double"},
    {base::Value::TYPE_STRING, "String"},
    {base::Value::TYPE_BINARY, "Binary"},
    {base::Value::TYPE_DICTIONARY, "Object"},
    {base::Value::TYPE_LIST, "Array"},
};

}  // anonymous namespace

template <>
EnumToStringMap<base::Value::Type>::EnumToStringMap() : EnumToStringMap(kMap) {}

ObjectSchema::ObjectSchema() {}
ObjectSchema::~ObjectSchema() {}

std::unique_ptr<ObjectSchema> ObjectSchema::Clone() const {
  std::unique_ptr<ObjectSchema> cloned{new ObjectSchema};
  for (const auto& pair : properties_) {
    cloned->properties_.emplace(pair.first, pair.second->Clone());
  }
  cloned->extra_properties_allowed_ = extra_properties_allowed_;
  return cloned;
}

void ObjectSchema::AddProp(const std::string& name,
                           std::unique_ptr<PropType> prop) {
  // Not using emplace() here to make sure we override existing properties.
  properties_[name] = std::move(prop);
}

const PropType* ObjectSchema::GetProp(const std::string& name) const {
  auto p = properties_.find(name);
  return p != properties_.end() ? p->second.get() : nullptr;
}

bool ObjectSchema::MarkPropRequired(const std::string& name, ErrorPtr* error) {
  auto p = properties_.find(name);
  if (p == properties_.end()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                       errors::commands::kUnknownProperty,
                       "Unknown property '%s'", name.c_str());
    return false;
  }
  p->second->MakeRequired(true);
  return true;
}

std::unique_ptr<base::DictionaryValue> ObjectSchema::ToJson(
    bool full_schema,
    bool in_command_def) const {
  std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue);
  for (const auto& pair : properties_) {
    auto prop_def = pair.second->ToJson(full_schema, in_command_def);
    CHECK(prop_def);
    value->SetWithoutPathExpansion(pair.first, prop_def.release());
  }
  return value;
}

bool ObjectSchema::FromJson(const base::DictionaryValue* value,
                            const ObjectSchema* object_schema,
                            ErrorPtr* error) {
  Properties properties;
  base::DictionaryValue::Iterator iter(*value);
  while (!iter.IsAtEnd()) {
    std::string name = iter.key();
    const PropType* base_schema =
        object_schema ? object_schema->GetProp(iter.key()) : nullptr;
    auto prop_type = PropFromJson(iter.value(), base_schema, error);
    if (prop_type) {
      properties.emplace(iter.key(), std::move(prop_type));
    } else {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                         errors::commands::kInvalidPropDef,
                         "Error in definition of property '%s'",
                         iter.key().c_str());
      return false;
    }
    iter.Advance();
  }
  properties_ = std::move(properties);
  return true;
}

std::unique_ptr<PropType> ObjectSchema::PropFromJson(
    const base::Value& value,
    const PropType* base_schema,
    ErrorPtr* error) {
  if (value.IsType(base::Value::TYPE_STRING)) {
    // A string value is a short-hand object specification and provides
    // the parameter type.
    return PropFromJsonString(value, base_schema, error);
  } else if (value.IsType(base::Value::TYPE_LIST)) {
    // One of the enumerated types.
    return PropFromJsonArray(value, base_schema, error);
  } else if (value.IsType(base::Value::TYPE_DICTIONARY)) {
    // Full parameter definition.
    return PropFromJsonObject(value, base_schema, error);
  }
  Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                     errors::commands::kUnknownType,
                     "Unexpected JSON value type: %s",
                     EnumToString(value.GetType()).c_str());
  return nullptr;
}

std::unique_ptr<ObjectSchema> ObjectSchema::Create() {
  return std::unique_ptr<ObjectSchema>{new ObjectSchema};
}

}  // namespace weave
