// Copyright 2022 The Dawn Authors
//
// 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.

#ifndef SRC_DAWN_NATIVE_CACHEKEY_H_
#define SRC_DAWN_NATIVE_CACHEKEY_H_

#include <bitset>
#include <iostream>
#include <limits>
#include <string>
#include <type_traits>
#include <vector>

#include "dawn/common/TypedInteger.h"
#include "dawn/common/ityp_array.h"

namespace dawn::native {

    // Forward declare classes because of co-dependency.
    class CacheKey;
    class CachedObject;

    // Stream operator for CacheKey for debugging.
    std::ostream& operator<<(std::ostream& os, const CacheKey& key);

    // Overridable serializer struct that should be implemented for cache key serializable
    // types/classes.
    template <typename T, typename SFINAE = void>
    class CacheKeySerializer {
      public:
        static void Serialize(CacheKey* key, const T& t);
    };

    class CacheKey : public std::vector<uint8_t> {
      public:
        using std::vector<uint8_t>::vector;

        enum class Type { ComputePipeline, RenderPipeline, Shader };

        template <typename T>
        CacheKey& Record(const T& t) {
            CacheKeySerializer<T>::Serialize(this, t);
            return *this;
        }
        template <typename T, typename... Args>
        CacheKey& Record(const T& t, const Args&... args) {
            CacheKeySerializer<T>::Serialize(this, t);
            return Record(args...);
        }

        // Records iterables by prepending the number of elements. Some common iterables are have a
        // CacheKeySerializer implemented to avoid needing to split them out when recording, i.e.
        // strings and CacheKeys, but they fundamentally do the same as this function.
        template <typename IterableT>
        CacheKey& RecordIterable(const IterableT& iterable) {
            // Always record the size of generic iterables as a size_t for now.
            Record(static_cast<size_t>(iterable.size()));
            for (auto it = iterable.begin(); it != iterable.end(); ++it) {
                Record(*it);
            }
            return *this;
        }
        template <typename Index, typename Value, size_t Size>
        CacheKey& RecordIterable(const ityp::array<Index, Value, Size>& iterable) {
            Record(static_cast<Index>(iterable.size()));
            for (auto it = iterable.begin(); it != iterable.end(); ++it) {
                Record(*it);
            }
            return *this;
        }
        template <typename Ptr>
        CacheKey& RecordIterable(const Ptr* ptr, size_t n) {
            Record(n);
            for (size_t i = 0; i < n; ++i) {
                Record(ptr[i]);
            }
            return *this;
        }
    };

    // Specialized overload for fundamental types.
    template <typename T>
    class CacheKeySerializer<T, std::enable_if_t<std::is_fundamental_v<T>>> {
      public:
        static void Serialize(CacheKey* key, const T t) {
            const char* it = reinterpret_cast<const char*>(&t);
            key->insert(key->end(), it, (it + sizeof(T)));
        }
    };

    // Specialized overload for bitsets that are smaller than 64.
    template <size_t N>
    class CacheKeySerializer<std::bitset<N>, std::enable_if_t<(N <= 64)>> {
      public:
        static void Serialize(CacheKey* key, const std::bitset<N>& t) {
            key->Record(t.to_ullong());
        }
    };

    // Specialized overload for bitsets since using the built-in to_ullong have a size limit.
    template <size_t N>
    class CacheKeySerializer<std::bitset<N>, std::enable_if_t<(N > 64)>> {
      public:
        static void Serialize(CacheKey* key, const std::bitset<N>& t) {
            // Serializes the bitset into series of uint8_t, along with recording the size.
            static_assert(N > 0);
            key->Record(static_cast<size_t>(N));
            uint8_t value = 0;
            for (size_t i = 0; i < N; i++) {
                value <<= 1;
                // Explicitly convert to numeric since MSVC doesn't like mixing of bools.
                value |= t[i] ? 1 : 0;
                if (i % 8 == 7) {
                    // Whenever we fill an 8 bit value, record it and zero it out.
                    key->Record(value);
                    value = 0;
                }
            }
            // Serialize the last value if we are not a multiple of 8.
            if (N % 8 != 0) {
                key->Record(value);
            }
        }
    };

    // Specialized overload for enums.
    template <typename T>
    class CacheKeySerializer<T, std::enable_if_t<std::is_enum_v<T>>> {
      public:
        static void Serialize(CacheKey* key, const T t) {
            CacheKeySerializer<std::underlying_type_t<T>>::Serialize(
                key, static_cast<std::underlying_type_t<T>>(t));
        }
    };

    // Specialized overload for TypedInteger.
    template <typename Tag, typename Integer>
    class CacheKeySerializer<::detail::TypedIntegerImpl<Tag, Integer>> {
      public:
        static void Serialize(CacheKey* key, const ::detail::TypedIntegerImpl<Tag, Integer> t) {
            CacheKeySerializer<Integer>::Serialize(key, static_cast<Integer>(t));
        }
    };

    // Specialized overload for pointers. Since we are serializing for a cache key, we always
    // serialize via value, not by pointer. To handle nullptr scenarios, we always serialize whether
    // the pointer was nullptr followed by the contents if applicable.
    template <typename T>
    class CacheKeySerializer<T, std::enable_if_t<std::is_pointer_v<T>>> {
      public:
        static void Serialize(CacheKey* key, const T t) {
            key->Record(t == nullptr);
            if (t != nullptr) {
                CacheKeySerializer<std::remove_cv_t<std::remove_pointer_t<T>>>::Serialize(key, *t);
            }
        }
    };

    // Specialized overload for fixed arrays of primitives.
    template <typename T, size_t N>
    class CacheKeySerializer<T[N], std::enable_if_t<std::is_fundamental_v<T>>> {
      public:
        static void Serialize(CacheKey* key, const T (&t)[N]) {
            static_assert(N > 0);
            key->Record(static_cast<size_t>(N));
            const char* it = reinterpret_cast<const char*>(t);
            key->insert(key->end(), it, it + sizeof(t));
        }
    };

    // Specialized overload for fixed arrays of non-primitives.
    template <typename T, size_t N>
    class CacheKeySerializer<T[N], std::enable_if_t<!std::is_fundamental_v<T>>> {
      public:
        static void Serialize(CacheKey* key, const T (&t)[N]) {
            static_assert(N > 0);
            key->Record(static_cast<size_t>(N));
            for (size_t i = 0; i < N; i++) {
                key->Record(t[i]);
            }
        }
    };

    // Specialized overload for CachedObjects.
    template <typename T>
    class CacheKeySerializer<T, std::enable_if_t<std::is_base_of_v<CachedObject, T>>> {
      public:
        static void Serialize(CacheKey* key, const T& t) {
            key->Record(t.GetCacheKey());
        }
    };

}  // namespace dawn::native

#endif  // SRC_DAWN_NATIVE_CACHEKEY_H_
