/*
 * 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.
 */

/**
 * @file
 * Declares ignite::Reference class.
 */

#ifndef _IGNITE_COMMON_REFERENCE
#define _IGNITE_COMMON_REFERENCE

#include <cstddef>

#include <ignite/common/common.h>
#include <ignite/common/concurrent.h>
#include <ignite/common/reference_impl.h>

namespace ignite
{
    template<typename T>
    class Reference;

    /**
     * Constant Reference class.
     *
     * Abstraction on any reference-type object, from simple raw pointers and
     * references to standard library smart pointers. Provides only constant
     * access to the underlying data.
     *
     * There are no requirements for the template type T.
     */
    template<typename T>
    class ConstReference
    {
        template<typename>
        friend class ConstReference;

        template<typename>
        friend class Reference;

    public:
        /**
         * Default constructor.
         */
        ConstReference() :
            ptr(),
            offset(0)
        {
            // No-op.
        }

        /**
         * Constructor.
         *
         * @param ptr ConstReference class implementation.
         * @param offset Pointer offset.
         */
        explicit ConstReference(common::ConstReferenceImplBase* ptr, ptrdiff_t offset = 0) :
            ptr(ptr),
            offset(offset)
        {
            // No-op.
        }

        /**
         * Copy constructor.
         *
         * @param other Another instance.
         */
        ConstReference(const ConstReference& other) :
            ptr(other.ptr),
            offset(other.offset)
        {
            // No-op.
        }

        /**
         * Copy constructor.
         *
         * Constant reference of type T2 should be static-castable to constant
         * reference of type T.
         *
         * @param other Another instance.
         */
        template<typename T2>
        ConstReference(const ConstReference<T2>& other) :
            ptr(other.ptr),
            offset(other.offset)
        {
            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
            T* p1 = static_cast<T*>(p0);

            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
            offset += diff;
        }

        /**
         * Assignment operator.
         *
         * @param other Another instance.
         */
        ConstReference& operator=(const ConstReference& other)
        {
            ptr = other.ptr;
            offset = other.offset;

            return *this;
        }
        
        /**
         * Assignment operator.
         *
         * Constant reference of type T2 should be static-castable to constant
         * reference of type T.
         *
         * @param other Another instance.
         */
        template<typename T2>
        ConstReference& operator=(const ConstReference<T2>& other)
        {
            ptr = other.ptr;
            offset = other.offset;

            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
            T* p1 = static_cast<T*>(p0);

            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
            offset += diff;

            return *this;
        }

        /**
         * Destructor.
         */
        ~ConstReference()
        {
            // No-op.
        }

        /**
         * Dereference the pointer.
         *
         * If the pointer is null then this operation causes undefined
         * behaviour.
         *
         * @return Constant reference to underlying value.
         */
        const T* Get() const
        {
            return reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
        }

        /**
         * Check if the pointer is null.
         *
         * @return True if the value is null.
         */
        bool IsNull() const
        {
            const common::ConstReferenceImplBase* raw = ptr.Get();

            return !raw || !raw->Get();
        }

    private:
        /** Implementation. */
        common::concurrent::SharedPointer<common::ConstReferenceImplBase> ptr;

        /** Address offset. */
        ptrdiff_t offset;
    };

    /**
     * Reference class.
     *
     * Abstraction on any reference-type object, from simple raw pointers and
     * references to standard library smart pointers.
     *
     * There are no requirements for the template type T.
     */
    template<typename T>
    class Reference
    {
        template<typename>
        friend class Reference;
    public:
        /**
         * Default constructor.
         */
        Reference() :
            ptr(),
            offset(0)
        {
            // No-op.
        }

        /**
         * Constructor.
         *
         * @param ptr Reference class implementation.
         * @param offset Pointer offset.
         */
        explicit Reference(common::ReferenceImplBase* ptr, ptrdiff_t offset = 0) :
            ptr(ptr),
            offset(offset)
        {
            // No-op.
        }

        /**
         * Copy constructor.
         *
         * @param other Another instance.
         */
        Reference(const Reference& other) :
            ptr(other.ptr),
            offset(other.offset)
        {
            // No-op.
        }

        /**
         * Copy constructor.
         * 
         * Reference of type T2 should be static-castable to reference of type T.
         *
         * @param other Another instance.
         */
        template<typename T2>
        Reference(const Reference<T2>& other) :
            ptr(other.ptr),
            offset(other.offset)
        {
            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
            T* p1 = static_cast<T*>(p0);

            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
            offset += diff;
        }

        /**
         * Assignment operator.
         *
         * @param other Another instance.
         */
        Reference& operator=(const Reference& other)
        {
            ptr = other.ptr;
            offset = other.offset;

            return *this;
        }
        
        /**
         * Assignment operator.
         *
         * Reference of type T2 should be static-castable to reference of type T.
         *
         * @param other Another instance.
         */
        template<typename T2>
        Reference& operator=(const Reference<T2>& other)
        {
            ptr = other.ptr;
            offset = other.offset;

            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
            T* p1 = static_cast<T*>(p0);

            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
            offset += diff;

            return *this;
        }

        /**
         * Destructor.
         */
        ~Reference()
        {
            // No-op.
        }

