/*
 * Copyright (C) 2013 Google, Inc. All rights reserved.
 * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
 */

#pragma once

#include <wtf/GetPtr.h>
#include <wtf/HashTraits.h>
#include <wtf/Threading.h>
#include <wtf/TypeCasts.h>

namespace WTF {

template<typename, typename> class WeakHashSet;
template<typename, typename> class WeakPtrFactory;

struct EmptyCounter {
    static void increment() { }
    static void decrement() { }
};

enum class EnableWeakPtrThreadingAssertions : bool { No, Yes };

template<typename Counter = EmptyCounter> class WeakPtrImpl : public ThreadSafeRefCounted<WeakPtrImpl<Counter>> {
    WTF_MAKE_NONCOPYABLE(WeakPtrImpl);
    WTF_MAKE_FAST_ALLOCATED;
public:
    template<typename T> static Ref<WeakPtrImpl> create(T* ptr)
    {
        return adoptRef(*new WeakPtrImpl(ptr));
    }

    ~WeakPtrImpl()
    {
        Counter::decrement();
    }

    template<typename T> typename T::WeakValueType* get()
    {
        return static_cast<typename T::WeakValueType*>(m_ptr);
    }

    explicit operator bool() const { return m_ptr; }
    void clear() { m_ptr = nullptr; }

#if ASSERT_ENABLED
    bool wasConstructedOnMainThread() const { return m_wasConstructedOnMainThread; }
#endif

private:
    template<typename T> explicit WeakPtrImpl(T* ptr)
        : m_ptr(static_cast<typename T::WeakValueType*>(ptr))
#if ASSERT_ENABLED
        , m_wasConstructedOnMainThread(isMainThread())
#endif
    {
        Counter::increment();
    }

    void* m_ptr;
#if ASSERT_ENABLED
    bool m_wasConstructedOnMainThread;
#endif
};

template<typename Counter> struct HashTraits<Ref<WeakPtrImpl<Counter>>> : RefHashTraits<WeakPtrImpl<Counter>> {
    static constexpr bool hasIsReleasedWeakValueFunction = true;
    static bool isReleasedWeakValue(const Ref<WeakPtrImpl<Counter>>& value)
    {
        return !value.isHashTableDeletedValue() && !value.isHashTableEmptyValue() && !value.get();
    }
};

template<typename T, typename Counter> class WeakPtr {
    WTF_MAKE_FAST_ALLOCATED;
public:
    WeakPtr() { }
    WeakPtr(std::nullptr_t) { }
    template<typename U> WeakPtr(const WeakPtr<U, Counter>&);
    template<typename U> WeakPtr(WeakPtr<U, Counter>&&);

    template<typename = std::enable_if_t<!IsSmartPtr<T>::value>> WeakPtr(const T* object, EnableWeakPtrThreadingAssertions shouldEnableAssertions = EnableWeakPtrThreadingAssertions::Yes)
        : m_impl(object ? implForObject(*object) : nullptr)
#if ASSERT_ENABLED
        , m_shouldEnableAssertions(shouldEnableAssertions == EnableWeakPtrThreadingAssertions::Yes)
#endif
    {
        UNUSED_PARAM(shouldEnableAssertions);
        ASSERT(!object || object == m_impl->template get<T>());
    }

    template<typename = std::enable_if_t<!IsSmartPtr<T>::value && !std::is_pointer_v<T>>> WeakPtr(const T& object, EnableWeakPtrThreadingAssertions shouldEnableAssertions = EnableWeakPtrThreadingAssertions::Yes)
        : m_impl(implForObject(object))
#if ASSERT_ENABLED
        , m_shouldEnableAssertions(shouldEnableAssertions == EnableWeakPtrThreadingAssertions::Yes)
#endif
    {
        UNUSED_PARAM(shouldEnableAssertions);
        ASSERT(&object == m_impl->template get<T>());
    }

    template<typename = std::enable_if_t<!IsSmartPtr<T>::value>> WeakPtr(const Ref<T>& object, EnableWeakPtrThreadingAssertions shouldEnableAssertions = EnableWeakPtrThreadingAssertions::Yes)
        : WeakPtr(object.get(), shouldEnableAssertions)
    { }

    template<typename = std::enable_if_t<!IsSmartPtr<T>::value>> WeakPtr(const RefPtr<T>& object, EnableWeakPtrThreadingAssertions shouldEnableAssertions = EnableWeakPtrThreadingAssertions::Yes)
        : WeakPtr(object.get(), shouldEnableAssertions)
    { }

    T* get() const
    {
        // FIXME: Our GC threads currently need to get opaque pointers from WeakPtrs and have to be special-cased.
        ASSERT(!m_impl || !m_shouldEnableAssertions || Thread::mayBeGCThread() || m_impl->wasConstructedOnMainThread() == isMainThread());
        return m_impl ? static_cast<T*>(m_impl->template get<T>()) : nullptr;
    }

    bool operator!() const { return !m_impl || !*m_impl; }
    explicit operator bool() const { return m_impl && *m_impl; }

    WeakPtr& operator=(std::nullptr_t) { m_impl = nullptr; return *this; }
    template<typename U> WeakPtr& operator=(const WeakPtr<U, Counter>&);
    template<typename U> WeakPtr& operator=(WeakPtr<U, Counter>&&);

    T* operator->() const
    {
        ASSERT(!m_impl || !m_shouldEnableAssertions || m_impl->wasConstructedOnMainThread() == isMainThread());
        return get();
    }

    T& operator*() const
    {
        ASSERT(!m_impl || !m_shouldEnableAssertions || m_impl->wasConstructedOnMainThread() == isMainThread());
        return *get();
    }

    void clear() { m_impl = nullptr; }

private:
    template<typename, typename, typename> friend class WeakHashMap;
    template<typename, typename> friend class WeakHashSet;
    template<typename, typename> friend class WeakPtr;
    template<typename, typename> friend class WeakPtrFactory;

    explicit WeakPtr(Ref<WeakPtrImpl<Counter>>&& ref, EnableWeakPtrThreadingAssertions shouldEnableAssertions)
        : m_impl(WTFMove(ref))
#if ASSERT_ENABLED
        , m_shouldEnableAssertions(shouldEnableAssertions == EnableWeakPtrThreadingAssertions::Yes)
#endif
    {
        UNUSED_PARAM(shouldEnableAssertions);
    }

    template<typename U> static WeakPtrImpl<Counter>* implForObject(const U& object)
    {
        object.weakPtrFactory().initializeIfNeeded(object);
        return object.weakPtrFactory().m_impl.get();
    }

    RefPtr<WeakPtrImpl<Counter>> m_impl;
#if ASSERT_ENABLED
    bool m_shouldEnableAssertions { true };
#endif
};

// Note: you probably want to inherit from CanMakeWeakPtr rather than use this directly.
template<typename T, typename Counter = EmptyCounter> class WeakPtrFactory {
    WTF_MAKE_NONCOPYABLE(WeakPtrFactory);
    WTF_MAKE_FAST_ALLOCATED;
public:
    using CounterType = Counter;

    WeakPtrFactory()
#if ASSERT_ENABLED
        : m_wasConstructedOnMainThread(isMainThread())
#endif
    {
    }

    ~WeakPtrFactory()
    {
        if (!m_impl)
            return;
        m_impl->clear();
    }

    void initializeIfNeeded(const T& object) const
    {
        if (m_impl)
            return;

        ASSERT(m_wasConstructedOnMainThread == isMainThread());
        m_impl = WeakPtrImpl<Counter>::create(const_cast<T*>(&object));
    }

    template<typename U> WeakPtr<U, Counter> createWeakPtr(U& object, EnableWeakPtrThreadingAssertions enableWeakPtrThreadingAssertions = EnableWeakPtrThreadingAssertions::Yes) const
    {
        initializeIfNeeded(object);

        ASSERT(&object == m_impl->template get<T>());
        return WeakPtr<U, Counter>(*m_impl, enableWeakPtrThreadingAssertions);
    }

    void revokeAll()
    {
        if (!m_impl)
            return;

        m_impl->clear();
        m_impl = nullptr;
    }

    unsigned weakPtrCount() const { return m_impl ? m_impl->refCount() - 1 : 0; }

#if ASSERT_ENABLED
    bool isInitialized() const { return m_impl; }
#endif

private:
    template<typename, typename> friend class WeakHashSet;
    template<typename, typename, typename> friend class WeakHashMap;
    template<typename, typename> friend class WeakPtr;

    mutable RefPtr<WeakPtrImpl<Counter>> m_impl;
#if ASSERT_ENABLED
    bool m_wasConstructedOnMainThread;
#endif
};

// We use lazy initialization of the WeakPtrFactory by default to avoid unnecessary initialization. Eager
// initialization is however useful if you plan to call construct WeakPtrs from other threads.
enum class WeakPtrFactoryInitialization { Lazy, Eager };

template<typename T, WeakPtrFactoryInitialization initializationMode = WeakPtrFactoryInitialization::Lazy, typename Counter = EmptyCounter> class CanMakeWeakPtr {
public:
    using WeakValueType = T;

    const WeakPtrFactory<T, Counter>& weakPtrFactory() const { return m_weakPtrFactory; }
    WeakPtrFactory<T, Counter>& weakPtrFactory() { return m_weakPtrFactory; }

protected:
    CanMakeWeakPtr()
    {
        if (initializationMode == WeakPtrFactoryInitialization::Eager)
            initializeWeakPtrFactory();
    }

    void initializeWeakPtrFactory()
    {
        m_weakPtrFactory.initializeIfNeeded(static_cast<T&>(*this));
    }

private:
    WeakPtrFactory<T, Counter> m_weakPtrFactory;
};

template<typename T, typename U, typename Counter> inline WeakPtrImpl<Counter>* weak_ptr_impl_cast(WeakPtrImpl<Counter>* impl)
{
    static_assert(std::is_same_v<typename T::WeakValueType, typename U::WeakValueType>, "Invalid weak pointer cast");
    return impl;
}

template<typename T, typename Counter> template<typename U> inline WeakPtr<T, Counter>::WeakPtr(const WeakPtr<U, Counter>& o)
    : m_impl(weak_ptr_impl_cast<T, U>(o.m_impl.get()))
{
}

template<typename T, typename Counter> template<typename U> inline WeakPtr<T, Counter>::WeakPtr(WeakPtr<U, Counter>&& o)
    : m_impl(adoptRef(weak_ptr_impl_cast<T, U>(o.m_impl.leakRef())))
{
}

template<typename T, typename Counter> template<typename U> inline WeakPtr<T, Counter>& WeakPtr<T, Counter>::operator=(const WeakPtr<U, Counter>& o)
{
    m_impl = weak_ptr_impl_cast<T, U>(o.m_impl.get());
    return *this;
}

template<typename T, typename Counter> template<typename U> inline WeakPtr<T, Counter>& WeakPtr<T, Counter>::operator=(WeakPtr<U, Counter>&& o)
{
    m_impl = adoptRef(weak_ptr_impl_cast<T, U>(o.m_impl.leakRef()));
    return *this;
}

template <typename T, typename Counter>
struct GetPtrHelper<WeakPtr<T, Counter>> {
    using PtrType = T*;
    static T* getPtr(const WeakPtr<T, Counter>& p) { return const_cast<T*>(p.get()); }
};

template <typename T, typename Counter>
struct IsSmartPtr<WeakPtr<T, Counter>> {
    static constexpr bool value = true;
};

template<typename ExpectedType, typename ArgType, typename Counter>
inline bool is(WeakPtr<ArgType, Counter>& source)
{
    return is<ExpectedType>(source.get());
}

template<typename ExpectedType, typename ArgType, typename Counter>
inline bool is(const WeakPtr<ArgType, Counter>& source)
{
    return is<ExpectedType>(source.get());
}

template<typename T, typename U, typename Counter> inline bool operator==(const WeakPtr<T, Counter>& a, const WeakPtr<U, Counter>& b)
{
    return a.get() == b.get();
}

template<typename T, typename U, typename Counter> inline bool operator==(const WeakPtr<T, Counter>& a, U* b)
{
    return a.get() == b;
}

template<typename T, typename U, typename Counter> inline bool operator==(T* a, const WeakPtr<U, Counter>& b)
{
    return a == b.get();
}

template<typename T, typename U, typename Counter> inline bool operator!=(const WeakPtr<T, Counter>& a, const WeakPtr<U, Counter>& b)
{
    return a.get() != b.get();
}

template<typename T, typename U, typename Counter> inline bool operator!=(const WeakPtr<T, Counter>& a, U* b)
{
    return a.get() != b;
}

template<typename T, typename U, typename Counter> inline bool operator!=(T* a, const WeakPtr<U, Counter>& b)
{
    return a != b.get();
}

} // namespace WTF

using WTF::CanMakeWeakPtr;
using WTF::EnableWeakPtrThreadingAssertions;
using WTF::WeakPtr;
using WTF::WeakPtrFactory;
using WTF::WeakPtrFactoryInitialization;
