/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#ifndef QUICKSTEP_PARSER_PARSE_INDEX_PROPERTIES_HPP_
#define QUICKSTEP_PARSER_PARSE_INDEX_PROPERTIES_HPP_

#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>

#include "parser/ParseKeyValue.hpp"
#include "parser/ParseString.hpp"
#include "parser/ParseTreeNode.hpp"
#include "storage/StorageBlockLayout.pb.h"
#include "utility/Macros.hpp"
#include "utility/PtrList.hpp"
#include "utility/StringUtil.hpp"

#include "glog/logging.h"

namespace quickstep {
/** \addtogroup Parser
 *  @{
 */

/**
 * @brief Base class for different types of indices and their associated properties
 */
class IndexProperties {
 public:
  typedef std::unordered_map<const char*, ParseKeyValue::KeyValueType> valid_property_map_type;

  // An enum specifying the reason for an invalid index description, if any.
  enum class InvalidIndexType {
    kNone = 0,
    kUnimplemented,
    kDuplicateKey,
    kInvalidKey,
    kInvalidValue,
    kTypeIsNotString,
    kSizeIsFloat,
    kSizeIsNegative,
    kNumHashesIsFloat,
    kNumHashesIsNegative,
    kProjectedCountIsFloat,
    kProjectedCountIsNegative
  };

  /**
   * @brief Constructor.
   * @note The constructor takes ownership of index_sub_block_description.
   *
   * @param index_sub_block_description A pointer to an IndexSubBlockDescription proto object.
   * @param invalid_index_type An enum describing the validity of index.
   * @param invalid_property_node A pointer to an invalid ParseKeyValue node, if any.
   **/
  IndexProperties(IndexSubBlockDescription *index_sub_block_description,
                  const InvalidIndexType invalid_index_type = InvalidIndexType::kNone,
                  const ParseKeyValue *invalid_property_node = nullptr)
      : index_sub_block_description_(index_sub_block_description),
        invalid_index_type_(invalid_index_type),
        invalid_property_node_(invalid_property_node) {
  }

  /**
   * @brief Virtual Destructor
   */
  virtual ~IndexProperties() {
  }

  /**
   * @brief Returns printable string that specifies reason for invalid index instance.
   *
   * @return The string describing the reason for invalid index
   **/
  virtual std::string getReasonForInvalidIndexDescription() const = 0;

  /**
   * @brief Modifies the index description given a set of custom properties
   *        specified as a key-value list of properties.
   *
   * @param key_value_list Key Value list of custom properties.
   * @return Returns true if the given set of custom properties was valid
   *         and was applied correctly, otherwise returns false.
   **/
  virtual bool addCustomProperties(const PtrList<ParseKeyValue> *key_value_list) = 0;

  /**
   * @brief Checks whether this instance describes a valid index or not.
   *
   * @return True if index description is valid, false otherwise.
   **/
  bool isIndexPropertyValid() const {
    return invalid_index_type_ == InvalidIndexType::kNone;
  }

  /**
   * @brief Returns the parse node corresponding for invalid index instance, if any.
   *
   * @return The parse node.
   **/
  const ParseKeyValue* getInvalidPropertyNode() const {
    return invalid_property_node_;
  }

  /**
   * @brief Returns a protobuf object representing the index description.
   *
   * @return An IndexSubBlockDescription object.
   **/
  const IndexSubBlockDescription* getIndexDescription() const {
    return index_sub_block_description_.get();
  }

  /**
   * @brief A helper function that checks whether the given list of custom properties
   *        contains duplicate keys or not.
   *
   * @param key_value_list Key Value list of custom properties.
   * @param invalid_node Double pointer to an invalid node that is used to store duplicate node, if any.
   * @return Returns true if the given set of custom properties contains duplicate
   *         keys, otherwise returns false.
   **/
  bool hasDuplicateCustomProperty(const PtrList<ParseKeyValue> *key_value_list, const ParseKeyValue **invalid_node) {
    // Define an existence map, which checks for duplicate properties in the key_value_list.
    std::unordered_map<std::string, bool> is_duplicate_property;
    for (const ParseKeyValue &key_value : *key_value_list) {
      const std::string key = ToLower(key_value.key()->value());
      if (is_duplicate_property.find(key) != is_duplicate_property.end()) {
        *invalid_node = &key_value;
        return true;  // duplicate found, return true.
      } else {
        is_duplicate_property[key] = true;
      }
    }
    return false;  // no duplicates, return false.
  }

