/* Copyright (c) 2015-2016 The Khronos Group Inc.
 * Copyright (c) 2015-2016 Valve Corporation
 * Copyright (c) 2015-2016 LunarG, Inc.
 * Copyright (C) 2015-2016 Google Inc.
 *
 * Licensed 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.
 *
 * Author: John Zulauf <jzulauf@lunarg.com>
 */
#ifndef HASH_UTIL_H_
#define HASH_UTIL_H_

#define NOMINMAX
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <mutex>
#include <type_traits>
#include <unordered_set>
#include <vector>

// Hash and equality utilities for supporting hashing containers (e.g. unordered_set, unordered_map)
namespace hash_util {

// True iff both pointers are null or both are non-null
template <typename T>
bool similar_for_nullity(const T *const lhs, const T *const rhs) {
    return ((lhs != nullptr) && (rhs != nullptr)) || ((lhs == nullptr) && (rhs == nullptr));
}

// Wrap std hash to avoid manual casts for the holes in std::hash (in C++11)
template <typename Value>
size_t HashWithUnderlying(Value value, typename std::enable_if<!std::is_enum<Value>::value, void *>::type = nullptr) {
    return std::hash<Value>()(value);
}

template <typename Value>
size_t HashWithUnderlying(Value value, typename std::enable_if<std::is_enum<Value>::value, void *>::type = nullptr) {
    using Underlying = typename std::underlying_type<Value>::type;
    return std::hash<Underlying>()(static_cast<const Underlying &>(value));
}

class HashCombiner {
   public:
    using Key = size_t;

    template <typename Value>
    struct WrappedHash {
        size_t operator()(const Value &value) const { return HashWithUnderlying(value); }
    };

    HashCombiner(Key combined = 0) : combined_(combined) {}
    // magic and combination algorithm based on boost::hash_combine
    // http://www.boost.org/doc/libs/1_43_0/doc/html/hash/reference.html#boost.hash_combine
    // Magic value is 2^size / ((1-sqrt(5)/2)
    static const uint64_t kMagic = sizeof(Key) > 4 ? Key(0x9e3779b97f4a7c16UL) : Key(0x9e3779b9U);

    // If you need to override the default hash
    template <typename Value, typename Hasher = WrappedHash<Value>>
    HashCombiner &Combine(const Value &value) {
        combined_ ^= Hasher()(value) + kMagic + (combined_ << 6) + (combined_ >> 2);
        return *this;
    }

    template <typename Iterator, typename Hasher = WrappedHash<typename std::iterator_traits<Iterator>::value_type>>
    HashCombiner &Combine(Iterator first, Iterator end) {
        using Value = typename std::iterator_traits<Iterator>::value_type;
        auto current = first;
        for (; current != end; ++current) {
            Combine<Value, Hasher>(*current);
        }
        return *this;
    }

    template <typename Value, typename Hasher = WrappedHash<Value>>
    HashCombiner &Combine(const std::vector<Value> &vector) {
        return Combine(vector.cbegin(), vector.cend());
    }

    template <typename Value>
    HashCombiner &operator<<(const Value &value) {
        return Combine(value);
    }

    Key Value() const { return combined_; }
    void Reset(Key combined = 0) { combined_ = combined; }

   private:
    Key combined_;
};

// A template to inherit std::hash overloads from when T::hash() is defined
template <typename T>
struct HasHashMember {
    size_t operator()(const T &value) const { return value.hash(); }
};

// A template to inherit std::hash overloads from when is an *ordered* constainer
template <typename T>
struct IsOrderedContainer {
    size_t operator()(const T &value) const { return HashCombiner().Combine(value.cbegin(), value.cend()).Value(); }
};

// The dictionary provides a way of referencing canonical/reference
// data by id, such that the id's are invariant with dictionary
// resize/insert and that no entries point to identical data.  This
// approach uses the address of the unique data and as the unique
//  ID  for a give value of T.
//
// Note: This ID is unique for a given application execution, neither
//       globally unique, invariant, nor repeatable from execution to
//       execution.
//
// The entries of the dictionary are shared_pointers (the contents of
// which are invariant with resize/insert), with the hash and equality
// template arguments wrapped in a shared pointer dereferencing
// function object
template <typename T, typename Hasher = std::hash<T>, typename KeyEqual = std::equal_to<T>>
class Dictionary {
   public:
    using Def = T;
    using Id = std::shared_ptr<const Def>;

    // Find the unique entry match the provided value, adding if needed
    // TODO: segregate lookup from insert, using reader/write locks to reduce contention -- if needed
    template <typename U = T>
    Id look_up(U &&value) {
        // We create an Id from the value, which will either be retained by dict (if new) or deleted on return (if extant)
        Id from_input = std::make_shared<T>(std::forward<U>(value));

        // Insert takes care of the "unique" id part by rejecting the insert if a key matching by_value exists, but returning us
        // the Id of the extant shared_pointer(id->def) instead.
        // return the value of the Iterator from the <Iterator, bool> pair returned by insert
        Guard g(lock);  // Dict isn't thread safe, and use is presumed to be multi-threaded
        return *dict.insert(from_input).first;
    }

   private:
    struct HashKeyValue {
        size_t operator()(const Id &value) const { return Hasher()(*value); }
    };
    struct KeyValueEqual {
        bool operator()(const Id &lhs, const Id &rhs) const { return KeyEqual()(*lhs, *rhs); }
    };
    using Dict = std::unordered_set<Id, HashKeyValue, KeyValueEqual>;
    using Lock = std::mutex;
    using Guard = std::lock_guard<Lock>;
    Lock lock;
    Dict dict;
};
}  // namespace hash_util

#endif  // HASH_UTILS_H_
