/*
 * Copyright (C) 2013 Google, Inc. All Rights Reserved.
 * Copyright (C) 2015, 2017 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/Noncopyable.h>
#include <wtf/Ref.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Threading.h>

namespace WTF {

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

// Note: WeakReference is an implementation detail, and should not be used directly.
template<typename T>
class WeakReference : public ThreadSafeRefCounted<WeakReference<T>> {
    WTF_MAKE_NONCOPYABLE(WeakReference<T>);
    WTF_MAKE_FAST_ALLOCATED;
public:
    ~WeakReference() { } // So that we can use a template specialization for testing purposes to detect leaks.

    T* get() const { return m_ptr; }

    void clear() { m_ptr = nullptr; }

private:
    friend class WeakPtr<T>;
    friend class WeakPtrFactory<T>;

    static Ref<WeakReference<T>> create(T* ptr) { return adoptRef(*new WeakReference(ptr)); }

    explicit WeakReference(T* ptr)
        : m_ptr(ptr)
    {
    }

    T* m_ptr;
};

template<typename T>
class WeakPtr {
    WTF_MAKE_FAST_ALLOCATED;
public:
    WeakPtr() { }
    WeakPtr(std::nullptr_t) { }
    WeakPtr(Ref<WeakReference<T>>&& ref) : m_ref(std::forward<Ref<WeakReference<T>>>(ref)) { }
    template<typename U> WeakPtr(const WeakPtr<U>&);
    template<typename U> WeakPtr(WeakPtr<U>&&);

    T* get() const { return m_ref ? m_ref->get() : nullptr; }
    explicit operator bool() const { return m_ref && m_ref->get(); }

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

    T* operator->() const { return m_ref->get(); }
    T& operator*() const { return *m_ref->get(); }

    void clear() { m_ref = nullptr; }

private:
    template<typename> friend class WeakHashSet;
    template<typename> friend class WeakPtr;
    template<typename U> friend WeakPtr<U> makeWeakPtr(U&);

    RefPtr<WeakReference<T>> m_ref;
};

// Note: you probably want to inherit from CanMakeWeakPtr rather than use this directly.
template<typename T>
class WeakPtrFactory {
    WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>);
    WTF_MAKE_FAST_ALLOCATED;
public:
    WeakPtrFactory() = default;
    ~WeakPtrFactory()
    {
        if (!m_ref)
            return;
        m_ref->clear();
    }

    WeakPtr<T> createWeakPtr(T& ptr) const
    {
        if (!m_ref)
            m_ref = WeakReference<T>::create(&ptr);
        return { makeRef(*m_ref) };
    }

    WeakPtr<const T> createWeakPtr(const T& ptr) const
    {
        if (!m_ref)
            m_ref = WeakReference<T>::create(const_cast<T*>(&ptr));
        return { makeRef(reinterpret_cast<WeakReference<const T>&>(*m_ref)) };
    }

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

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

private:
    template<typename> friend class WeakHashSet;

    mutable RefPtr<WeakReference<T>> m_ref;
};

template<typename T> class CanMakeWeakPtr {
public:
    const WeakPtrFactory<T>& weakPtrFactory() const { return m_weakFactory; }
    WeakPtrFactory<T>& weakPtrFactory() { return m_weakFactory; }

private:
    WeakPtrFactory<T> m_weakFactory;
};

template<typename T, typename U> inline WeakReference<T>* weak_reference_upcast(WeakReference<U>* weakReference)
{
    static_assert(std::is_convertible<U*, T*>::value, "U* must be convertible to T*");
    return reinterpret_cast<WeakReference<T>*>(weakReference);
}

template<typename T, typename U> inline WeakReference<T>* weak_reference_downcast(WeakReference<U>* weakReference)
{
    static_assert(std::is_convertible<T*, U*>::value, "T* must be convertible to U*");
    return reinterpret_cast<WeakReference<T>*>(weakReference);
}

template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(const WeakPtr<U>& o)
    : m_ref(weak_reference_upcast<T>(o.m_ref.get()))
{
}

template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(WeakPtr<U>&& o)
    : m_ref(adoptRef(weak_reference_upcast<T>(o.m_ref.leakRef())))
{
}

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

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

template<typename T> inline WeakPtr<T> makeWeakPtr(T& ref)
{
    return { adoptRef(*weak_reference_downcast<T>(ref.weakPtrFactory().createWeakPtr(ref).m_ref.leakRef())) };
}

template<typename T> inline WeakPtr<T> makeWeakPtr(T* ptr)
{
    if (!ptr)
        return { };
    return makeWeakPtr(*ptr);
}

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

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

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

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

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

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

} // namespace WTF

using WTF::CanMakeWeakPtr;
using WTF::WeakPtr;
using WTF::WeakPtrFactory;
using WTF::WeakReference;
using WTF::makeWeakPtr;
