/*
 *  Copyright (c) 2021, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *  This file defines OpenThread `Appender` class.
 */

#ifndef APPENDER_HPP_
#define APPENDER_HPP_

#include "openthread-core-config.h"

#include "common/data.hpp"
#include "common/message.hpp"
#include "common/type_traits.hpp"

namespace ot {

/**
 * The `Appender` class acts as a wrapper over either a `Message` or a data buffer and provides different flavors of
 * `Append()` method.
 *
 * This class helps in construction of message content where the destination can be either a `Message` or a buffer.
 *
 */
class Appender
{
public:
    /**
     * This enumeration represent the `Appender` Type (whether appending to a `Message` or data buffer).
     *
     */
    enum Type : uint8_t
    {
        kMessage, ///< `Appender` appends to a `Message`
        kBuffer,  ///< `Appender` appends to a buffer.
    };

    /**
     * This constructor initializes the `Appender` to append to a `Message`.
     *
     * New content is appended to the end of @p aMessage, growing its length.
     *
     * @param[in] aMessage   The message to append to.
     *
     */
    explicit Appender(Message &aMessage);

    /**
     * This constructor initializes the `Appender` to append in a given a buffer
     *
     * New content is append in the buffer starting from @p aBuffer up to is size @p aSize. `Appender` does not allow
     * content to be appended beyond the size of the buffer.
     *
     * @param[in] aBuffer  A pointer to start of buffer.
     * @param[in] aSize    The maximum size of @p aBuffer (number of available bytes in buffer).
     *
     */
    Appender(uint8_t *aBuffer, uint16_t aSize);

    /**
     * This method indicates the `Appender` type (whether appending to a `Message` or data buffer).
     *
     * @returns The type of `Appender`.
     *
     */
    Type GetType(void) const { return mType; }

    /**
     * This method appends bytes to the `Appender` object
     *
     * @param[in] aBuffer  A pointer to a data buffer (MUST NOT be `nullptr`) to append.
     * @param[in] aLength  The number of bytes to append.
     *
     * @retval kErrorNone    Successfully appended the bytes.
     * @retval kErrorNoBufs  Insufficient available buffers.
     *
     */
    Error AppendBytes(const void *aBuffer, uint16_t aLength);

    /**
     * This method appends an object to the end of the `Appender` object.
     *
     * @tparam    ObjectType   The object type to append to the message.
     *
     * @param[in] aObject      A reference to the object to append to the message.
     *
     * @retval kErrorNone    Successfully appended the object.
     * @retval kErrorNoBufs  Insufficient available buffers to append @p aObject.
     *
     */
    template <typename ObjectType> Error Append(const ObjectType &aObject)
    {
        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");

        return AppendBytes(&aObject, sizeof(ObjectType));
    }

    /**
     * This method returns the number of bytes appended so far using `Appender` methods.
     *
     * This method can be used independent of the `Type` of `Appender`.
     *
     * @returns The number of byes appended so far.
     *
     */
    uint16_t GetAppendedLength(void) const;

    /**
     * This method returns the `Message` associated with `Appender`.
     *
     * This method MUST be used when `GetType() == kMessage`. Otherwise its behavior is undefined.
     *
     * @returns The `Message` instance associated with `Appender`.
     *
     */
    Message &GetMessage(void) { return *mShared.mMessage.mMessage; }

    /**
     * This method returns a pointer to the start of the data buffer associated with `Appender`.
     *
     * This method MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined.
     *
     * @returns A pointer to the start of the data buffer associated with `Appender`.
     *
     */
    uint8_t *GetBufferStart(void) { return mShared.mBuffer.mStart; }

    /**
     * This method gets the data buffer associated with `Appender` as a `Data`.
     *
     * This method MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined.
     *
     * @pram[out] aData  A reference to a `Data` to output the data buffer.
     *
     */
    void GetAsData(Data<kWithUint16Length> &aData);

private:
    Type mType;
    union
    {
        struct
        {
            Message *mMessage;
            uint16_t mStartOffset;
        } mMessage;

        struct
        {
            uint8_t *mStart;
            uint8_t *mCur;
            uint8_t *mEnd;
        } mBuffer;
    } mShared;
};

} // namespace ot

#endif // APPENDER_HPP_
