// 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/prop_types.h"

#include <algorithm>
#include <limits>
#include <set>

#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/values.h>

#include "src/commands/object_schema.h"
#include "src/commands/prop_values.h"
#include "src/commands/schema_constants.h"

namespace weave {

// PropType -------------------------------------------------------------------
PropType::PropType() {}

PropType::~PropType() {}

std::string PropType::GetTypeAsString() const {
  return GetTypeStringFromType(GetType());
}

bool PropType::HasOverriddenAttributes() const {
  if (default_.value && !default_.is_inherited)
    return true;

  for (const auto& pair : constraints_) {
    if (pair.second->HasOverriddenAttributes())
      return true;
  }
  return false;
}

bool PropType::IsRequired() const {
  return required_.value;
}

void PropType::MakeRequired(bool required) {
  required_.value = required;
  required_.is_inherited = false;
}

std::unique_ptr<base::Value> PropType::ToJson(bool full_schema,
                                              bool in_command_def) const {
  // Determine if we need to output "isRequired" attribute.
  const bool include_required = in_command_def && !required_.is_inherited;

  // If we must include "isRequired" attribute, then treat this as "full schema"
  // request because there could be cases where we have just this attribute and
  // won't be able to infer the type from the constraints only.
  if (include_required)
    full_schema = true;

  if (!full_schema && !HasOverriddenAttributes()) {
    if (based_on_schema_)
      return std::unique_ptr<base::Value>(new base::DictionaryValue);
    return TypedValueToJson(GetTypeAsString());
  }

  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
  if (full_schema) {
    // If we are asked for full_schema definition, then we need to output every
    // parameter property, including the "type", and any constraints.
    // So, we write the "type" only if asked for full schema.
    // Otherwise we will be able to infer the parameter type based on
    // the constraints and their types.
    // That is, the following JSONs could possibly define a parameter:
    // {'type':'integer'} -> explicit "integer" with no constraints
    // {'minimum':10} -> no type specified, but since we have "minimum"
    //                   and 10 is integer, than this is an integer
    //                   parameter with min constraint.
    // {'enum':[1,2,3]} -> integer with OneOf constraint.
    // And so is this: [1,2,3] -> an array of ints assume it's an "int" enum.
    dict->SetString(commands::attributes::kType, GetTypeAsString());
  }

  if (!full_schema && constraints_.size() == 1) {
    // If we are not asked for full schema, and we have only one constraint
    // which is OneOf, we short-circuit the whole thing and return just
    // the array [1,2,3] instead of an object with "enum" property like:
    // {'enum':[1,2,3]}
    auto p = constraints_.find(ConstraintType::OneOf);
    if (p != constraints_.end()) {
      return p->second->ToJson();
    }
  }

  for (const auto& pair : constraints_)
    pair.second->AddToJsonDict(dict.get(), !full_schema);

  if (default_.value && (full_schema || !default_.is_inherited)) {
    auto def_val = default_.value->ToJson();
    CHECK(def_val);
    dict->Set(commands::attributes::kDefault, std::move(def_val));
  }

  if (include_required)
    dict->SetBoolean(commands::attributes::kIsRequired, required_.value);
  return std::unique_ptr<base::Value>(dict.release());
}

std::unique_ptr<PropType> PropType::Clone() const {
  auto cloned = PropType::Create(GetType());
  cloned->based_on_schema_ = based_on_schema_;
  for (const auto& pair : constraints_) {
    cloned->constraints_.emplace(pair.first, pair.second->Clone());
  }
  cloned->default_.is_inherited = default_.is_inherited;
  if (default_.value)
    cloned->default_.value = default_.value->Clone();
  cloned->required_ = required_;
  return cloned;
}

bool PropType::FromJson(const base::DictionaryValue* value,
                        const PropType* base_schema,
                        ErrorPtr* error) {
  if (base_schema && base_schema->GetType() != GetType()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                       errors::commands::kPropTypeChanged,
                       "Redefining a property of type %s as %s",
                       base_schema->GetTypeAsString().c_str(),
                       GetTypeAsString().c_str());
    return false;
  }
  based_on_schema_ = (base_schema != nullptr);
  constraints_.clear();
  // Add the well-known object properties first (like "type", "displayName",
  // "default") to the list of "processed" keys so we do not complain about them
  // when we check for unknown/unexpected keys below.
  std::set<std::string> processed_keys{
      commands::attributes::kType, commands::attributes::kDisplayName,
      commands::attributes::kDefault, commands::attributes::kIsRequired,
  };
  if (!ObjectSchemaFromJson(value, base_schema, &processed_keys, error))
    return false;
  if (base_schema) {
    for (const auto& pair : base_schema->GetConstraints()) {
      constraints_.emplace(pair.first, pair.second->CloneAsInherited());
    }
  }
  if (!ConstraintsFromJson(value, &processed_keys, error))
    return false;