 protected:
  std::unique_ptr<IndexSubBlockDescription> index_sub_block_description_;
  InvalidIndexType invalid_index_type_;
  const ParseKeyValue *invalid_property_node_;  // referred object owned by ParseIndexProperties class.

  /**
   * @brief A setter function that be used to invalidate the index.
   *
   * @param invalid_index_type An enum corresponding to the reason, which invalidated the index.
   * @param invalid_property_node Pointer to the node, which may have caused invalidation.
   **/
  void setIndexDescriptionAsInvalid(const InvalidIndexType invalid_index_type,
                                    const ParseKeyValue *invalid_property_node) {
    invalid_index_type_ = invalid_index_type;
    invalid_property_node_ = invalid_property_node;
    index_sub_block_description_.reset();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IndexProperties);
};

/**
 * @brief Implementation of index properties for a BitWeaving Index (H or V).
 */
class BitWeavingIndexProperties : public IndexProperties {
 public:
  static const char *kBitWeavingType;  // is of type string.

  /**
   * @brief Constructor.
   **/
  BitWeavingIndexProperties()
    : IndexProperties(new IndexSubBlockDescription()) {
    // Default to BITWEAVING_V, custom properties can change this to H.
    index_sub_block_description_->set_sub_block_type(IndexSubBlockDescription::BITWEAVING_V);
  }

  ~BitWeavingIndexProperties() override {
  }

  std::string getReasonForInvalidIndexDescription() const override {
    switch (invalid_index_type_) {
      case InvalidIndexType::kNone:
        return "";
      case InvalidIndexType::kDuplicateKey:  // Fall through.
      case InvalidIndexType::kInvalidKey:
        return "The only valid property for BitWeaving is TYPE.";
      case InvalidIndexType::kTypeIsNotString:  // Fall through.
      case InvalidIndexType::kInvalidValue:
        return "The only valid values for TYPE are V or H.";
      default:
        return "Unknown reason";
    }
  }

  bool addCustomProperties(const PtrList<ParseKeyValue> *key_value_list) override {
    if (key_value_list->size() == 0u) {
      // No properties specified.
      return true;
    } else if (key_value_list->size() == 1u) {
      const ParseKeyValue &key_value = *key_value_list->begin();
      if (key_value.getKeyValueType() != ParseKeyValue::KeyValueType::kStringString) {
        setIndexDescriptionAsInvalid(InvalidIndexType::kTypeIsNotString, &key_value);
        return false;
      }
      const std::string key = ToLower(key_value.key()->value());
      const std::string value = ToLower(
          static_cast<const ParseKeyStringValue&>(key_value).value()->value());
      if (key.compare(kBitWeavingType) == 0) {
        if (value.compare("h") == 0) {
          index_sub_block_description_->set_sub_block_type(IndexSubBlockDescription::BITWEAVING_H);
          return true;
        } else if (value.compare("v") != 0) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kInvalidValue, &key_value);
          return false;
        } else {
          // If V was specified, then we do nothing because it's set to V by default.
          return true;
        }
      } else {
        // Incorrect key specified.
        setIndexDescriptionAsInvalid(InvalidIndexType::kInvalidKey, &key_value);
        return false;
      }
    } else {
      // More than one key. This must be an error.
      invalid_index_type_ = InvalidIndexType::kDuplicateKey;
      return false;
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BitWeavingIndexProperties);
};

/**
 * @brief Implementation of index properties for Bloom Filter Index
 */
class BloomFilterIndexProperties : public IndexProperties {
 public:
  // Index properties associated with this index.

  static const char *kBloomFilterSizeInBytes;    // is of type integer
  static const char *kBloomFilterNumHashes;      // is of type integer
  static const char *kBloomFilterProjectElementCount;  // is of type integer

  /**
   * @brief Constructor.
   **/
  BloomFilterIndexProperties()
      : IndexProperties(new IndexSubBlockDescription()) {
    index_sub_block_description_->set_sub_block_type(IndexSubBlockDescription::BLOOM_FILTER);

    // Initialize the valid_property_map_ for this index with appropriate type for each property.
    valid_property_map_[kBloomFilterSizeInBytes] = ParseKeyValue::KeyValueType::kStringInteger;
    valid_property_map_[kBloomFilterNumHashes] = ParseKeyValue::KeyValueType::kStringInteger;
    valid_property_map_[kBloomFilterProjectElementCount] = ParseKeyValue::KeyValueType::kStringInteger;
  }

