// Copyright 2018 The Fuchsia 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 SRC_LIB_CALLBACK_AUTO_CLEANABLE_H_
#define SRC_LIB_CALLBACK_AUTO_CLEANABLE_H_

#include <lib/async/default.h>
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>

#include <functional>
#include <map>
#include <unordered_set>
#include <utility>

#include "src/lib/callback/scoped_task_runner.h"

namespace callback {

// List that will delete its elements when they call their on_discardable.
// The elements must have a setter method:
// |void SetOnDiscardable(fit::closure on_discardable)|
// and another to check whether they can be discarded:
// |bool IsDiscardable()|.
template <typename V>
class AutoCleanableSet {
 public:
  class ReferenceEquality {
   public:
    bool operator()(const V& v1, const V& v2) const { return &v1 == &v2; }
  };

  class ReferenceHash {
   public:
    uintptr_t operator()(const V& v) const { return reinterpret_cast<uintptr_t>(&v); }
  };

  using Set_ = typename std::unordered_set<V, ReferenceHash, ReferenceEquality>;
  class iterator : public std::iterator<std::forward_iterator_tag, V> {
   public:
    explicit iterator(typename Set_::iterator base) : base_(base) {}

    iterator& operator++() {
      ++base_;
      return *this;
    }

    iterator operator++(int) {
      iterator result(base_);
      operator++();
      return result;
    }

    bool operator==(const iterator& rhs) const { return base_ == rhs.base_; }
    bool operator!=(const iterator& rhs) const { return base_ != rhs.base_; }
    // This set uses the reference of the object (and not its contents) to
    // define object equality. Thus, calling non-const methods on the stored
    // objects does not change their hash, and they are safe to use.
    V& operator*() const { return const_cast<V&>(*(base_)); }
    V* operator->() const { return const_cast<V*>(base_.operator->()); }

   private:
    typename Set_::iterator base_;
  };

  AutoCleanableSet(async_dispatcher_t* dispatcher) : task_runner_(dispatcher) {}
  AutoCleanableSet(const AutoCleanableSet<V>& other) = delete;
  ~AutoCleanableSet() {}

  AutoCleanableSet<V>& operator=(const AutoCleanableSet<V>& other) = delete;

  // Capacity methods.
  size_t size() const { return set_.size(); }
  bool empty() const { return set_.empty(); }

  void clear() {
    task_runner_.Reset();
    set_.clear();
  }

  template <class... Args>
  V& emplace(Args&&... args) {
    auto pair = set_.emplace(std::forward<Args>(args)...);
    FX_DCHECK(pair.second);
    // Set iterators are const because modifying the element would change the
    // hash. In this particular case, this is safe because this set uses
    // reference equality.
    V& item = const_cast<V&>(*(pair.first));
    item.SetOnDiscardable([this, &item] {
      task_runner_.PostTask([this, &item] {
        auto it = set_.find(item);
        if (it == set_.end() || !it->IsDiscardable()) {
          return;
        }
        set_.erase(it);
        CheckDiscardable();
      });
    });
    return item;
  }

  iterator begin() { return iterator(set_.begin()); }

  iterator end() { return iterator(set_.end()); }

  void SetOnDiscardable(fit::closure on_discardable) {
    on_discardable_ = std::move(on_discardable);
  }

  bool IsDiscardable() const { return empty(); }

 private:
  static bool Equals(const V& v1, const V& v2) { return v1 == v2; };

  static std::size_t Hash(const V& v1) { return &v1; };

  void CheckDiscardable() {
    if (IsDiscardable() && on_discardable_)
      on_discardable_();
  }

  Set_ set_;
  fit::closure on_discardable_;

  // Must be the last member of the class.
  ScopedTaskRunner task_runner_;
};

// Map that will delete its elements when they call their on_discardable.
// The elements must have a setter method:
// |void SetOnDiscardable(fit::closure on_discardable)|
// and another to check whether they can be discarded:
// |bool IsDiscardable()|.
template <typename K, typename V, typename Compare = std::less<K>>
class AutoCleanableMap {
 public:
  using Map_ = typename std::map<K, V, Compare>;
  using iterator = typename Map_::iterator;
  using const_iterator = typename Map_::const_iterator;

  AutoCleanableMap(async_dispatcher_t* dispatcher) : task_runner_(dispatcher) {}
  AutoCleanableMap(const AutoCleanableMap<K, V, Compare>& other) = delete;
  ~AutoCleanableMap() {}

  AutoCleanableMap<K, V, Compare>& operator=(const AutoCleanableMap<K, V, Compare>& other) = delete;

  template <typename Key, typename... Args>
  std::pair<iterator, bool> try_emplace(Key&& key, Args&&... args) {
    auto result = map_.try_emplace(std::forward<Key>(key), std::forward<Args>(args)...);
    if (result.second) {
      auto& key = result.first->first;
      auto& value = result.first->second;
      value.SetOnDiscardable([this, key]() {
        task_runner_.PostTask([this, key] {
          auto it = map_.find(key);
          if (it != map_.end() && it->second.IsDiscardable()) {
            map_.erase(it);
          }
          CheckDiscardable();
        });
      });
    }
    return result;
  }

  template <typename... Args>
  std::pair<iterator, bool> emplace(Args&&... args) {
    auto result = map_.emplace(std::forward<Args>(args)...);
    if (result.second) {
      auto& key = result.first->first;
      auto& value = result.first->second;
      value.SetOnDiscardable([this, key] {
        task_runner_.PostTask([this, key] {
          auto it = map_.find(key);
          if (it == map_.end() || !it->second.IsDiscardable()) {
            return;
          }
          map_.erase(it);
          CheckDiscardable();
        });
      });
    }
    return result;
  }

  void erase(iterator pos) {
    map_.erase(pos);
    CheckDiscardable();
  }

  template <class KR>
  iterator find(const KR& x) {
    return map_.find(x);
  }

  template <class KR>
  const_iterator find(const KR& x) const {
    return map_.find(x);
  }

  iterator begin() { return map_.begin(); }

  const_iterator begin() const { return map_.begin(); }

  iterator end() { return map_.end(); }

  const_iterator end() const { return map_.end(); }

  void SetOnDiscardable(fit::closure on_discardable) {
    on_discardable_ = std::move(on_discardable);
  }

  bool IsDiscardable() const { return empty(); }

  size_t size() const { return map_.size(); }

  bool empty() const { return map_.empty(); }

  void clear() {
    task_runner_.Reset();
    map_.clear();
  }

 private:
  void CheckDiscardable() {
    if (IsDiscardable() && on_discardable_) {
      on_discardable_();
    }
  }

  Map_ map_;
  fit::closure on_discardable_;

  // Must be the last member of the class.
  ScopedTaskRunner task_runner_;
};

}  // namespace callback

#endif  // SRC_LIB_CALLBACK_AUTO_CLEANABLE_H_