  // Now make sure there are no unexpected/unknown keys in the property schema
  // definition object.
  base::DictionaryValue::Iterator iter(*value);
  while (!iter.IsAtEnd()) {
    std::string key = iter.key();
    if (processed_keys.find(key) == processed_keys.end()) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                         errors::commands::kUnknownProperty,
                         "Unexpected property '%s'", key.c_str());
      return false;
    }
    iter.Advance();
  }

  // Read the "isRequired" attribute, if specified.
  bool required = false;
  if (value->GetBoolean(commands::attributes::kIsRequired, &required)) {
    required_.value = required;
    required_.is_inherited = false;
  } else if (base_schema) {
    // If we have the base schema, inherit the type's required value from it.
    if (base_schema->required_.value)
      required_.value = base_schema->required_.value;
    required_.is_inherited = true;
  }

  // Read the default value, if specified.
  // We need to do this last since the current type definition must be complete,
  // so we can parse and validate the value of the default.
  const base::Value* defval = nullptr;  // Owned by value
  if (value->GetWithoutPathExpansion(commands::attributes::kDefault, &defval)) {
    std::unique_ptr<PropValue> prop_value = CreatePropValue(*defval, error);
    if (!prop_value) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                         errors::commands::kInvalidPropValue,
                         "Invalid value for property '%s'",
                         commands::attributes::kDefault);
      return false;
    }
    default_.value = std::move(prop_value);
    default_.is_inherited = false;
  } else if (base_schema) {
    // If we have the base schema, inherit the type's default value from it.
    // It doesn't matter if the base schema actually has a default value
    // specified or not. If it doesn't, then the current type definition will
    // have no default value set either (|default_.value| is a unique_ptr to
    // PropValue, which can be set to nullptr).
    if (base_schema->default_.value)
      default_.value = base_schema->default_.value->Clone();
    default_.is_inherited = true;
  }
  return true;
}

void PropType::AddConstraint(std::unique_ptr<Constraint> constraint) {
  constraints_[constraint->GetType()] = std::move(constraint);
}

void PropType::RemoveConstraint(ConstraintType constraint_type) {
  constraints_.erase(constraint_type);
}

void PropType::RemoveAllConstraints() {
  constraints_.clear();
}

const Constraint* PropType::GetConstraint(
    ConstraintType constraint_type) const {
  auto p = constraints_.find(constraint_type);
  return p != constraints_.end() ? p->second.get() : nullptr;
}

Constraint* PropType::GetConstraint(ConstraintType constraint_type) {
  auto p = constraints_.find(constraint_type);
  return p != constraints_.end() ? p->second.get() : nullptr;
}

bool PropType::ValidateConstraints(const PropValue& value,
                                   ErrorPtr* error) const {
  for (const auto& pair : constraints_) {
    if (!pair.second->Validate(value, error))
      return false;
  }
  return true;
}

const PropType::TypeMap& PropType::GetTypeMap() {
  static TypeMap map = {
      {ValueType::Int, "integer"},   {ValueType::Double, "number"},
      {ValueType::String, "string"}, {ValueType::Boolean, "boolean"},
      {ValueType::Object, "object"}, {ValueType::Array, "array"},
  };
  return map;
}

std::string PropType::GetTypeStringFromType(ValueType type) {
  for (const auto& pair : GetTypeMap()) {
    if (pair.first == type)
      return pair.second;
  }
  LOG(FATAL) << "Type map is missing a type";
  return std::string();
}

bool PropType::GetTypeFromTypeString(const std::string& name, ValueType* type) {
  for (const auto& pair : GetTypeMap()) {
    if (pair.second == name) {
      *type = pair.first;
      return true;
    }
  }
  return false;
}

