/*
 *    Copyright (c) 2016, 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 includes definitions for an HDLC-lite encoder and decoder.
 */

#ifndef HDLC_HPP_
#define HDLC_HPP_

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <openthread/error.h>

#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"

namespace ot {

/**
 * @namespace ot::Hdlc
 *
 * @brief
 *   This namespace includes definitions for the HDLC-lite encoder and decoder.
 *
 */
namespace Hdlc {

/**
 * This class defines a frame write pointer used by `Hdlc::Encoder` or `Hdlc::Decoder`.
 *
 * This class defines the minimum set of APIs used by `Encoder/Decoder` for writing an encoded/decoded frame. It is
 * simply a wrapper over a pointer into a buffer indicating where next byte should be written. Along with a write
 * pointer, this class stores a remaining length variable indicating number of remaining bytes that can be written into
 * the buffer.
 *
 * @note This class does NOT define the underlying buffer space or how it is being managed.
 *
 * `Encoder` or `Decoder` users are expected to use sub-classes of this class adding the buffer space and implementing
 * the frame buffer management scheme.
 *
 * Two template sub-class `FrameBuffer` and `MultiFrameBuffer` are defined which respectively allow storing a single
 * frame or multiple frames (FIFO queue of frame) in a buffer of a given size.
 *
 */
class FrameWritePointer
{
public:
    /**
     * This method indicates whether there is buffer space available to write @p aWriteLength bytes.
     *
     * param[in] aWriteLength       Number of bytes to write.
     *
     * @retval TRUE                 Enough buffer space is available to write the requested number of bytes.
     * @retval FALSE                Insufficient buffer space to write the requested number of bytes.
     *
     */
    bool CanWrite(uint16_t aWriteLength) const { return (mRemainingLength >= aWriteLength); }

    /**
     * This method writes a byte into the buffer and updates the write pointer (if space is available).
     *
     * @retval OT_ERROR_NONE     Successfully wrote the byte and updated the pointer.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space to write the byte.
     *
     */
    otError WriteByte(uint8_t aByte)
    {
        return CanWrite(sizeof(uint8_t)) ? (*mWritePointer++ = aByte, mRemainingLength--, OT_ERROR_NONE)
                                         : OT_ERROR_NO_BUFS;
    }

    /**
     * This method undoes the last @p aUndoLength writes, removing them from frame.
     *
     * @note Caller should ensure that @p aUndoLength is less than or equal to the number of previously written bytes
     * into the frame. This method does not perform any checks and its behavior is undefined if @p aUndoLength is
     * larger than the number of bytes previously written into the frame.
     *
     * @param[in]  aUndoLength   Number of bytes to remove (number of last `WriteByte()` calls to undo).
     *
     */
    void UndoLastWrites(uint16_t aUndoLength)
    {
        mWritePointer -= aUndoLength;
        mRemainingLength += aUndoLength;
    }

protected:
    FrameWritePointer(void)
        : mWritePointer(nullptr)
        , mRemainingLength(0)
    {
    }

