#pragma once

#ifndef GEODE_SET_H_
#define GEODE_SET_H_

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

#include <unordered_set>

#include <ace/Guard_T.h>
#include <ace/Recursive_Thread_Mutex.h>

#include "NonCopyable.hpp"

namespace apache {
namespace geode {
namespace client {

// A synchronized Set using std::unordered_set<T>

/* adongre
 * CID 28616: Other violation (COPY_WITHOUT_ASSIGN)
 * Class "apache::geode::client::Set<unsigned short>::Iterator" has user-written
 * copyi
 * `constructor "apache::geode::client::Set<unsigned
 * short>::Iterator::Iterator(apache::geode::client::Set<unsigned
 * short>::Iterator const &)" i
 * but no corresponding user-written assignment operator.
 *
 * FIX : Make the class non copyable
 */
template <typename T>
class APACHE_GEODE_EXPORT Set : private NonAssignable {
 public:
  // Iterator for a synchronized Set
  class Iterator {
   private:
    Set<T>& m_set;
    typename std::unordered_set<T>::const_iterator m_iter;

    explicit Iterator(Set<T>& set) : m_set(set) {
      m_set.m_mutex.acquire();
      m_iter = set.m_set.begin();
    }
    // Never defined.
    Iterator();

   public:
    Iterator(const Iterator& other) : m_set(other.m_set) {
      m_set.m_mutex.acquire();
      m_iter = other.m_iter;
    }

    inline const T& next() { return *(m_iter++); }

    inline bool hasNext() const { return (m_iter != m_set.m_set.end()); }

    ~Iterator() { m_set.m_mutex.release(); }

    friend class Set;
  };

  Set() : m_set() {}

  ~Set() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    m_set.clear();
  }

  inline bool insert(const T& key) {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    return m_set.insert(key).second;
  }

  inline bool find(const T& key) const {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    return (m_set.find(key) != m_set.end());
  }

  inline bool erase(const T& key) {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    return (m_set.erase(key) > 0);
  }

  inline size_t size() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    return m_set.size();
  }

  inline void clear() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    m_set.clear();
  }

  inline bool empty() {
    ACE_Guard<ACE_Recursive_Thread_Mutex> _guard(m_mutex);

    return m_set.empty();
  }

  inline Iterator iterator() { return Iterator(*this); }

 private:
  std::unordered_set<T> m_set;
  ACE_Recursive_Thread_Mutex m_mutex;
};
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_SET_H_
