/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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.
 */

#pragma once

#include <lib/core/CHIPCore.h>

#include <algorithm>
#include <new>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>

#include <lib/core/InPlace.h>

namespace chip {

namespace VariantInternal {

template <std::size_t Index, typename... Ts>
struct VariantCurry;

template <std::size_t Index, typename T, typename... Ts>
struct VariantCurry<Index, T, Ts...>
{
    inline static void Destroy(std::size_t id, void * data)
    {
        if (id == Index)
            reinterpret_cast<T *>(data)->~T();
        else
            VariantCurry<Index + 1, Ts...>::Destroy(id, data);
    }

    inline static void Move(std::size_t that_t, void * that_v, void * this_v)
    {
        if (that_t == Index)
            new (this_v) T(std::move(*reinterpret_cast<T *>(that_v)));
        else
            VariantCurry<Index + 1, Ts...>::Move(that_t, that_v, this_v);
    }

    inline static void Copy(std::size_t that_t, const void * that_v, void * this_v)
    {
        if (that_t == Index)
        {
            new (this_v) T(*reinterpret_cast<const T *>(that_v));
        }
        else
        {
            VariantCurry<Index + 1, Ts...>::Copy(that_t, that_v, this_v);
        }
    }

    inline static bool Equal(std::size_t type_t, const void * that_v, const void * this_v)
    {
        if (type_t == Index)
        {
            return *reinterpret_cast<const T *>(this_v) == *reinterpret_cast<const T *>(that_v);
        }

        return VariantCurry<Index + 1, Ts...>::Equal(type_t, that_v, this_v);
    }
};

template <std::size_t Index>
struct VariantCurry<Index>
{
    inline static void Destroy(std::size_t id, void * data) {}
    inline static void Move(std::size_t that_t, void * that_v, void * this_v) {}
    inline static void Copy(std::size_t that_t, const void * that_v, void * this_v) {}
    inline static bool Equal(std::size_t type_t, const void * that_v, const void * this_v)
    {
        VerifyOrDie(false);
        return false;
    }
};

template <typename T, typename TupleType>
class TupleIndexOfType
{
private:
    template <std::size_t Index>
    static constexpr
        typename std::enable_if<std::is_same<T, typename std::tuple_element<Index, TupleType>::type>::value, std::size_t>::type
        calculate()
    {
        return Index;
    }

    template <std::size_t Index>
    static constexpr
        typename std::enable_if<!std::is_same<T, typename std::tuple_element<Index, TupleType>::type>::value, std::size_t>::type
        calculate()
    {
        return calculate<Index + 1>();
    }

public:
    static constexpr std::size_t value = calculate<0>();
};

} // namespace VariantInternal

/**
 * @brief
 *   Represents a type-safe union. An instance of Variant at any given time either holds a value of one of its
 *   alternative types, or no value.
 *
 *   Example:
 *     struct Type1 {};
 *
 *     struct Type2 {};
 *
 *     Variant<Type1, Type2> v;
 *     v.Set<Type1>(); // v contains Type1
 *     Type1 o1 = v.Get<Type1>();
 */
template <typename... Ts>
struct Variant
{
private:
    static constexpr std::size_t kDataSize    = std::max({ sizeof(Ts)... });
    static constexpr std::size_t kDataAlign   = std::max({ alignof(Ts)... });
    static constexpr std::size_t kInvalidType = SIZE_MAX;

    using Data  = typename std::aligned_storage<kDataSize, kDataAlign>::type;
    using Curry = VariantInternal::VariantCurry<0, Ts...>;

    std::size_t mTypeId;
    Data mData;

public:
    Variant() : mTypeId(kInvalidType) {}

    template <typename T, class... Args>
    constexpr explicit Variant(InPlaceTemplateType<T>, Args &&... args) :
        mTypeId(VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value)
    {
        new (&mData) T(std::forward<Args>(args)...);
    }

    Variant(const Variant<Ts...> & that) : mTypeId(that.mTypeId) { Curry::Copy(that.mTypeId, &that.mData, &mData); }

    Variant(Variant<Ts...> && that) : mTypeId(that.mTypeId)
    {
        Curry::Move(that.mTypeId, &that.mData, &mData);
        Curry::Destroy(that.mTypeId, &that.mData);
        that.mTypeId = kInvalidType;
    }

    Variant<Ts...> & operator=(const Variant<Ts...> & that)
    {
        Curry::Destroy(mTypeId, &mData);
        mTypeId = that.mTypeId;
        Curry::Copy(that.mTypeId, &that.mData, &mData);
        return *this;
    }

    Variant<Ts...> & operator=(Variant<Ts...> && that)
    {
        Curry::Destroy(mTypeId, &mData);
        mTypeId = that.mTypeId;
        Curry::Move(that.mTypeId, &that.mData, &mData);
        Curry::Destroy(that.mTypeId, &that.mData);
        that.mTypeId = kInvalidType;
        return *this;
    }

    bool operator==(const Variant & other) const
    {
        return GetType() == other.GetType() && (!Valid() || Curry::Equal(mTypeId, &other.mData, &mData));
    }

    template <typename T>
    bool Is() const
    {
        return (mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value);
    }

    std::size_t GetType() const { return mTypeId; }

    bool Valid() const { return (mTypeId != kInvalidType); }

    template <typename T, typename... Args>
    static Variant<Ts...> Create(Args &&... args)
    {
        return Variant<Ts...>(InPlaceTemplate<T>, std::forward<Args>(args)...);
    }

    template <typename T, typename... Args>
    void Set(Args &&... args)
    {
        Curry::Destroy(mTypeId, &mData);
        new (&mData) T(std::forward<Args>(args)...);
        mTypeId = VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value;
    }

    template <typename T>
    T & Get()
    {
        VerifyOrDie((mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value));
        return *reinterpret_cast<T *>(&mData);
    }

    template <typename T>
    const T & Get() const
    {
        VerifyOrDie((mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value));
        return *reinterpret_cast<const T *>(&mData);
    }

    ~Variant() { Curry::Destroy(mTypeId, &mData); }
};

} // namespace chip