    uint8_t *mWritePointer;    ///< A pointer to current write position in the buffer.
    uint16_t mRemainingLength; ///< Number of remaining bytes available to write.
};

/**
 * This class defines a template frame buffer of a given size for storing a single frame.
 *
 * The template parameter `kSize` specifies the size of the buffer.
 *
 */
template <uint16_t kSize> class FrameBuffer : public FrameWritePointer
{
public:
    /**
     * This constructor initializes the `FrameBuffer` object.
     *
     */
    FrameBuffer(void)
        : FrameWritePointer()
    {
        Clear();
    }

    /**
     * This method clears the buffer, moving the write pointer to the beginning of the buffer.
     *
     */
    void Clear(void)
    {
        mWritePointer    = mBuffer;
        mRemainingLength = sizeof(mBuffer);
    }

    /**
     * This method indicates whether the buffer is empty or contains a frame.
     *
     * @retval TRUE  Buffer is empty
     * @retval FALSE Buffer contains a frame
     *
     */
    bool IsEmpty(void) const { return (mWritePointer == mBuffer); }

    /**
     * This method gets the length (number of bytes) in the frame.
     *
     * @returns The length (number of bytes) in the frame.
     *
     */
    uint16_t GetLength(void) const { return static_cast<uint16_t>(mWritePointer - mBuffer); }

    /**
     * This method gets a pointer to start of the frame.
     *
     * @returns A pointer to start of the frame.
     *
     */
    uint8_t *GetFrame(void) { return mBuffer; }

private:
    uint8_t mBuffer[kSize];
};

/**
 * This class defines a template frame buffer of a given size for storing multiple frames.
 *
 * The template parameter `kSize` specifies the total size of the buffer.
 *
 * Unlike `FrameBuffer` class where a single frame can be stored, this class is capable of saving multiple frames
 * in a FIFO queue format.
 *
 */
template <uint16_t kSize> class MultiFrameBuffer : public FrameWritePointer
{
public:
    /**
     * This constructor initializes the `MultiFrameBuffer` object.
     *
     */
    MultiFrameBuffer(void)
        : FrameWritePointer()
    {
        Clear();
    }

    /**
     * This method clears the buffer, removing current frame and all previously saved frames.
     *
     * It moves the write pointer to the beginning of the buffer.
     *
     */
    void Clear(void)
    {
        mWriteFrameStart = mBuffer;
        mWritePointer    = mBuffer + kHeaderSize;
        mRemainingLength = kSize - kHeaderSize;

        IgnoreError(SetSkipLength(0));
    }

    /**
     * This method indicates whether the current frame (being written) is empty or not.
     *
     * @retval TRUE  Current frame is empty.
     * @retval FALSE Current frame is not empty.
     *
     */
    bool HasFrame(void) const { return (mWritePointer != GetFrame()); }

    /**
     * This method sets the length (number of bytes) of the current frame being written.
     *
     * param[in] aLength  The length of current frame.
     *
     * @retval OT_ERROR_NONE     Successfully set the length of the current frame.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space to hold a frame of length @p aLength.
     *
     */
    otError SetLength(uint16_t aLength)
    {
        otError error = OT_ERROR_NO_BUFS;

        if (GetFrame() + aLength <= GetArrayEnd(mBuffer))
        {
            mWritePointer    = GetFrame() + aLength;
            mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
            error            = OT_ERROR_NONE;
        }

        return error;
    }

    /**
     * This method gets the length (number of bytes) in the current frame being written into the buffer.
     *
     * @returns The length (number of bytes) in the frame.
     *
     */
    uint16_t GetLength(void) const { return static_cast<uint16_t>(mWritePointer - GetFrame()); }

    /**
     * This method sets the length (number of bytes) of reserved buffer in front of the current frame being written.
     *
     * param[in] aSkipLength  The length of reserved buffer.
     *
     * @retval OT_ERROR_NONE     Successfully set the length of reserved buffer.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space to hold a reserved buffer of length @p aLength.
     *
     */
    otError SetSkipLength(uint16_t aSkipLength)
    {
        otError error = OT_ERROR_NO_BUFS;

        if (mWriteFrameStart + kHeaderSize + aSkipLength <= GetArrayEnd(mBuffer))
        {
            Encoding::LittleEndian::WriteUint16(aSkipLength, mWriteFrameStart + kHeaderSkipLengthOffset);
            mWritePointer    = GetFrame();
            mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
            error            = OT_ERROR_NONE;
        }

        return error;
    }

    /**
     * This method gets the length (number of bytes) of reserved buffer in front of the current frame being written.
     *
     * @returns The length (number of bytes) of the reserved buffer.
     *
     */
    uint16_t GetSkipLength(void) const
    {
        return Encoding::LittleEndian::ReadUint16(mWriteFrameStart + kHeaderSkipLengthOffset);
    }

    /**
     * This method gets a pointer to the start of the current frame.
     *
     * @returns A pointer to the start of the frame.
     *
     */
    uint8_t *GetFrame(void) const { return mWriteFrameStart + kHeaderSize + GetSkipLength(); }

    /**
     * This method gets the maximum length of the current frame.
     *
     * @returns The maximum length of the current frame.
     *
     */
    uint16_t GetFrameMaxLength(void) const { return static_cast<uint16_t>(mBuffer + kSize - GetFrame()); }

    /**
     * This method saves the current frame and prepares the write pointer for a next frame to be written into the
     * buffer.
     *
     * Saved frame can be retrieved later using `GetNextSavedFrame()`.
     *
     */
    void SaveFrame(void)
    {
        Encoding::LittleEndian::WriteUint16(GetSkipLength() + GetLength(), mWriteFrameStart + kHeaderTotalLengthOffset);
        mWriteFrameStart = mWritePointer;
        IgnoreError(SetSkipLength(0));
        mWritePointer    = GetFrame();
        mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
    }

    /**
     * This method discards the current frame and prepares the write pointer for a next frame to be written into the
     * buffer.
     *
     */
    void DiscardFrame(void)
    {
        IgnoreError(SetSkipLength(0));

        mWritePointer    = GetFrame();
        mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
    }

    /**
     * This method indicates whether there are any saved frames in the buffer.
     *
     * @retval TRUE  There is at least one saved frame in the buffer.
     * @retval FALSE There is no saved frame in the buffer.
     *
     */
    bool HasSavedFrame(void) const { return (mWriteFrameStart != mBuffer); }

    /**
     * This method iterates through previously saved frames in the buffer, getting a next frame in the queue.
     *
     * @param[in,out] aFrame   On entry, should point to a previous saved frame or nullptr to get the first frame.
     *                         On exit, the pointer variable is updated to next frame or set to nullptr if there are
     *                         none.
     * @param[in,out] aLength  On entry, should be a reference to the frame length of the previous saved frame.
     *                         On exit, the reference is updated to the frame length (number of bytes) of next frame.
     *
     * @retval OT_ERROR_NONE       Updated @aFrame and @aLength successfully with the next saved frame.
     * @retval OT_ERROR_NOT_FOUND  No more saved frame in the buffer.
     *
     */
    otError GetNextSavedFrame(uint8_t *&aFrame, uint16_t &aLength)
    {
        otError error = OT_ERROR_NONE;

        OT_ASSERT(aFrame == nullptr || (mBuffer <= aFrame && aFrame < GetArrayEnd(mBuffer)));

        aFrame = (aFrame == nullptr) ? mBuffer : aFrame + aLength;

        if (aFrame != mWriteFrameStart)
        {
            uint16_t totalLength = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderTotalLengthOffset);
            uint16_t skipLength  = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderSkipLengthOffset);

            aLength = totalLength - skipLength;
            aFrame += kHeaderSize + skipLength;
        }
        else
        {
            aLength = 0;
            aFrame  = nullptr;
            error   = OT_ERROR_NOT_FOUND;
        }

