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

#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->CreateDeepCopy());
  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, std::move(prop_def));
  }
  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
