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

#ifndef LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_
#define LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_

#include <limits>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <weave/error.h>

#include "src/commands/prop_constraints.h"
#include "src/commands/prop_values.h"

namespace weave {

class IntPropType;
class DoublePropType;
class StringPropType;
class BooleanPropType;
class ObjectPropType;
class ArrayPropType;

// PropType is a base class for all parameter type definition objects.
// Property definitions of a particular type will derive from this class and
// provide type-specific implementations.
class PropType {
 public:
  // ConstraintMap is a type alias for a map containing parameter
  // constraints. It is implemented as a map for fast look-ups of constraints
  // of particular type. Also it is expected to have at most one constraint
  // of each type (e.g. it makes no sense to impose two "minimum" constraints
  // onto a numeric parameter).
  using ConstraintMap = std::map<ConstraintType, std::unique_ptr<Constraint>>;

  PropType();
  virtual ~PropType();

  // Gets the parameter type as an enumeration.
  virtual ValueType GetType() const = 0;
  // Gets the parameter type as a string.
  std::string GetTypeAsString() const;
  // Returns true if this parameter definition inherits a type
  // definition from a base object schema.
  bool IsBasedOnSchema() const { return based_on_schema_; }
  // Returns a default value specified for the type, or nullptr if no default
  // is available.
  const PropValue* GetDefaultValue() const { return default_.value.get(); }
  // Gets the constraints specified for the parameter, if any.
  const ConstraintMap& GetConstraints() const { return constraints_; }
  // Returns true if this value is required. Properties are marked as required
  // by using "isRequired" attribute or listed in "required" array.
  bool IsRequired() const;
  // Sets the required attribute to the value of |required| and marks it as
  // overridden (not-inherited).
  void MakeRequired(bool required);
  // Checks if any of the type attributes were overridden from the base
  // schema definition. If this type does not inherit from a base schema,
  // this method returns true.
  // An attribute could be the value of any of the constraints, default
  // value of a parameter or any other data that may be specified in
  // parameter type definition in and can be inherited from the base schema.
  virtual bool HasOverriddenAttributes() const;

  // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
  virtual IntPropType* GetInt() { return nullptr; }
  virtual IntPropType const* GetInt() const { return nullptr; }
  virtual DoublePropType* GetDouble() { return nullptr; }
  virtual DoublePropType const* GetDouble() const { return nullptr; }
  virtual StringPropType* GetString() { return nullptr; }
  virtual StringPropType const* GetString() const { return nullptr; }
  virtual BooleanPropType* GetBoolean() { return nullptr; }
  virtual BooleanPropType const* GetBoolean() const { return nullptr; }
  virtual ObjectPropType* GetObject() { return nullptr; }
  virtual ObjectPropType const* GetObject() const { return nullptr; }
  virtual ArrayPropType* GetArray() { return nullptr; }
  virtual ArrayPropType const* GetArray() const { return nullptr; }

  // Makes a full copy of this type definition.
  virtual std::unique_ptr<PropType> Clone() const;

  // Creates an instance of associated value object.
  virtual std::unique_ptr<PropValue> CreatePropValue(const base::Value& value,
                                                     ErrorPtr* error) const = 0;

  // Saves the parameter type definition as a JSON object.
  // If |full_schema| is set to true, the full type definition is saved,
  // otherwise only the overridden properties and attributes from the base
  // schema is saved. That is, inherited properties and attributes are not
  // saved.
  // If it fails, returns "nullptr" and fills in the |error| with additional
  // error information.
  // |in_command_def| is set to true if the property type describes a
  // GCD command parameter, otherwise it is for an object property.
  // Command definitions handle required parameters differently (using
  // "isRequired" property as opposed to "required" list for object properties).
  virtual std::unique_ptr<base::Value> ToJson(bool full_schema,
                                              bool in_command_def) const;
  // Parses an JSON parameter type definition. Optional |base_schema| may
  // specify the base schema type definition this type should be based upon.
  // If not specified (nullptr), the parameter type is assumed to be a full
  // definition and any omitted required properties are treated as an error.
  // Returns true on success, otherwise fills in the |error| with additional
  // error information.
  virtual bool FromJson(const base::DictionaryValue* value,
                        const PropType* base_schema,
                        ErrorPtr* error);
  // Helper function to load object schema from JSON.
  virtual bool ObjectSchemaFromJson(const base::DictionaryValue* value,
                                    const PropType* base_schema,
                                    std::set<std::string>* processed_keys,
                                    ErrorPtr* error) {
    return true;
  }
  // Helper function to load type-specific constraints from JSON.
  virtual bool ConstraintsFromJson(const base::DictionaryValue* value,
                                   std::set<std::string>* processed_keys,
                                   ErrorPtr* error) {
    return true;
  }

