/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed 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
 *      Defines scoped auto-free buffers for CHIP.
 *
 */

#pragma once

#include <lib/support/CHIPMem.h>

#include <type_traits>
#include <utility>

namespace chip {
namespace Platform {

namespace Impl {

/**
 * Represents a memory buffer that is auto-freed in the destructor.
 *
 * This class uses void* underneath on purpose (rather than a unique_ptr like
 * 'Type') and uses  templated type on Ptr(). This is to avoid template explosion
 * when the buffers are used for different types - only one implementation of
 * the class will be stored in flash.
 */
template <class Impl>
class ScopedMemoryBufferBase
{
public:
    ScopedMemoryBufferBase() {}
    ScopedMemoryBufferBase(const ScopedMemoryBufferBase &) = delete;
    ScopedMemoryBufferBase & operator=(const ScopedMemoryBufferBase & other) = delete;

    ScopedMemoryBufferBase(ScopedMemoryBufferBase && other) { *this = std::move(other); }

    ScopedMemoryBufferBase & operator=(ScopedMemoryBufferBase && other)
    {
        if (this != &other)
        {
            mBuffer       = other.mBuffer;
            other.mBuffer = nullptr;
        }
        return *this;
    }

    ~ScopedMemoryBufferBase() { Free(); }

    /** Check if a buffer is valid */
    explicit operator bool() const { return mBuffer != nullptr; }
    bool operator!() const { return mBuffer == nullptr; }

    /** Release memory used */
    void Free()
    {
        if (mBuffer == nullptr)
        {
            return;
        }
        Impl::MemoryFree(mBuffer);
        mBuffer = nullptr;
    }

protected:
    void * Ptr() { return mBuffer; }
    const void * Ptr() const { return mBuffer; }

    /**
     * Releases the undelying buffer. Buffer stops being managed and will not be
     * auto-freed.
     */
    void * Release()
    {
        void * buffer = mBuffer;
        mBuffer       = nullptr;
        return buffer;
    }

    void Alloc(size_t size)
    {
        Free();
        mBuffer = Impl::MemoryAlloc(size);
    }

    void Calloc(size_t elementCount, size_t elementSize)
    {
        Free();
        mBuffer = Impl::MemoryCalloc(elementCount, elementSize);
    }

private:
    void * mBuffer = nullptr;
};

/**
 * Helper class that forwards memory management tasks to Platform::Memory* calls.
 */
class PlatformMemoryManagement
{
public:
    static void MemoryFree(void * p) { chip::Platform::MemoryFree(p); }
    static void * MemoryAlloc(size_t size) { return chip::Platform::MemoryAlloc(size); }
    static void * MemoryCalloc(size_t num, size_t size) { return chip::Platform::MemoryCalloc(num, size); }
};

} // namespace Impl

/**
 * Represents a memory buffer allocated using chip::Platform::Memory*Alloc
 * methods.
 *
 * Use for RAII to auto-free after use.
 */
template <typename T, class MemoryManagement = Impl::PlatformMemoryManagement>
class ScopedMemoryBuffer : public Impl::ScopedMemoryBufferBase<MemoryManagement>
{
    friend class Impl::ScopedMemoryBufferBase<MemoryManagement>;

public:
    using Base = Impl::ScopedMemoryBufferBase<MemoryManagement>;

    static_assert(std::is_trivially_destructible<T>::value, "Destructors won't get run");

    inline T * Get() { return static_cast<T *>(Base::Ptr()); }
    inline T & operator[](size_t index) { return Get()[index]; }

    inline const T * Get() const { return static_cast<const T *>(Base::Ptr()); }
    inline const T & operator[](size_t index) const { return Get()[index]; }

    inline T * Release() { return static_cast<T *>(Base::Release()); }

    ScopedMemoryBuffer & Calloc(size_t elementCount)
    {
        Base::Calloc(elementCount, sizeof(T));
        ExecuteConstructors(elementCount);
        return *this;
    }

    ScopedMemoryBuffer & Alloc(size_t elementCount)
    {
        Base::Alloc(elementCount * sizeof(T));
        ExecuteConstructors(elementCount);
        return *this;
    }

private:
    template <typename U = T, std::enable_if_t<std::is_trivial<U>::value, int> = 0>
    void ExecuteConstructors(size_t elementCount)
    {
        // Do nothing if our type is trivial.  In particular, if we are a buffer
        // of integers, we should not go zero-initializing them here: either
        // caller wants that and called Calloc(), or it doesn't and we shouldn't
        // do it.
    }

    template <typename U = T, std::enable_if_t<!std::is_trivial<U>::value, int> = 0>
    void ExecuteConstructors(size_t elementCount)
    {
        T * elementPtr = Get();
        if (elementPtr == nullptr)
        {
            // Alloc failed, don't bother.
            return;
        }
        for (size_t i = 0; i < elementCount; ++i)
        {
            new (&elementPtr[i]) T();
        }
    }
};

/**
 * Represents a memory buffer with buffer size allocated using chip::Platform::Memory*Alloc
 * methods.
 *
 * Use for RAII to auto-free after use.
 */
template <typename T>
class ScopedMemoryBufferWithSize : public ScopedMemoryBuffer<T>
{
public:
    ScopedMemoryBufferWithSize() {}
    ScopedMemoryBufferWithSize(ScopedMemoryBufferWithSize && other) { *this = std::move(other); }

    ScopedMemoryBufferWithSize & operator=(ScopedMemoryBufferWithSize && other)
    {
        if (this != &other)
        {
            mCount       = other.mCount;
            other.mCount = 0;
        }
        ScopedMemoryBuffer<T>::operator=(std::move(other));
        return *this;
    }

    ~ScopedMemoryBufferWithSize() { mCount = 0; }

    // return the size as count of elements
    inline size_t AllocatedSize() const { return mCount; }

    void Free()
    {
        mCount = 0;
        ScopedMemoryBuffer<T>::Free();
    }

    T * Release()
    {
        T * buffer = ScopedMemoryBuffer<T>::Release();
        mCount     = 0;
        return buffer;
    }

    ScopedMemoryBufferWithSize & Calloc(size_t elementCount)
    {
        ScopedMemoryBuffer<T>::Calloc(elementCount);
        if (this->Get() != nullptr)
        {
            mCount = elementCount;
        }
        return *this;
    }

    ScopedMemoryBufferWithSize & Alloc(size_t elementCount)
    {
        ScopedMemoryBuffer<T>::Alloc(elementCount);
        if (this->Get() != nullptr)
        {
            mCount = elementCount;
        }
        return *this;
    }

private:
    size_t mCount = 0;
};

} // namespace Platform
} // namespace chip
