// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_
#define SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_

#include <functional>
#include <utility>

#include "src/tint/utils/containers/hashmap_base.h"
#include "src/tint/utils/memory/block_allocator.h"

namespace tint {

/// UniqueAllocator is used to allocate unique instances of the template type `T`.
template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
class UniqueAllocator {
  public:
    /// Iterator is the type returned by begin() and end()
    using Iterator = typename BlockAllocator<T>::ConstIterator;

    /// @param args the arguments used to construct the object.
    /// @return a pointer to an instance of `T` with the provided arguments.
    ///         If an existing instance of `T` has been constructed, then the same
    ///         pointer is returned.
    template <typename TYPE = T, typename... ARGS>
    TYPE* Get(ARGS&&... args) {
        // Create a temporary T instance on the stack so that we can hash it, and use it for
        // equality lookup for the Set. If the item is not found in the set, then we create the
        // persisted instance with the allocator.
        TYPE prototype{args...};
        Key& key = items.Add(&prototype);
        if (key.Value() == &prototype) {
            key = allocator.template Create<TYPE>(std::forward<ARGS>(args)...);
        }
        return static_cast<TYPE*>(key.Value());
    }

    /// @param args the arguments used to create the temporary used for the search.
    /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item
    ///         was not found.
    template <typename TYPE = T, typename... ARGS>
    TYPE* Find(ARGS&&... args) const {
        // Create a temporary T instance on the stack so that we can hash it, and use it for
        // equality lookup for the Set.
        TYPE prototype{std::forward<ARGS>(args)...};
        return static_cast<TYPE*>(items.Get(&prototype));
    }

    /// Wrap sets this allocator to the objects created with the content of `inner`.
    /// The allocator after Wrap is intended to temporarily extend the objects
    /// of an existing immutable UniqueAllocator.
    /// As the copied objects are owned by `inner`, `inner` must not be destructed
    /// or assigned while using this allocator.
    /// @param o the immutable UniqueAlllocator to extend
    void Wrap(const UniqueAllocator<T, HASH, EQUAL>& o) { items = o.items; }

    /// @returns an iterator to the beginning of the types
    Iterator begin() const { return allocator.Objects().begin(); }
    /// @returns an iterator to the end of the types
    Iterator end() const { return allocator.Objects().end(); }

  private:
    /// Comparator is the hashing function used by the Hashset
    struct Hasher {
        /// Hashing function
        /// @param e the entry
        /// @returns the hash of the entry
        size_t operator()(T* e) const { return HASH{}(*e); }
    };

    /// Equality is the equality function used by the Hashset
    struct Equality {
        /// Equality function
        /// @param a the first entry to compare
        /// @param b the second entry to compare
        /// @returns true if the two entries are equal
        bool operator()(T* a, T* b) const { return EQUAL{}(*a, *b); }
    };

    /// The maximum capacity of Set before it performs heap allocations.
    static constexpr size_t kFixedSize = 32;

    /// The key type of Set.
    using Key = HashmapKey<T*, Hasher, Equality>;

    /// A custom Hashset implementation that allows keys to be modified.
    class Set : public HashmapBase<Key, kFixedSize> {
      public:
        Key& Add(T* key) {
            auto idx = this->EditAt(key);
            if (!idx.entry) {
                idx.Insert(std::forward<T*>(key));
            }
            return *idx.entry;
        }

        T* Get(T* key) const {
            if (auto* entry = this->GetEntry(key)) {
                return *entry;
            }
            return nullptr;
        }
    };

    /// The block allocator used to allocate the unique objects
    BlockAllocator<T> allocator;
    /// The set of unique item entries
    Set items;
};

}  // namespace tint

#endif  // SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_