        /**
         * Const cast operator.
         *
         * Reference of type T2 should be static-castable to reference of type T.
         *
         * Casts this instance to constant reference.
         */
        template<typename T2>
        operator ConstReference<T2>()
        {
            ConstReference<T2> cr;

            cr.ptr = ptr;
            cr.offset = offset;

            T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER);
            const T* p1 = static_cast<T*>(p0);

            ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0);
            cr.offset -= diff;

            return cr;
        }

        /**
         * Dereference the pointer.
         *
         * If the pointer is null then this operation causes undefined
         * behaviour.
         *
         * @return Constant pointer to underlying value.
         */
        const T* Get() const
        {
            return reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
        }

        /**
         * Dereference the pointer.
         *
         * If the pointer is null then this operation causes undefined
         * behaviour.
         *
         * @return Reference to underlying value.
         */
        T* Get()
        {
            return reinterpret_cast<T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset);
        }

        /**
         * Check if the pointer is null.
         *
         * @return True if the value is null.
         */
        bool IsNull() const
        {
            const common::ReferenceImplBase* raw = ptr.Get();

            return !raw || !raw->Get();
        }

    private:
        /** Implementation. */
        common::concurrent::SharedPointer<common::ReferenceImplBase> ptr;

        /** Address offset. */
        ptrdiff_t offset;
    };

    /**
     * Make ignite::Reference instance out of smart pointer.
     *
     * Template type 'T' should be a smart pointer and provide pointer semantics:
     * - There should be defined type 'T::element_type', showing underlying type.
     * - Type 'T' should be dereferencible (should have operators
     *   T::element_type& operator*() and const T::element_type& operator*() const).
     * - Operation std::swap should result in valid result if applied to two
     *   instances of that type.
     *
     * @param ptr Pointer.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    Reference<typename T::element_type> MakeReferenceFromSmartPointer(T ptr)
    {
        common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>();

        Reference<typename T::element_type> res(impl);

        impl->Swap(ptr);

        return res;
    }

    /**
     * Make ignite::ConstReference instance out of smart pointer.
     *
     * Template type 'T' should be a smart pointer and provide pointer semantics:
     * - There should be defined type 'T::element_type', showing underlying type.
     * - Type 'T' should be dereferencible (should have operators
     *   T::element_type& operator*() and const T::element_type& operator*() const).
     * - Operation std::swap should result in valid result if applied to two
     *   instances of that type.
     *
     * @param ptr Pointer.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    ConstReference<typename T::element_type> MakeConstReferenceFromSmartPointer(T ptr)
    {
        common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>();

        ConstReference<typename T::element_type> res(impl);

        impl->Swap(ptr);

        return res;
    }

    /**
     * Copy object and wrap it to make ignite::Reference instance.
     *
     * Template type 'T' should be copy-constructible.
     *
     * @param val Instance.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    Reference<T> MakeReferenceFromCopy(const T& val)
    {
        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val));

        return Reference<T>(impl);
    }

    /**
     * Copy object and wrap it to make ignite::ConstReference instance.
     *
     * Template type 'T' should be copy-constructible.
     *
     * @param val Instance.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    ConstReference<T> MakeConstReferenceFromCopy(const T& val)
    {
        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val));

        return ConstReference<T>(impl);
    }

    /**
     * Make ignite::Reference instance out of pointer and pass its ownership.
     * Passed object deleted by Ignite when no longer needed.
     *
     * There are no requirements for the template type T.
     *
     * @param val Instance.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    Reference<T> MakeReferenceFromOwningPointer(T* val)
    {
        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val);

        return Reference<T>(impl);
    }

    /**
     * Make ignite::ConstReference instance out of pointer and pass its ownership.
     * Passed object deleted by Ignite when no longer needed.
     *
     * There are no requirements for the template type T.
     *
     * @param val Instance.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    ConstReference<T> MakeConstReferenceFromOwningPointer(T* val)
    {
        common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val);

        return ConstReference<T>(impl);
    }

    /**
     * Make ignite::Reference instance out of reference.
     * Ignite do not manage passed object and does not affect its lifetime.
     *
     * There are no requirements for the template type T.
     *
     * @param val Reference.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    Reference<T> MakeReference(T& val)
    {
        common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(&val);

        return Reference<T>(impl);
    }

    /**
     * Make ignite::Reference instance out of pointer.
     * Ignite do not manage passed object and does not affect its lifetime.
     *
     * There are no requirements for the template type T.
     *
     * @param val Reference.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    Reference<T> MakeReference(T* val)
    {
        common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(val);

        return Reference<T>(impl);
    }

    /**
     * Make ignite::ConstReference instance out of constant reference.
     * Ignite do not manage passed object and does not affect its lifetime.
     *
     * There are no requirements for the template type T.
     *
     * @param val Reference.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    ConstReference<T> MakeConstReference(const T& val)
    {
        common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(&val);

        return ConstReference<T>(impl);
    }

    /**
     * Make ignite::ConstReference instance out of constant pointer.
     * Ignite do not manage passed object and does not affect its lifetime.
     *
     * There are no requirements for the template type T.
     *
     * @param val Reference.
     * @return Implementation defined value. User should not explicitly use the
     *     returned value.
     */
    template<typename T>
    ConstReference<T> MakeConstReference(const T* val)
    {
        common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(val);

        return ConstReference<T>(impl);
    }
}

#endif //_IGNITE_COMMON_REFERENCE