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

#ifndef _DECAF_LANG_POINTER_H_
#define _DECAF_LANG_POINTER_H_

#include <decaf/util/Config.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/ClassCastException.h>
#include <decaf/util/concurrent/atomic/AtomicRefCounter.h>
#include <decaf/util/Comparator.h>
#include <memory>
#include <typeinfo>
#include <algorithm>
#include <functional>

namespace decaf {
namespace lang {

    // Used internally in Pointer.
    struct STATIC_CAST_TOKEN {};
    struct DYNAMIC_CAST_TOKEN {};

    /**
     * Decaf's implementation of a Smart Pointer that is a template on a Type
     * and is Thread Safe if the default Reference Counter is used.  This Pointer
     * type allows for the substitution of different Reference Counter implementations
     * which provide a means of using invasive reference counting if desired using
     * a custom implementation of <code>ReferenceCounter</code>.
     * <p>
     * The Decaf smart pointer provide comparison operators for comparing Pointer
     * instances in the same manner as normal pointer, except that it does not provide
     * an overload of operators ( <, <=, >, >= ).  To allow use of a Pointer in a STL
     * container that requires it, Pointer provides an implementation of std::less.
     *
     * @since 1.0
     */
    template<typename T, typename REFCOUNTER = decaf::util::concurrent::atomic::AtomicRefCounter>
    class Pointer : public REFCOUNTER {
    private:

        typedef void (*deletionFuncPtr)(T* p);

    private:

        T* value;

        // Pointer to our internal delete function.
        deletionFuncPtr onDelete;

    public:

        typedef T* PointerType;         // type returned by operator->
        typedef T& ReferenceType;       // type returned by operator*
        typedef REFCOUNTER CounterType; // Type of the Reference Counter

    public:

        /**
         * Default Constructor
         *
         * Initialized the contained pointer to NULL, using the -> operator
         * results in an exception unless reset to contain a real value.
         */
        Pointer() : REFCOUNTER(), value(NULL), onDelete(onDeleteFunc) {}

        /**
         * Explicit Constructor, creates a Pointer that contains value with a
         * single reference.  This object now has ownership until a call to release.
         *
         * @param value -
         *      The instance of the type we are containing here.
         */
        explicit Pointer(const PointerType value) : REFCOUNTER(), value(value), onDelete(onDeleteFunc) {}

        /**
         * Copy constructor. Copies the value contained in the pointer to the new
         * instance and increments the reference counter.
         *
         * @param value
         *      Another instance of a Pointer<T> that this Pointer will copy.
         */
        Pointer(const Pointer& value) : REFCOUNTER(value), value(value.value), onDelete(onDeleteFunc) {}

        /**
         * Copy constructor. Copies the value contained in the pointer to the new
         * instance and increments the reference counter.
         *
         * @param value
         *      A different but compatible Pointer instance that this Pointer will copy.
         */
        template<typename T1, typename R1>
        Pointer(const Pointer<T1, R1>& value) : REFCOUNTER(value), value(value.get()), onDelete(onDeleteFunc) {}

        /**
         * Static Cast constructor. Copies the value contained in the pointer to the new
         * instance and increments the reference counter performing a static cast on the
         * value contained in the source Pointer object.
         *
         * @param value
         *      Pointer instance to cast to this type using a static_cast.
         */
        template<typename T1, typename R1>
        Pointer(const Pointer<T1, R1>& value, const STATIC_CAST_TOKEN&) :
            REFCOUNTER(value), value(static_cast<T*> (value.get())), onDelete(onDeleteFunc) {}

        /**
         * Dynamic Cast constructor. Copies the value contained in the pointer to the new
         * instance and increments the reference counter performing a dynamic cast on the
         * value contained in the source Pointer object.  If the cast fails and return NULL
         * then this method throws a ClassCastException.
         *
         * @param value
         *      Pointer instance to cast to this type using a dynamic_cast.
         *
         * @throw ClassCastException if the dynamic cast returns NULL
         */
        template<typename T1, typename R1>
        Pointer(const Pointer<T1, R1>& value, const DYNAMIC_CAST_TOKEN&) :
            REFCOUNTER(value), value(dynamic_cast<T*> (value.get())), onDelete(onDeleteFunc) {

            if (this->value == NULL) {
                // Remove the reference we took in the Reference Counter's ctor since we
                // didn't actually create one as the dynamic cast failed.
                REFCOUNTER::release();
                throw decaf::lang::exceptions::ClassCastException(
                    __FILE__, __LINE__, "Failed to cast source pointer of type %s to this type: %s.",
                    typeid(T1).name(), typeid(T).name());
            }
        }

