/*
 *
 *    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 <lib/support/CodeUtils.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 underlying buffer.
     *
     * The buffer stops being managed and will not be auto-freed.
     */
    CHECK_RETURN_VALUE 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");

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

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

    /**
     * Releases the underlying buffer.
     *
     * The buffer stops being managed and will not be auto-freed.
     */
    CHECK_RETURN_VALUE 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();
    }

    /**
     * Releases the underlying buffer.
     *
     * The buffer stops being managed and will not be auto-freed.
     */
    CHECK_RETURN_VALUE 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