  // Additional helper static methods to help with converting a type enum
  // value into a string and back.
  using TypeMap = std::vector<std::pair<ValueType, std::string>>;
  // Returns a list of value types and corresponding type names.
  static const TypeMap& GetTypeMap();
  // Gets the type name string for the given type.
  static std::string GetTypeStringFromType(ValueType type);
  // Finds the type for the given type name. Returns true on success.
  static bool GetTypeFromTypeString(const std::string& name, ValueType* type);

  // Creates an instance of PropType-derived class for the specified
  // parameter type.
  static std::unique_ptr<PropType> Create(ValueType type);

  // Adds a constraint to the type definition.
  void AddConstraint(std::unique_ptr<Constraint> constraint);
  // Removes a constraint of given type, if it exists.
  void RemoveConstraint(ConstraintType constraint_type);
  // Removes all constraints.
  void RemoveAllConstraints();

  // Finds a constraint of given type. Returns nullptr if not found.
  const Constraint* GetConstraint(ConstraintType constraint_type) const;
  Constraint* GetConstraint(ConstraintType constraint_type);

  // Validates the given value against all the constraints.
  bool ValidateConstraints(const PropValue& value, ErrorPtr* error) const;

 protected:
  friend class StatePackage;
  virtual std::unique_ptr<PropValue> CreateDefaultValue() const = 0;

  // Specifies if this parameter definition is derived from a base
  // object schema.
  bool based_on_schema_ = false;
  // A list of constraints specified for the parameter.
  ConstraintMap constraints_;
  // The default value specified for the parameter, if any. If the default
  // value is present, the parameter is treated as optional and the default
  // value is used if the parameter value is omitted when sending a command.
  // Otherwise the parameter is treated as required and, if it is omitted,
  // this is treated as an error.
  InheritableAttribute<std::unique_ptr<PropValue>> default_;
  // Specifies whether the parameter/property is required and must be specified
  // (either directly, or by the default value being provided in the schema).
  // Non-required parameters can be omitted completely and their values will not
  // be present in the object instance.
  InheritableAttribute<bool> required_;
};

// Base class for all the derived concrete implementations of property
// type classes. Provides implementations for common methods of PropType base.
template <class Derived, class Value, typename T>
class PropTypeBase : public PropType {
 public:
  // Overrides from PropType.
  ValueType GetType() const override { return GetValueType<T>(); }

  std::unique_ptr<PropValue> CreatePropValue(const base::Value& value,
                                             ErrorPtr* error) const override {
    return CreateValue(value, error);
  }

  std::unique_ptr<Value> CreateValue(const base::Value& value,
                                     ErrorPtr* error) const {
    return Value::CreateFromJson(value, *this, error);
  }

  bool ConstraintsFromJson(const base::DictionaryValue* value,
                           std::set<std::string>* processed_keys,
                           ErrorPtr* error) override;

 protected:
  std::unique_ptr<PropValue> CreateDefaultValue() const override {
    if (GetDefaultValue())
      return GetDefaultValue()->Clone();
    return std::unique_ptr<PropValue>{new Value{*this}};
  }
};

// Helper base class for Int and Double parameter types.
template <class Derived, class Value, typename T>
class NumericPropTypeBase : public PropTypeBase<Derived, Value, T> {
 public:
  using Base = PropTypeBase<Derived, Value, T>;
  bool ConstraintsFromJson(const base::DictionaryValue* value,
                           std::set<std::string>* processed_keys,
                           ErrorPtr* error) override;