std::unique_ptr<PropType> PropType::Create(ValueType type) {
  PropType* prop = nullptr;
  switch (type) {
    case ValueType::Int:
      prop = new IntPropType;
      break;
    case ValueType::Double:
      prop = new DoublePropType;
      break;
    case ValueType::String:
      prop = new StringPropType;
      break;
    case ValueType::Boolean:
      prop = new BooleanPropType;
      break;
    case ValueType::Object:
      prop = new ObjectPropType;
      break;
    case ValueType::Array:
      prop = new ArrayPropType;
      break;
  }
  return std::unique_ptr<PropType>(prop);
}

template <typename T>
static std::unique_ptr<Constraint> LoadOneOfConstraint(
    const base::DictionaryValue* value,
    const PropType* prop_type,
    ErrorPtr* error) {
  std::unique_ptr<Constraint> constraint;
  const base::Value* list = nullptr;  // Owned by |value|
  CHECK(value->Get(commands::attributes::kOneOf_Enum, &list))
      << "'enum' property missing in JSON dictionary";
  ValueVector choice_list;
  ArrayPropType array_type;
  array_type.SetItemType(prop_type->Clone());
  if (!TypedValueFromJson(list, &array_type, &choice_list, error))
    return constraint;
  InheritableAttribute<ValueVector> val(std::move(choice_list), false);
  constraint.reset(new ConstraintOneOf{std::move(val)});
  return constraint;
}

template <class ConstraintClass, typename T>
static std::unique_ptr<Constraint> LoadMinMaxConstraint(
    const char* dict_key,
    const base::DictionaryValue* value,
    ErrorPtr* error) {
  std::unique_ptr<Constraint> constraint;
  InheritableAttribute<T> limit;

  const base::Value* src_val = nullptr;
  CHECK(value->Get(dict_key, &src_val)) << "Unable to get min/max constraints";
  if (!TypedValueFromJson(src_val, nullptr, &limit.value, error))
    return constraint;
  limit.is_inherited = false;

  constraint.reset(new ConstraintClass{limit});
  return constraint;
}

// PropTypeBase ----------------------------------------------------------------

template <class Derived, class Value, typename T>
bool PropTypeBase<Derived, Value, T>::ConstraintsFromJson(
    const base::DictionaryValue* value,
    std::set<std::string>* processed_keys,
    ErrorPtr* error) {
  if (!PropType::ConstraintsFromJson(value, processed_keys, error))
    return false;

  if (value->HasKey(commands::attributes::kOneOf_Enum)) {
    auto type = Clone();
    type->RemoveAllConstraints();
    auto constraint = LoadOneOfConstraint<T>(value, type.get(), error);
    if (!constraint)
      return false;
    this->AddConstraint(std::move(constraint));
    this->RemoveConstraint(ConstraintType::Min);
    this->RemoveConstraint(ConstraintType::Max);
    processed_keys->insert(commands::attributes::kOneOf_Enum);
  }

  return true;
}

// NumericPropTypeBase ---------------------------------------------------------

template <class Derived, class Value, typename T>
bool NumericPropTypeBase<Derived, Value, T>::ConstraintsFromJson(
    const base::DictionaryValue* value,
    std::set<std::string>* processed_keys,
    ErrorPtr* error) {
  if (!Base::ConstraintsFromJson(value, processed_keys, error))
    return false;

  if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
      processed_keys->end()) {
    // Process min/max constraints only if "enum" constraint wasn't already
    // specified.
    if (value->HasKey(commands::attributes::kNumeric_Min)) {
      auto constraint = LoadMinMaxConstraint<ConstraintMin<T>, T>(
          commands::attributes::kNumeric_Min, value, error);
      if (!constraint)
        return false;
      this->AddConstraint(std::move(constraint));
      this->RemoveConstraint(ConstraintType::OneOf);
      processed_keys->insert(commands::attributes::kNumeric_Min);
    }
    if (value->HasKey(commands::attributes::kNumeric_Max)) {
      auto constraint = LoadMinMaxConstraint<ConstraintMax<T>, T>(
          commands::attributes::kNumeric_Max, value, error);
      if (!constraint)
        return false;
      this->AddConstraint(std::move(constraint));
      this->RemoveConstraint(ConstraintType::OneOf);
      processed_keys->insert(commands::attributes::kNumeric_Max);
    }
  }

  return true;
}

// StringPropType -------------------------------------------------------------