  ~BloomFilterIndexProperties() override {
  }

  std::string getReasonForInvalidIndexDescription() const override {
    switch (invalid_index_type_) {
      case InvalidIndexType::kNone:
        return "";
      case InvalidIndexType::kUnimplemented:
        return "Bloom Filter index is not yet implemented";
      case InvalidIndexType::kDuplicateKey:
        return "Index property is specified more than once";
      case InvalidIndexType::kInvalidKey:
        return "Invalid property for this index";
      case InvalidIndexType::kSizeIsFloat:
        return "Size cannot be specified as a float";
      case InvalidIndexType::kSizeIsNegative:
        return "Size cannot be negative";
      case InvalidIndexType::kNumHashesIsFloat:
        return "Num_hashes cannot be specified as a float";
      case InvalidIndexType::kNumHashesIsNegative:
        return "Num_hashes cannot be negative";
      case InvalidIndexType::kProjectedCountIsFloat:
        return "Projected_element_count cannot be specified as a float";
      case InvalidIndexType::kProjectedCountIsNegative:
        return "Projected_element_count cannot be negative";
      default:
        return "Unknown reason";
    }
  }

  bool addCustomProperties(const PtrList<ParseKeyValue> *key_value_list) override {
    // If the index is unimplemented, skip adding the custom properties.
    if (invalid_index_type_ == InvalidIndexType::kUnimplemented) {
      return false;
    }

    // Verify for duplicates, if any.
    if (hasDuplicateCustomProperty(key_value_list, &invalid_property_node_)) {
      invalid_index_type_ = InvalidIndexType::kDuplicateKey;
      return false;
    }

    for (const ParseKeyValue &key_value : *key_value_list) {
      const std::string key = ToLower(key_value.key()->value());
      if (key.compare(kBloomFilterSizeInBytes) == 0) {
        const ParseKeyIntegerValue *key_integer_value = static_cast<const ParseKeyIntegerValue*>(&key_value);
        if (key_integer_value->value()->float_like()) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kSizeIsFloat, &key_value);
          return false;
        }
        const std::int64_t bloom_filter_size = key_integer_value->value()->long_value();
        if (bloom_filter_size < 0) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kSizeIsNegative, &key_value);
          return false;
        }
        // All good! allow the default bloom filter size to be modified.
        index_sub_block_description_->SetExtension(BloomFilterIndexSubBlockDescription::bloom_filter_size,
                                                   bloom_filter_size);
      } else if (key.compare(kBloomFilterNumHashes) == 0) {
        const ParseKeyIntegerValue *key_integer_value = static_cast<const ParseKeyIntegerValue*>(&key_value);
        if (key_integer_value->value()->float_like()) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kNumHashesIsFloat, &key_value);
          return false;
        }
        const std::int64_t number_of_hashes = key_integer_value->value()->long_value();
        if (number_of_hashes < 0) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kNumHashesIsNegative, &key_value);
          return false;
        }
        // All good! allow the default num_hashes to be modified.
        index_sub_block_description_->SetExtension(BloomFilterIndexSubBlockDescription::number_of_hashes,
                                                   number_of_hashes);
      } else if (key.compare(kBloomFilterProjectElementCount) == 0) {
        const ParseKeyIntegerValue *key_integer_value = static_cast<const ParseKeyIntegerValue*>(&key_value);
        if (key_integer_value->value()->float_like()) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kProjectedCountIsFloat, &key_value);
          return false;
        }
        const std::int64_t projected_element_count = key_integer_value->value()->long_value();
        if (projected_element_count < 0) {
          setIndexDescriptionAsInvalid(InvalidIndexType::kProjectedCountIsNegative, &key_value);
          return false;
        }
        // All good! allow the default projected_element_count to be modified.
        index_sub_block_description_->SetExtension(BloomFilterIndexSubBlockDescription::projected_element_count,
                                                   projected_element_count);
      } else {
        // None of the defined properties matched, this is an invalid property for this index.
        setIndexDescriptionAsInvalid(InvalidIndexType::kInvalidKey, &key_value);
        return false;
      }
    }
    invalid_index_type_ = InvalidIndexType::kNone;
    invalid_property_node_ = nullptr;
    return true;
  }

 private:
  // A map of index property constants and their associated type.
  valid_property_map_type valid_property_map_;

  DISALLOW_COPY_AND_ASSIGN(BloomFilterIndexProperties);
};