  // Helper method to set and obtain a min/max constraint values.
  // Used mostly for unit testing.
  void AddMinMaxConstraint(T min_value, T max_value) {
    InheritableAttribute<T> min_attr(min_value, false);
    InheritableAttribute<T> max_attr(max_value, false);
    this->AddConstraint(
        std::unique_ptr<ConstraintMin<T>>{new ConstraintMin<T>{min_attr}});
    this->AddConstraint(
        std::unique_ptr<ConstraintMax<T>>{new ConstraintMax<T>{max_attr}});
  }
  T GetMinValue() const {
    auto mmc = static_cast<const ConstraintMin<T>*>(
        this->GetConstraint(ConstraintType::Min));
    return mmc ? mmc->limit_.value : std::numeric_limits<T>::lowest();
  }
  T GetMaxValue() const {
    auto mmc = static_cast<const ConstraintMax<T>*>(
        this->GetConstraint(ConstraintType::Max));
    return mmc ? mmc->limit_.value : (std::numeric_limits<T>::max)();
  }
};

// Property definition of Integer type.
class IntPropType : public NumericPropTypeBase<IntPropType, IntValue, int> {
 public:
  // Overrides from the PropType base class.
  IntPropType* GetInt() override { return this; }
  IntPropType const* GetInt() const override { return this; }
};

// Property definition of Number type.
class DoublePropType
    : public NumericPropTypeBase<DoublePropType, DoubleValue, double> {
 public:
  // Overrides from the PropType base class.
  DoublePropType* GetDouble() override { return this; }
  DoublePropType const* GetDouble() const override { return this; }
};

// Property definition of String type.
class StringPropType
    : public PropTypeBase<StringPropType, StringValue, std::string> {
 public:
  using Base = PropTypeBase<StringPropType, StringValue, std::string>;
  // Overrides from the PropType base class.
  StringPropType* GetString() override { return this; }
  StringPropType const* GetString() const override { return this; }

  bool ConstraintsFromJson(const base::DictionaryValue* value,
                           std::set<std::string>* processed_keys,
                           ErrorPtr* error) override;

  // Helper methods to add and inspect simple constraints.
  // Used mostly for unit testing.
  void AddLengthConstraint(int min_len, int max_len);
  int GetMinLength() const;
  int GetMaxLength() const;
};

// Property definition of Boolean type.
class BooleanPropType
    : public PropTypeBase<BooleanPropType, BooleanValue, bool> {
 public:
  // Overrides from the PropType base class.
  BooleanPropType* GetBoolean() override { return this; }
  BooleanPropType const* GetBoolean() const override { return this; }
};

// Parameter definition of Object type.
class ObjectPropType
    : public PropTypeBase<ObjectPropType, ObjectValue, ValueMap> {
 public:
  using Base = PropTypeBase<ObjectPropType, ObjectValue, ValueMap>;
  ObjectPropType();

  // Overrides from the ParamType base class.
  bool HasOverriddenAttributes() const override;

  ObjectPropType* GetObject() override { return this; }
  ObjectPropType const* GetObject() const override { return this; }

  std::unique_ptr<PropType> Clone() const override;

  std::unique_ptr<base::Value> ToJson(bool full_schema,
                                      bool in_command_def) const override;
  bool ObjectSchemaFromJson(const base::DictionaryValue* value,
                            const PropType* base_schema,
                            std::set<std::string>* processed_keys,
                            ErrorPtr* error) override;

  // Returns a schema for Object-type parameter.
  inline const ObjectSchema* GetObjectSchemaPtr() const {
    return object_schema_.value.get();
  }
  void SetObjectSchema(std::unique_ptr<const ObjectSchema> schema);

 private:
  InheritableAttribute<std::unique_ptr<const ObjectSchema>> object_schema_;
};

// Parameter definition of Array type.
class ArrayPropType
    : public PropTypeBase<ArrayPropType, ArrayValue, ValueVector> {
 public:
  using Base = PropTypeBase<ArrayPropType, ArrayValue, ValueVector>;
  ArrayPropType();

  // Overrides from the ParamType base class.
  bool HasOverriddenAttributes() const override;

  ArrayPropType* GetArray() override { return this; }
  ArrayPropType const* GetArray() const override { return this; }

  std::unique_ptr<PropType> Clone() const override;

  std::unique_ptr<base::Value> ToJson(bool full_schema,
                                      bool in_command_def) const override;

  bool ObjectSchemaFromJson(const base::DictionaryValue* value,
                            const PropType* base_schema,
                            std::set<std::string>* processed_keys,
                            ErrorPtr* error) override;

  // Returns a type for Array elements.
  inline const PropType* GetItemTypePtr() const {
    return item_type_.value.get();
  }
  void SetItemType(std::unique_ptr<const PropType> item_type);

 private:
  InheritableAttribute<std::unique_ptr<const PropType>> item_type_;
};

}  // namespace weave

#endif  // LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_