bool StringPropType::ConstraintsFromJson(const base::DictionaryValue* value,
                                         std::set<std::string>* processed_keys,
                                         ErrorPtr* error) {
  if (!Base::ConstraintsFromJson(value, processed_keys, error))
    return false;

  if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
      processed_keys->end()) {
    // Process min/max constraints only if "enum" constraint wasn't already
    // specified.
    if (value->HasKey(commands::attributes::kString_MinLength)) {
      auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMin, int>(
          commands::attributes::kString_MinLength, value, error);
      if (!constraint)
        return false;
      AddConstraint(std::move(constraint));
      RemoveConstraint(ConstraintType::OneOf);
      processed_keys->insert(commands::attributes::kString_MinLength);
    }
    if (value->HasKey(commands::attributes::kString_MaxLength)) {
      auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMax, int>(
          commands::attributes::kString_MaxLength, value, error);
      if (!constraint)
        return false;
      AddConstraint(std::move(constraint));
      RemoveConstraint(ConstraintType::OneOf);
      processed_keys->insert(commands::attributes::kString_MaxLength);
    }
  }
  return true;
}

void StringPropType::AddLengthConstraint(int min_len, int max_len) {
  InheritableAttribute<int> min_attr(min_len, false);
  InheritableAttribute<int> max_attr(max_len, false);
  AddConstraint(std::unique_ptr<ConstraintStringLengthMin>{
      new ConstraintStringLengthMin{min_attr}});
  AddConstraint(std::unique_ptr<ConstraintStringLengthMax>{
      new ConstraintStringLengthMax{max_attr}});
}

int StringPropType::GetMinLength() const {
  auto slc = static_cast<const ConstraintStringLength*>(
      GetConstraint(ConstraintType::StringLengthMin));
  return slc ? slc->limit_.value : 0;
}

int StringPropType::GetMaxLength() const {
  auto slc = static_cast<const ConstraintStringLength*>(
      GetConstraint(ConstraintType::StringLengthMax));
  return slc ? slc->limit_.value : std::numeric_limits<int>::max();
}

// ObjectPropType -------------------------------------------------------------

ObjectPropType::ObjectPropType()
    : object_schema_{ObjectSchema::Create(), false} {}

bool ObjectPropType::HasOverriddenAttributes() const {
  return PropType::HasOverriddenAttributes() || !object_schema_.is_inherited;
}

std::unique_ptr<PropType> ObjectPropType::Clone() const {
  auto cloned = Base::Clone();

  cloned->GetObject()->object_schema_.is_inherited =
      object_schema_.is_inherited;
  cloned->GetObject()->object_schema_.value = object_schema_.value->Clone();
  return cloned;
}

std::unique_ptr<base::Value> ObjectPropType::ToJson(bool full_schema,
                                                    bool in_command_def) const {
  std::unique_ptr<base::Value> value =
      PropType::ToJson(full_schema, in_command_def);
  CHECK(value);
  base::DictionaryValue* dict = nullptr;
  CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
  if (!object_schema_.is_inherited || full_schema) {
    auto object_schema = object_schema_.value->ToJson(full_schema, false);
    CHECK(object_schema);

    dict->SetWithoutPathExpansion(commands::attributes::kObject_Properties,
                                  std::move(object_schema));
    dict->SetBooleanWithoutPathExpansion(
        commands::attributes::kObject_AdditionalProperties,
        object_schema_.value->GetExtraPropertiesAllowed());
    std::unique_ptr<base::ListValue> required{new base::ListValue};
    for (const auto& pair : object_schema_.value->GetProps()) {
      if (pair.second->IsRequired())
        required->AppendString(pair.first);
    }
    if (required->GetSize() > 0) {
      dict->Set(commands::attributes::kObject_Required, std::move(required));
    }
  }
  return value;
}

