// Copyright 2014 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/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 <chromeos/any.h>
#include <chromeos/strings/string_utils.h>

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

namespace buffet {

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

PropType::~PropType() {
}

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

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

std::unique_ptr<base::Value> PropType::ToJson(bool full_schema,
                                              chromeos::ErrorPtr* error) const {
  if (!full_schema && !HasOverriddenAttributes()) {
    if (based_on_schema_)
      return std::unique_ptr<base::Value>(new base::DictionaryValue);
    return TypedValueToJson(GetTypeAsString(), error);
  }

  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(error);
    }
  }

  for (const auto& pair : constraints_) {
    if (!pair.second->AddToJsonDict(dict.get(), !full_schema, error))
      return std::unique_ptr<base::Value>();
  }
  return std::unique_ptr<base::Value>(dict.release());
}

bool PropType::FromJson(const base::DictionaryValue* value,
                        const PropType* base_schema,
                        chromeos::ErrorPtr* error) {
  if (base_schema && base_schema->GetType() != GetType()) {
    chromeos::Error::AddToPrintf(error, 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();
  std::set<std::string> processed_keys{commands::attributes::kType};
  if (!ObjectSchemaFromJson(value, base_schema, &processed_keys, error))
    return false;
  if (base_schema) {
    for (const auto& pair : base_schema->GetConstraints()) {
      std::shared_ptr<Constraint> inherited(pair.second->CloneAsInherited());
      constraints_.insert(std::make_pair(pair.first, inherited));
    }
  }
  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()) {
      chromeos::Error::AddToPrintf(error, errors::commands::kDomain,
                                   errors::commands::kUnknownProperty,
                                   "Unexpected property '%s'", key.c_str());
      return false;
    }
    iter.Advance();
  }

  return true;
}

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

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

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::ValidateValue(const base::Value* value,
                             chromeos::ErrorPtr* error) const {
  std::shared_ptr<PropValue> val = CreateValue();
  CHECK(val) << "Failed to create value object";
  return val->FromJson(value, error) && ValidateConstraints(*val, error);
}

bool PropType::ValidateValue(const chromeos::Any& value,
                             chromeos::ErrorPtr* error) const {
  std::shared_ptr<PropValue> val = CreateValue(value, error);
  return val && ValidateConstraints(*val, error);
}

bool PropType::ValidateConstraints(const PropValue& value,
                                   chromeos::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"},
  };
  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 buffet::ValueType::Int:
    prop = new IntPropType;
    break;
  case buffet::ValueType::Double:
    prop = new DoublePropType;
    break;
  case buffet::ValueType::String:
    prop = new StringPropType;
    break;
  case buffet::ValueType::Boolean:
    prop = new BooleanPropType;
    break;
  case buffet::ValueType::Object:
    prop = new ObjectPropType;
    break;
  }
  return std::unique_ptr<PropType>(prop);
}

bool PropType::GenerateErrorValueTypeMismatch(chromeos::ErrorPtr* error) const {
  chromeos::Error::AddToPrintf(error, errors::commands::kDomain,
                                errors::commands::kTypeMismatch,
                                "Unable to convert value to type '%s'",
                                GetTypeAsString().c_str());
  return false;
}

template<typename T>
static std::shared_ptr<Constraint> LoadOneOfConstraint(
    const base::DictionaryValue* value, const ObjectSchema* object_schema,
    chromeos::ErrorPtr* error) {
  const base::ListValue* list = nullptr;
  if (!value->GetListWithoutPathExpansion(commands::attributes::kOneOf_Enum,
                                          &list)) {
    chromeos::Error::AddTo(error, errors::commands::kDomain,
                           errors::commands::kTypeMismatch,
                           "Expecting an array");
    return std::shared_ptr<Constraint>();
  }
  std::vector<T> set;
  set.reserve(list->GetSize());
  for (const base::Value* item : *list) {
    T val{};
    if (!TypedValueFromJson(item, object_schema, &val, error))
      return std::shared_ptr<Constraint>();
    set.push_back(val);
  }
  InheritableAttribute<std::vector<T>> val(set, false);
  return std::make_shared<ConstraintOneOf<T>>(val);
}

template<class ConstraintClass, typename T>
static std::shared_ptr<Constraint> LoadMinMaxConstraint(
    const char* dict_key, const base::DictionaryValue* value,
    const ObjectSchema* object_schema, chromeos::ErrorPtr* error) {
  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, object_schema, &limit.value, error))
    return std::shared_ptr<Constraint>();
  limit.is_inherited = false;

  return std::make_shared<ConstraintClass>(limit);
}

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

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

  if (value->HasKey(commands::attributes::kOneOf_Enum)) {
    auto constraint = LoadOneOfConstraint<T>(value, this->GetObjectSchemaPtr(),
                                             error);
    if (!constraint)
      return false;
    this->AddConstraint(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,
    chromeos::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, this->GetObjectSchemaPtr(),
          error);
      if (!constraint)
        return false;
      this->AddConstraint(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, this->GetObjectSchemaPtr(),
          error);
      if (!constraint)
        return false;
      this->AddConstraint(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,
    chromeos::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, GetObjectSchemaPtr(),
          error);
      if (!constraint)
        return false;
      AddConstraint(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, GetObjectSchemaPtr(),
          error);
      if (!constraint)
        return false;
      AddConstraint(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::make_shared<ConstraintStringLengthMin>(min_attr));
  AddConstraint(std::make_shared<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_(std::make_shared<ObjectSchema>(), false) {}

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

std::unique_ptr<base::Value> ObjectPropType::ToJson(
    bool full_schema, chromeos::ErrorPtr* error) const {
  std::unique_ptr<base::Value> value = PropType::ToJson(full_schema, error);
  if (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, error);
      if (!object_schema) {
        value.reset();
        return value;
      }
      dict->SetWithoutPathExpansion(commands::attributes::kObject_Properties,
                                    object_schema.release());
    }
  }
  return value;
}

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

  using commands::attributes::kObject_Properties;

  std::shared_ptr<const ObjectSchema> base_object_schema;
  if (base_schema)
    base_object_schema = base_schema->GetObject()->GetObjectSchema();

  const base::DictionaryValue* props = nullptr;
  if (value->GetDictionaryWithoutPathExpansion(kObject_Properties, &props)) {
    processed_keys->insert(kObject_Properties);
    auto object_schema = std::make_shared<ObjectSchema>();
    if (!object_schema->FromJson(props, base_object_schema.get(), error)) {
      chromeos::Error::AddTo(error, errors::commands::kDomain,
                             errors::commands::kInvalidObjectSchema,
                             "Error parsing object property schema");
      return false;
    }
    object_schema_.value = object_schema;
    object_schema_.is_inherited = false;
  } else if (base_object_schema) {
    object_schema_.value = base_object_schema;
    object_schema_.is_inherited = true;
  } else {
    chromeos::Error::AddToPrintf(error, errors::commands::kDomain,
                                 errors::commands::kInvalidObjectSchema,
                                 "Object type definition must include the "
                                 "object schema ('%s' field not found)",
                                 kObject_Properties);
    return false;
  }

  return true;
}

}  // namespace buffet
