/*
 * This source file is part of KEOS (Free 3D Engine)
 * For the latest info, see http://www.keosengine.org/
 * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 * http://www.gnu.org/copyleft/lesser.txt.
 *
 */

#ifndef KEOS_BUFFER_H
#define KEOS_BUFFER_H

#include "KeosPrerequisites.h"
#include "KeosBufferBase.h"

namespace Keos
{
    //-----------------------------------------------------------------------
    /** Wrapper manipulating the buffers (VB/IB/...).
     */
    template <class T>
    class CBuffer
    {
    public :

        /** Default constructor.
         *  @param pBuffer Pointer on the intern buffer.
         */
        CBuffer(IBufferBase* pBuffer = NULL);

        /** Lock the buffer.
         *  @param nOffset Lock position.
         *  @param nSize Number of elements to be locked.
         *  @param nFlags Lock options.
         *  @return Pointer on the data locked.
         */
        T* Lock(ulong nOffset = 0, ulong nSize = 0, ulong nFlags = 0);

        /** Unlock the buffer.
         */
        void Unlock();

        /** Fill the buffer.
         *  @param pData Pointer on the data.
         *  @param nCount Number of elements to be copied.
         */
        void Fill(const T* pData, size_t nCount);

        /** Destroy the buffer.
         */
        void Release();

        /** Return pointer on the buffer.
         *  @return Pointer on the data.
         */
        const IBufferBase* GetBuffer() const;

        /** Return the number of elements in the buffer.
         *  @return Buffer size.
         */
        ulong GetCount() const;

    private :

        //! Intern buffer
        CSmartPtr<IBufferBase> m_Buffer;
    };

    //=======================================================================
    // CBuffer inline functions
    //=======================================================================
    
    //-----------------------------------------------------------------------
    template <class T>
    inline CBuffer<T>::CBuffer(IBufferBase* pBuffer) :
    m_Buffer(pBuffer)
    {

    }

    //-----------------------------------------------------------------------
    template <class T>
    inline T* CBuffer<T>::Lock(ulong nOffset, ulong nSize, ulong nFlags)
    {
        return reinterpret_cast<T*>(m_Buffer->Lock(nOffset * sizeof(T), nSize * sizeof(T), nFlags));
    }

    //-----------------------------------------------------------------------
    template <class T>
    inline void CBuffer<T>::Unlock()
    {
        m_Buffer->Unlock();
    }

    //-----------------------------------------------------------------------
    template <class T>
    inline void CBuffer<T>::Fill(const T* pData, size_t nCount)
    {
        Assert(pData != NULL);

        T* pMyData = Lock();
        std::copy(pData, pData + nCount, pMyData);
        Unlock();
    }

    //-----------------------------------------------------------------------
    template <class T>
    inline void CBuffer<T>::Release()
    {
        m_Buffer = NULL;
    }

    //-----------------------------------------------------------------------
    template <class T>
    inline const IBufferBase* CBuffer<T>::GetBuffer() const
    {
        return m_Buffer;
    }

    //-----------------------------------------------------------------------
    template <class T>
    inline ulong CBuffer<T>::GetCount() const
    {
        return m_Buffer->m_nCount;
    }

} // namespace Keos

#endif // KEOS_BUFFER_H
