/*
  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 __TEST_SET_HPP__
#define __TEST_SET_HPP__
#include "nullable_value.hpp"
#include "test_utils.hpp"

namespace test { namespace driver {

/**
 * Set wrapped value
 */
template <typename T>
class Set
    : public Collection
    , Comparable<Set<T> > {
public:
  Set()
      : Collection(CASS_COLLECTION_TYPE_SET) {}

  Set(const std::set<T>& set)
      : Collection(CASS_COLLECTION_TYPE_SET, set.size())
      , set_(set) {
    // Create the collection
    for (typename std::set<T>::const_iterator iterator = set.begin(); iterator != set.end();
         ++iterator) {
      T value = *iterator;
      Collection::append<T>(value);
      set_.insert(value);
      primary_sub_type_ = value.value_type();
      secondary_sub_type_ = primary_sub_type_;
    }
  }

  Set(const std::vector<T>& set)
      : Collection(CASS_COLLECTION_TYPE_SET, set.size()) {
    // Create the collection
    for (typename std::vector<T>::const_iterator iterator = set.begin(); iterator < set.end();
         ++iterator) {
      T value = *iterator;
      Collection::append<T>(value);
      set_.insert(value);
      primary_sub_type_ = value.value_type();
      secondary_sub_type_ = primary_sub_type_;
    }
  }

  Set(const CassValue* value)
      : Collection(CASS_COLLECTION_TYPE_SET) {
    initialize(value);
  }

  void append(Collection collection) { Collection::append(collection); }

  std::string cql_type() const {
    std::string cql_type = "set<" + (*set_.begin()).cql_type() + ">";
    return cql_type;
  }

  std::string cql_value() const { return str(); }

  bool is_null() const { return Collection::is_null_; }

  /**
   * Comparison operation for driver value set. This comparison is performed in
   * lexicographical order.
   *
   * @param rhs Right hand side to compare
   * @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
   */
  int compare(const std::set<T>& rhs) const {
    // Ensure they are the same size
    if (set_.size() < rhs.size()) return -1;
    if (set_.size() > rhs.size()) return 1;

    // Iterate and compare (sets are already sorted)
    typename std::set<T>::const_iterator rhs_iterator = rhs.begin();
    for (typename std::set<T>::const_iterator iterator = set_.begin(); iterator != set_.end();
         ++iterator) {
      int comparison = (*iterator).compare(*rhs_iterator);
      if (comparison != 0) return comparison;
      ++rhs_iterator;
    }
    return 0;
  }

  /**
   * Comparison operation for driver value set. This comparison is performed in
   * lexicographical order.
   *
   * @param rhs Right hand side to compare
   * @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
   */
  int compare(const Set& rhs) const { return compare(rhs.set_); }

  void set(Tuple tuple, size_t index) { Collection::set(tuple, index); }

  void set(UserType user_type, const std::string& name) { Collection::set(user_type, name); }

  /**
   * Get the size of the set
   *
   * @return The number of values in the set
   */
  size_t size() const { return set_.size(); }

  void statement_bind(Statement statement, size_t index) {
    if (is_null()) {
      ASSERT_EQ(CASS_OK, cass_statement_bind_null(statement.get(), index));
    } else {
      ASSERT_EQ(CASS_OK, cass_statement_bind_collection(statement.get(), index, get()));
    }
  }

  void statement_bind(Statement statement, const std::string& name) {
    if (is_null()) {
      ASSERT_EQ(CASS_OK, cass_statement_bind_null_by_name(statement.get(), name.c_str()));
    } else {
      ASSERT_EQ(CASS_OK,
                cass_statement_bind_collection_by_name(statement.get(), name.c_str(), get()));
    }
  }

  std::string str() const {
    if (is_null()) {
      return "null";
    } else if (set_.empty()) {
      return "{}";
    } else {
      std::stringstream set_string;
      set_string << "{";
      for (typename std::set<T>::const_iterator iterator = set_.begin(); iterator != set_.end();
           ++iterator) {
        set_string << (*iterator).cql_value();

        // Add a comma separation to the set (unless the last element)
        if (iterator != --set_.end()) {
          set_string << ", ";
        }
      }
      set_string << "}";
      return set_string.str();
    }
  }

  std::set<T> value() const { return set_; }

  CassCollectionType collection_type() const { return collection_type_; }

  CassValueType value_type() const { return primary_sub_type_; }

private:
  /**
   * Values used in the set
   */
  std::set<T> set_;

  void initialize(const CassValue* value) {
    // Call the parent class
    Collection::initialize(value);

    // Add the values to the set
    if (!is_null_) {
      const CassValue* current_value = next();
      while (current_value) {
        set_.insert(T(current_value));
        current_value = next();
      }
    }
  }
};

template <class T>
inline std::ostream& operator<<(std::ostream& os, const Set<T>& set) {
  os << set.cql_value();
  return os;
}

}} // namespace test::driver

#endif // __TEST_SET_HPP__