        virtual ~Pointer() {
            if (REFCOUNTER::release() == true) {
                onDelete(this->value);
            }
        }

        /**
         * Resets the Pointer to hold the new value.  Before the new value is stored
         * reset checks if the old value should be destroyed and if so calls delete.
         * Call reset with a value of NULL is supported and acts to set this Pointer
         * to a NULL pointer.
         *
         * @param value
         *      The new value to contain or NULL to empty the pointer (default NULL if not set).
         */
        void reset(T* value = NULL) {
            Pointer(value).swap(*this);
        }

        /**
         * Releases the Pointer held and resets the internal pointer value to Null.  This method
         * is not guaranteed to be safe if the Pointer is held by more than one object or this
         * method is called from more than one thread.
         *
         * @return The pointer instance that was held by this Pointer object, the pointer is
         *          no longer owned by this Pointer and won't be freed when this Pointer goes
         *          out of scope.
         */
        T* release() {
            T* temp = this->value;
            this->value = NULL;
            return temp;
        }

        /**
         * Gets the real pointer that is contained within this Pointer.  This is
         * not really safe since the caller could delete or alter the pointer but
         * it mimics the STL auto_ptr and gives access in cases where the caller
         * absolutely needs the real Pointer.  Use at your own risk.
         *
         * @return the contained pointer.
         */
        PointerType get() const {
            return this->value;
        }

        /**
         * Exception Safe Swap Function
         *
         * @param value
         *      The value to swap with this Pointer.
         */
        void swap(Pointer& value) {
            std::swap(this->value, value.value);
            REFCOUNTER::swap(value);
        }

        /**
         * Assigns the value of right to this Pointer and increments the reference Count.
         * @param right - Pointer on the right hand side of an operator= call to this.
         */
        Pointer& operator=(const Pointer& right) {
            if (this == (void*) &right) {
                return *this;
            }

            Pointer temp(right);
            temp.swap(*this);
            return *this;
        }
        template<typename T1, typename R1>
        Pointer& operator=(const Pointer<T1, R1>& right) {
            if (this == (void*) &right) {
                return *this;
            }

            Pointer temp(right);
            temp.swap(*this);
            return *this;
        }

        /**
         * Dereference Operator, returns a reference to the Contained value.  This
         * method throws an NullPointerException if the contained value is NULL.
         *
         * @return reference to the contained pointer.
         * @throws NullPointerException if the contained value is Null
         */
        ReferenceType operator*() {
            if (this->value == NULL) {
                throw decaf::lang::exceptions::NullPointerException(
                    __FILE__, __LINE__, "Pointer operator& - Pointee is NULL.");
            }

            return *(this->value);
        }
        ReferenceType operator*() const {
            if (this->value == NULL) {
                throw decaf::lang::exceptions::NullPointerException(
                    __FILE__, __LINE__, "Pointer operator& - Pointee is NULL.");
            }

            return *(this->value);
        }

        /**
         * Indirection Operator, returns a pointer to the Contained value.  This
         * method throws an NullPointerException if the contained value is NULL.
         *
         * @return reference to the contained pointer.
         * @throws NullPointerException if the contained value is Null
         */
        PointerType operator->() {
            if (this->value == NULL) {
                throw decaf::lang::exceptions::NullPointerException(
                    __FILE__, __LINE__, "Pointer operator-> - Pointee is NULL.");
            }
            return this->value;
        }
        PointerType operator->() const {
            if (this->value == NULL) {
                throw decaf::lang::exceptions::NullPointerException(
                    __FILE__, __LINE__, "Pointer operator-> - Pointee is NULL.");
            }
            return this->value;
        }

        bool operator!() const {
            return this->value == NULL;
        }