bool ObjectPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
                                          const PropType* base_schema,
                                          std::set<std::string>* processed_keys,
                                          ErrorPtr* error) {
  if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
    return false;

  using commands::attributes::kObject_Properties;
  using commands::attributes::kObject_AdditionalProperties;

  const ObjectSchema* base_object_schema = nullptr;
  if (base_schema)
    base_object_schema = base_schema->GetObject()->GetObjectSchemaPtr();

  const base::DictionaryValue* props = nullptr;
  std::unique_ptr<ObjectSchema> object_schema;
  bool inherited = false;
  if (value->GetDictionaryWithoutPathExpansion(kObject_Properties, &props)) {
    processed_keys->insert(kObject_Properties);
    object_schema.reset(new ObjectSchema);
    if (!object_schema->FromJson(props, base_object_schema, error)) {
      Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
                   errors::commands::kInvalidObjectSchema,
                   "Error parsing object property schema");
      return false;
    }
  } else if (base_object_schema) {
    object_schema = base_object_schema->Clone();
    inherited = true;
  } else {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                       errors::commands::kInvalidObjectSchema,
                       "Object type definition must include the "
                       "object schema ('%s' field not found)",
                       kObject_Properties);
    return false;
  }
  bool extra_properties_allowed = false;
  if (value->GetBooleanWithoutPathExpansion(kObject_AdditionalProperties,
                                            &extra_properties_allowed)) {
    processed_keys->insert(kObject_AdditionalProperties);
    object_schema->SetExtraPropertiesAllowed(extra_properties_allowed);
    inherited = false;
  }
  const base::Value* required = nullptr;
  if (value->Get(commands::attributes::kObject_Required, &required)) {
    processed_keys->insert(commands::attributes::kObject_Required);
    const base::ListValue* required_list = nullptr;
    if (!required->GetAsList(&required_list)) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                         errors::commands::kInvalidObjectSchema,
                         "Property '%s' must be an array",
                         commands::attributes::kObject_Required);
      return false;
    }
    for (const base::Value* value : *required_list) {
      std::string name;
      if (!value->GetAsString(&name)) {
        std::string json_value;
        CHECK(base::JSONWriter::Write(*value, &json_value));
        Error::AddToPrintf(
            error, FROM_HERE, errors::commands::kDomain,
            errors::commands::kInvalidObjectSchema,
            "Property '%s' contains invalid element (%s). String expected",
            commands::attributes::kObject_Required, json_value.c_str());
        return false;
      }
      if (!object_schema->MarkPropRequired(name, error))
        return false;
      inherited = false;
    }
  }
  object_schema_.value = std::move(object_schema);
  object_schema_.is_inherited = inherited;

  return true;
}

void ObjectPropType::SetObjectSchema(
    std::unique_ptr<const ObjectSchema> schema) {
  object_schema_.value = std::move(schema);
  object_schema_.is_inherited = false;
}

// ArrayPropType -------------------------------------------------------------

ArrayPropType::ArrayPropType() {}

bool ArrayPropType::HasOverriddenAttributes() const {
  return PropType::HasOverriddenAttributes() || !item_type_.is_inherited;
}

std::unique_ptr<PropType> ArrayPropType::Clone() const {
  auto cloned = Base::Clone();

  cloned->GetArray()->item_type_.is_inherited = item_type_.is_inherited;
  cloned->GetArray()->item_type_.value = item_type_.value->Clone();
  return cloned;
}

std::unique_ptr<base::Value> ArrayPropType::ToJson(bool full_schema,
                                                   bool in_command_def) const {
  std::unique_ptr<base::Value> value =
      PropType::ToJson(full_schema, in_command_def);
  CHECK(value);
  if (!item_type_.is_inherited || full_schema) {
    base::DictionaryValue* dict = nullptr;
    CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
    auto type = item_type_.value->ToJson(full_schema, false);
    CHECK(type);
    dict->SetWithoutPathExpansion(commands::attributes::kItems,
                                  std::move(type));
  }
  return value;
}

bool ArrayPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
                                         const PropType* base_schema,
                                         std::set<std::string>* processed_keys,
                                         ErrorPtr* error) {
  if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
    return false;

  using commands::attributes::kItems;

  const PropType* base_type = nullptr;
  if (base_schema)
    base_type = base_schema->GetArray()->GetItemTypePtr();

  const base::Value* type_value = nullptr;
  if (value->GetWithoutPathExpansion(kItems, &type_value)) {
    processed_keys->insert(kItems);
    auto item_type = ObjectSchema::PropFromJson(*type_value, base_type, error);
    if (!item_type)
      return false;
    if (item_type->GetType() == ValueType::Array) {
      Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
                   errors::commands::kInvalidObjectSchema,
                   "Arrays of arrays are not supported");
      return false;
    }
    SetItemType(std::move(item_type));
  } else if (!item_type_.value) {
    if (base_type) {
      item_type_.value = base_type->Clone();
      item_type_.is_inherited = true;
    } else {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                         errors::commands::kInvalidObjectSchema,
                         "Array type definition must include the "
                         "array item type ('%s' field not found)",
                         kItems);
      return false;
    }
  }
  return true;
}

void ArrayPropType::SetItemType(std::unique_ptr<const PropType> item_type) {
  item_type_.value = std::move(item_type);
  item_type_.is_inherited = false;
}

}  // namespace weave