/**
 * @brief Implementation of index properties for CSB Tree Index.
 */
class CSBTreeIndexProperties : public IndexProperties {
 public:
  /**
   * @brief Constructor.
   **/
  CSBTreeIndexProperties()
    : IndexProperties(new IndexSubBlockDescription()) {
    index_sub_block_description_->set_sub_block_type(IndexSubBlockDescription::CSB_TREE);
  }

  ~CSBTreeIndexProperties() override {
  }

  std::string getReasonForInvalidIndexDescription() const override {
    switch (invalid_index_type_) {
      case InvalidIndexType::kNone:
        return "";
      case InvalidIndexType::kUnimplemented:
        return "CSB Tree index is not yet implemented";
      case InvalidIndexType::kInvalidKey:
        return "CSB Tree index does not define index properties";
      default:
        return "Unknown reason";
    }
  }

  bool addCustomProperties(const PtrList<ParseKeyValue> *key_value_list) override {
    // CSBTreeIndex does not define any additional index property,
    // so a call to this function will invalidate the index.
    invalid_index_type_ = InvalidIndexType::kInvalidKey;
    invalid_property_node_ = nullptr;
    index_sub_block_description_.reset();
    return false;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(CSBTreeIndexProperties);
};

/**
 * @brief Implementation of index properties for SMA Index.
 */
class SMAIndexProperties : public IndexProperties {
 public:
  /**
   * @brief Constructor.
   */
  SMAIndexProperties() : IndexProperties(new IndexSubBlockDescription()) {
    index_sub_block_description_->set_sub_block_type(IndexSubBlockDescription::SMA);
  }

  ~SMAIndexProperties() override {
  }

  std::string getReasonForInvalidIndexDescription() const override {
    switch (invalid_index_type_) {
      case InvalidIndexType::kNone:
        return "";
      case InvalidIndexType::kInvalidKey:
        return "SMA index does not define index properties";
      default:
        return "Unknown reason";
    }
  }

  bool addCustomProperties(const PtrList<ParseKeyValue> *key_value_list) override {
    // SMA does not define any index properties, so calling this function
    // will invalidate the index.
    invalid_index_type_ = InvalidIndexType::kInvalidKey;
    invalid_property_node_ = nullptr;
    index_sub_block_description_.reset();
    return false;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(SMAIndexProperties);
};

/**
 * @brief Encapsulates the IndexProperties key-value list. Makes the job
 *        of resolving IndexProperties easy.
 */
class ParseIndexProperties : public ParseTreeNode {
 public:
  /**
   * @brief Constructor.
   *
   * @param line_number Beginning line number.
   * @param column_number Beginning column number.
   * @param properties PtrList to the KeyValues.
   */
  ParseIndexProperties(const int line_number,
                       const int column_number,
                       PtrList<ParseKeyValue> *key_value_list)
      : ParseTreeNode(line_number, column_number),
        key_value_list_(key_value_list) {
  }

  std::string getName() const override { return "IndexProperties"; }

  const PtrList<ParseKeyValue>* getKeyValueList() const {
    return key_value_list_.get();
  }

 protected:
  void getFieldStringItems(
      std::vector<std::string> *inline_field_names,
      std::vector<std::string> *inline_field_values,
      std::vector<std::string> *non_container_child_field_names,
      std::vector<const ParseTreeNode*> *non_container_child_fields,
      std::vector<std::string> *container_child_field_names,
      std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
    for (const ParseKeyValue &index_property : *key_value_list_) {
      non_container_child_field_names->push_back("index_property");
      non_container_child_fields->push_back(&index_property);
    }
  }

 private:
  std::unique_ptr<PtrList<ParseKeyValue>> key_value_list_;

  DISALLOW_COPY_AND_ASSIGN(ParseIndexProperties);
};

/** @} */

}  // namespace quickstep

#endif  // QUICKSTEP_PARSER_PARSE_INDEX_PROPERTIES_HPP_