        inline friend bool operator==(const Pointer& left, const T* right) {
            return left.get() == right;
        }

        inline friend bool operator==(const T* left, const Pointer& right) {
            return left == right.get();
        }

        inline friend bool operator!=(const Pointer& left, const T* right) {
            return left.get() != right;
        }

        inline friend bool operator!=(const T* left, const Pointer& right) {
            return left != right.get();
        }

        template<typename T1, typename R1>
        bool operator==(const Pointer<T1, R1>& right) const {
            return this->value == right.get();
        }

        template<typename T1, typename R1>
        bool operator!=(const Pointer<T1, R1>& right) const {
            return !(this->value == right.get());
        }

        template<typename T1>
        Pointer<T1, CounterType> dynamicCast() const {
            return Pointer<T1, CounterType> (*this, DYNAMIC_CAST_TOKEN());
        }

        template<typename T1>
        Pointer<T1, CounterType> staticCast() const {
            return Pointer<T1, CounterType> (*this, STATIC_CAST_TOKEN());
        }

    private:

        // Internal Static deletion function.
        static void onDeleteFunc(T* value) {
            delete value;
        }

    };

    ////////////////////////////////////////////////////////////////////////////
    template<typename T, typename R, typename U>
    inline bool operator==(const Pointer<T, R>& left, const U* right) {
        return left.get() == right;
    }

    ////////////////////////////////////////////////////////////////////////////
    template<typename T, typename R, typename U>
    inline bool operator==(const U* left, const Pointer<T, R>& right) {
        return right.get() == left;
    }

    ////////////////////////////////////////////////////////////////////////////
    template<typename T, typename R, typename U>
    inline bool operator!=(const Pointer<T, R>& left, const U* right) {
        return !(left.get() == right);
    }

    ////////////////////////////////////////////////////////////////////////////
    template<typename T, typename R, typename U>
    inline bool operator!=(const U* left, const Pointer<T, R>& right) {
        return right.get() != left;
    }

    ////////////////////////////////////////////////////////////////////////////
    template<typename T, typename R>
    std::ostream& operator<<(std::ostream &out, const Pointer<T, R>& pointer) {
        out << pointer.get();
        return out;
    }

    /**
     * This implementation of Comparator is designed to allows objects in a Collection
     * to be sorted or tested for equality based on the value of the Object being Pointed
     * to and not the value of the contained pointer in the Pointer instance.  This can
     * be useful in the case where a series of values in a Collection is more efficiently
     * accessed in the Objects Natural Order and not the underlying pointers location in
     * memory.
     * <p>
     * Also this allows Pointer objects that Point to different instances of the same type
     * to be compared based on the comparison of the object itself and not just the value of
     * the pointer.
     */
    template<typename T, typename R = decaf::util::concurrent::atomic::AtomicRefCounter>
    class PointerComparator: public decaf::util::Comparator<Pointer<T, R> > {
    public:

        virtual ~PointerComparator() {}

        // Allows for operator less on types that implement Comparable or provide
        // a workable operator <
        virtual bool operator()(const Pointer<T, R>& left, const Pointer<T, R>& right) const {
            return *left < *right;
        }

        // Requires that the type in the pointer is an instance of a Comparable.
        virtual int compare(const Pointer<T, R>& left, const Pointer<T, R>& right) const {
            return *left < *right ? -1 : *right < *left ? 1 : 0;
        }

    };

}}

////////////////////////////////////////////////////////////////////////////////
namespace std {

    /**
     * An override of the less function object so that the Pointer objects
     * can be stored in STL Maps, etc.
     */
    template<typename T>
    struct less<decaf::lang::Pointer<T> > { //: public binary_function<decaf::lang::Pointer<T>, decaf::lang::Pointer<T>, bool> {

        typedef decaf::lang::Pointer<T> first_argument_type;
        typedef decaf::lang::Pointer<T> second_argument_type;
        typedef bool result_type;

        bool operator()(const decaf::lang::Pointer<T>& left, const decaf::lang::Pointer<T>& right) const {
            return less<T*> ()(left.get(), right.get());
        }
    };
}

#endif /*_DECAF_LANG_POINTER_H_*/