        return error;
    }

    /**
     * This method clears all saved frames from the buffer and adjusts all the pointers.
     *
     * @note This method moves the pointers into the buffer and also copies the content. Any previously retrieved
     * pointer to buffer (from `GetFrame()` or `GetNextSavedFrame()`) should be considered invalid after calling this
     * method.
     *
     */
    void ClearSavedFrames(void)
    {
        uint16_t len = static_cast<uint16_t>(mWriteFrameStart - mBuffer);

        if (len > 0)
        {
            memmove(mBuffer, mWriteFrameStart, static_cast<uint16_t>(mWritePointer - mWriteFrameStart));
            mWritePointer -= len;
            mWriteFrameStart -= len;
            mRemainingLength += len;
        }
    }

private:
    /*
     * The diagram below illustrates the format of a saved frame.
     *
     *  +---------+-------------+------------+----------------+----------------------------+
     *  | Octets: |      2      |      2     |   SkipLength   |  TotalLength - SkipLength  |
     *  +---------+-------------+------------+----------------+----------------------------+
     *  | Fields: | TotalLength | SkipLength | ReservedBuffer |         FrameBuffer        |
     *  +---------+-------------+------------+----------------+----------------------------+
     *
     *   -  "TotalLength"   : The total length of the `ReservedBuffer` and `FrameBuffer`. It is stored in header bytes
     *                        as a `uint16_t` value using little-endian encoding.
     *   -  "SkipLength"    : The length of the `ReservedBuffer`. It is stored in header bytes as a `uint16_t` value
     *                        using little-endian encoding.
     *   -  "ReservedBuffer": A reserved buffer in front of `FrameBuffer`. User can use it to store extra header, etc.
     *   -  "FrameBuffer"   : Frame buffer.
     *
     * The diagram below illustrates how the frames are saved in the buffer.
     *
     * The diagram shows `mBuffer` and different pointers into the buffer. It represents buffer state when there are
     * two saved frames in the buffer.
     *
     *          Saved frame #1           Saved frame #2       Current frame being written
     *   /                        \ /                      \ /                           \
     *   +-----------+-------------+-----------+------------+---------+--------------------------------------------+
     *   | header #1 |   ...       | header #2 |  ...       | header  |  ...             | ...                     |
     *   +-----------+-------------+-----------+------------+---------+--------------------------------------------+
     *   ^                                                  ^                            ^\                       /^
     *   |                                                  |                            |   mRemainingLength      |
     *  mBuffer[0]                                          mWriteFrameStart             |                         |
     *                                                                                   |              mBuffer[kSize]
     *                                                                                 mWritePointer
     */

