#ifndef PROTON_THREAD_SAFE_HPP
#define PROTON_THREAD_SAFE_HPP

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 */

#include "./internal/config.hpp"
#include "./connection.hpp"
#include "./event_loop.hpp"
#include "./internal/object.hpp"
#include "./internal/type_traits.hpp"

#include <functional>

namespace proton {

class connection;
class session;
class link;
class sender;
class receiver;

namespace internal {
template <class T> struct endpoint_traits;
template<> struct endpoint_traits<connection> {};
template<> struct endpoint_traits<session> {};
template<> struct endpoint_traits<link> {};
template<> struct endpoint_traits<sender> {};
template<> struct endpoint_traits<receiver> {};
}

template <class T> class returned;

/// **Experimental** - A thread-safe object wrapper.
///
/// The proton::object subclasses (proton::connection, proton::sender etc.) are
/// reference-counted wrappers for C structs. They are not safe for concurrent use,
/// not even to copy or assign.
///
/// A pointer to thread_safe<> can be used from any thread to get the
/// proton::event_loop for the object's connection. The object will not be
/// destroyed until the thread_safe<> is deleted. You can use std::shared_ptr,
/// std::unique_ptr or any other memory management technique to manage the
/// thread_safe<>.
///
/// Use make_thread_safe(), make_shared_thread_safe(), make_unique_thread_safe() to
/// create a thread_safe<>
///
/// @see @ref mt_page
template <class T>
class thread_safe : private internal::pn_ptr_base, private internal::endpoint_traits<T> {
    typedef typename T::pn_type pn_type;

    struct inject_decref : public inject_handler {
        pn_type* ptr_;
        inject_decref(pn_type* p) : ptr_(p) {}
        void on_inject() PN_CPP_OVERRIDE { decref(ptr_); delete this; }
    };

  public:
    /// @cond INTERNAL
    static void operator delete(void*) {}
    /// @endcond

    ~thread_safe() {
        if (ptr()) {
            if (event_loop()) {
#if PN_CPP_HAS_CPP11
                event_loop()->inject(std::bind(&decref, ptr()));
#else
                event_loop()->inject(*new inject_decref(ptr()));
#endif
            } else {
                decref(ptr());
            }
        }
    }

    /// Get the event loop for this object.
    class event_loop* event_loop() { return event_loop::get(ptr()); }

    /// Get the thread-unsafe proton object wrapped by this thread_safe<T>
    T unsafe() { return T(ptr()); }

  private:
    static thread_safe* create(const T& obj) { return new (obj.pn_object()) thread_safe(); }
    static void* operator new(size_t, pn_type* p) { return p; }
    static void operator delete(void*, pn_type*) {}
    thread_safe() { incref(ptr()); }
    pn_type* ptr() { return reinterpret_cast<pn_type*>(this); }


    // Non-copyable.
    thread_safe(const thread_safe&);
    thread_safe& operator=(const thread_safe&);

    /// @cond INTERNAL
  friend class returned<T>;
    /// @endcond
};

// return value for functions returning a thread_safe<> object.
//
// Temporary return value only, you should release() to get a plain pointer or
// assign to a smart pointer type.
template <class T>
class returned : private internal::endpoint_traits<T>
{
  public:
    /// Take ownership
    explicit returned(thread_safe<T>* p) : ptr_(p) {}
    /// Create an owned thread_safe<T>
    explicit returned(const T& obj) : ptr_(thread_safe<T>::create(obj)) {}
    /// Transfer ownership.
    /// Use the same "cheat" as std::auto_ptr, calls x.release() even though x is const.
    returned(const returned& x) : ptr_(const_cast<returned&>(x).release()) {}
    /// Delete if still owned.
    ~returned() { if (ptr_) delete ptr_; }

    /// Release ownership.
    thread_safe<T>* release() const { thread_safe<T>* p = ptr_; ptr_ = 0; return p; }

    /// Implicit conversion to target, usable only in a safe context.
    operator T() { return ptr_->unsafe(); }

#if PN_CPP_HAS_CPP11
    /// Release to a std::shared_ptr
    operator std::shared_ptr<thread_safe<T> >() {
        return std::shared_ptr<thread_safe<T> >(release());
    }

    /// Release to a std::unique_ptr
    operator std::unique_ptr<thread_safe<T> >() {
        return std::unique_ptr<thread_safe<T> >(release());
    }
#endif

  private:
    void operator=(const returned&);
    mutable thread_safe<T>* ptr_;
};

/// Make a thread-safe wrapper for `obj`.
template <class T> returned<T> make_thread_safe(const T& obj) { return returned<T>(obj); }

#if PN_CPP_HAS_CPP11
template <class T> std::shared_ptr<thread_safe<T> > make_shared_thread_safe(const T& obj) {
    return make_thread_safe(obj);
}
template <class T> std::unique_ptr<thread_safe<T> > make_unique_thread_safe(const T& obj) {
    return make_thread_safe(obj);
}
#endif

} // proton

#endif // PROTON_THREAD_SAFE_HPP