    enum
    {
        kHeaderTotalLengthOffset = 0,
        kHeaderSkipLengthOffset  = sizeof(uint16_t),
        kHeaderSize              = sizeof(uint16_t) + sizeof(uint16_t),
    };

    uint8_t  mBuffer[kSize];
    uint8_t *mWriteFrameStart; // Pointer to start of current frame being written.
};

/**
 * This class implements the HDLC-lite encoder.
 *
 */
class Encoder
{
public:
    /**
     * This constructor initializes the object.
     *
     * @param[in] aWritePointer   The `FrameWritePointer` used by `Encoder` to write the encoded frames.
     *
     */
    explicit Encoder(FrameWritePointer &aWritePointer);

    /**
     * This method begins an HDLC frame.
     *
     * @retval OT_ERROR_NONE     Successfully started the HDLC frame.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to start the HDLC frame.
     *
     */
    otError BeginFrame(void);

    /**
     * This method encodes a single byte into current frame.
     *
     * If there is no space to add the byte, the write pointer in frame buffer remains the same.
     *
     * @param[in]    aByte       A byte value to encode and add to frame.
     *
     * @retval OT_ERROR_NONE     Successfully encoded and added the byte to frame buffer.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to encode and add the byte.
     *
     */
    otError Encode(uint8_t aByte);

    /**
     * This method encodes a given block of data into current frame.
     *
     * This method returns success only if there is space in buffer to encode the entire block of data. If there is no
     * space to encode the entire block of data, the write pointer in frame buffer remains the same.
     *
     * @param[in]    aData       A pointer to a buffer containing the data to encode.
     * @param[in]    aLength     The number of bytes in @p aData.
     *
     * @retval OT_ERROR_NONE     Successfully encoded and added the data to frame.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to add the frame.
     *
     */
    otError Encode(const uint8_t *aData, uint16_t aLength);

    /**
     * This method ends/finalizes the HDLC frame.
     *
     * @retval OT_ERROR_NONE     Successfully ended the HDLC frame.
     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to end the HDLC frame.
     *
     */
    otError EndFrame(void);

private:
    FrameWritePointer &mWritePointer;
    uint16_t           mFcs;
};

/**
 * This class implements the HDLC-lite decoder.
 *
 */
class Decoder
{
public:
    /**
     * This function pointer is called when either a complete frame has been decoded or an error occurs during
     * decoding.
     *
     * The decoded frame (or the partially decoded frame in case of an error) is available in `aFrameWritePointer`
     * buffer given in `Decoder` constructor.
     *
     * @param[in] aContext A pointer to arbitrary context information.
     * @param[in] aError   OT_ERROR_NONE    if the frame was decoded successfully,
     *                     OT_ERROR_PARSE   if the Frame Check Sequence (FCS) was incorrect in decoded frame,
     *                     OT_ERROR_NO_BUFS insufficient buffer space available to save the decoded frame.
     *
     */
    typedef void (*FrameHandler)(void *aContext, otError aError);

    /**
     * This constructor initializes the decoder.
     *
     * @param[in] aFrameWritePointer   The `FrameWritePointer` used by `Decoder` to write the decoded frames.
     * @param[in] aFrameHandler        The frame handler callback function pointer.
     * @param[in] aContext             A pointer to arbitrary context information.
     *
     */
    Decoder(FrameWritePointer &aFrameWritePointer, FrameHandler aFrameHandler, void *aContext);

    /**
     * This method feeds a block of data into the decoder.
     *
     * If during decoding, a full HDLC frame is successfully decoded or an error occurs, the `FrameHandler` callback
     * is called. The decoded frame (or the partially decoded frame in case of an error) is available in
     * `aFrameWritePointer` buffer from the constructor. The `Decoder` user (if required) must update/reset the write
     * pointer from this callback for the next frame to be decoded.
     *
     * @param[in]  aData    A pointer to a buffer containing data to be fed to decoder.
     * @param[in]  aLength  The number of bytes in @p aData.
     *
     */
    void Decode(const uint8_t *aData, uint16_t aLength);

    /**
     * This method resets internal states of the decoder.
     *
     */
    void Reset(void);

private:
    enum State
    {
        kStateNoSync,
        kStateSync,
        kStateEscaped,
    };

    State              mState;
    FrameWritePointer &mWritePointer;
    FrameHandler       mFrameHandler;
    void *             mContext;
    uint16_t           mFcs;
    uint16_t           mDecodedLength;
};

} // namespace Hdlc
} // namespace ot

#endif // HDLC_HPP_
