/*
 *    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 implements NCP frame buffer class.
 */

#include "ncp_buffer.hpp"

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "utils/wrap_string.h"

namespace ot {
namespace Ncp {

const NcpFrameBuffer::FrameTag NcpFrameBuffer::kInvalidTag = NULL;

NcpFrameBuffer::NcpFrameBuffer(uint8_t *aBuffer, uint16_t aBufferLength)
    : mBuffer(aBuffer)
    , mBufferEnd(aBuffer + aBufferLength)
    , mBufferLength(aBufferLength)
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
    for (uint8_t priority = 0; priority < kNumPrios; priority++)
    {
        otMessageQueueInit(&mMessageQueue[priority]);
    }

    otMessageQueueInit(&mWriteFrameMessageQueue);
#endif

    SetFrameAddedCallback(NULL, NULL);
    SetFrameRemovedCallback(NULL, NULL);
    Clear();
}

void NcpFrameBuffer::Clear(void)
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
    otMessage *message;
#endif

    // Write (InFrame) related variables
    mWriteFrameStart[kPriorityLow]  = mBuffer;
    mWriteFrameStart[kPriorityHigh] = GetUpdatedBufPtr(mBuffer, 1, kBackward);
    mWriteDirection                 = kUnknown;
    mWriteSegmentHead               = mBuffer;
    mWriteSegmentTail               = mBuffer;
    mWriteFrameTag                  = kInvalidTag;

    // Read (OutFrame) related variables
    mReadDirection   = kForward;
    mReadState       = kReadStateNotActive;
    mReadFrameLength = kUnknownFrameLength;

    mReadFrameStart[kPriorityLow]  = mBuffer;
    mReadFrameStart[kPriorityHigh] = GetUpdatedBufPtr(mBuffer, 1, kBackward);
    mReadSegmentHead               = mBuffer;
    mReadSegmentTail               = mBuffer;
    mReadPointer                   = mBuffer;

#if OPENTHREAD_MTD || OPENTHREAD_FTD
    mReadMessage       = NULL;
    mReadMessageOffset = 0;
    mReadMessageTail   = mMessageBuffer;

    // Free all messages in the queues.

    while ((message = otMessageQueueGetHead(&mWriteFrameMessageQueue)) != NULL)
    {
        otMessageQueueDequeue(&mWriteFrameMessageQueue, message);

        // Note that messages associated with current (unfinished) input frame
        // are not yet owned by the `NcpFrameBuffer` and therefore should not
        // be freed.
    }

    for (uint8_t priority = 0; priority < kNumPrios; priority++)
    {
        while ((message = otMessageQueueGetHead(&mMessageQueue[priority])) != NULL)
        {
            otMessageQueueDequeue(&mMessageQueue[priority], message);
            otMessageFree(message);
        }
    }
#endif
}

void NcpFrameBuffer::SetFrameAddedCallback(BufferCallback aFrameAddedCallback, void *aFrameAddedContext)
{
    mFrameAddedCallback = aFrameAddedCallback;
    mFrameAddedContext  = aFrameAddedContext;
}

void NcpFrameBuffer::SetFrameRemovedCallback(BufferCallback aFrameRemovedCallback, void *aFrameRemovedContext)
{
    mFrameRemovedCallback = aFrameRemovedCallback;
    mFrameRemovedContext  = aFrameRemovedContext;
}

// Returns an updated buffer pointer by moving forward/backward (based on `aDirection`) from `aBufPtr` by a given
// offset. The resulting buffer pointer is ensured to stay within the `mBuffer` boundaries.
uint8_t *NcpFrameBuffer::GetUpdatedBufPtr(uint8_t *aBufPtr, uint16_t aOffset, Direction aDirection) const
{
    uint8_t *ptr = aBufPtr;

    switch (aDirection)
    {
    case kForward:
        ptr += aOffset;

        while (ptr >= mBufferEnd)
        {
            ptr -= mBufferLength;
        }

        break;

    case kBackward:
        ptr -= aOffset;

        while (ptr < mBuffer)
        {
            ptr += mBufferLength;
        }

        break;

    case kUnknown:
        assert(false);
        break;
    }

    return ptr;
}

// Gets the distance between two buffer pointers (adjusts for the wrap-around) given a direction (forward or backward).
uint16_t NcpFrameBuffer::GetDistance(const uint8_t *aStartPtr, const uint8_t *aEndPtr, Direction aDirection) const
{
    size_t distance = 0;

    switch (aDirection)
    {
    case kForward:

        if (aEndPtr >= aStartPtr)
        {
            distance = static_cast<size_t>(aEndPtr - aStartPtr);
        }
        else
        {
            distance = static_cast<size_t>(mBufferEnd - aStartPtr);
            distance += static_cast<size_t>(aEndPtr - mBuffer);
        }

        break;

    case kBackward:

        if (aEndPtr <= aStartPtr)
        {
            distance = static_cast<size_t>(aStartPtr - aEndPtr);
        }
        else
        {
            distance = static_cast<size_t>(mBufferEnd - aEndPtr);
            distance += static_cast<size_t>(aStartPtr - mBuffer);
        }

        break;

    case kUnknown:
        assert(false);
        break;
    }

    return static_cast<uint16_t>(distance);
}

// Writes a uint16 value at the given buffer pointer (big-endian style).
void NcpFrameBuffer::WriteUint16At(uint8_t *aBufPtr, uint16_t aValue, Direction aDirection)
{
    *aBufPtr                                  = (aValue >> 8);
    *GetUpdatedBufPtr(aBufPtr, 1, aDirection) = (aValue & 0xff);
}

// Reads a uint16 value at the given buffer pointer (big-endian style).
uint16_t NcpFrameBuffer::ReadUint16At(uint8_t *aBufPtr, Direction aDirection)
{
    uint16_t value;

    value = static_cast<uint16_t>((*aBufPtr) << 8);
    value += *GetUpdatedBufPtr(aBufPtr, 1, aDirection);

    return value;
}

// Appends a byte at the write tail and updates the tail, discards the frame if buffer gets full.
otError NcpFrameBuffer::InFrameAppend(uint8_t aByte)
{
    otError  error = OT_ERROR_NONE;
    uint8_t *newTail;

    assert(mWriteDirection != kUnknown);

    newTail = GetUpdatedBufPtr(mWriteSegmentTail, 1, mWriteDirection);

    // Ensure the `newTail` has not reached the `mWriteFrameStart` for other direction (other priority level).
    if (newTail != mWriteFrameStart[(mWriteDirection == kForward) ? kBackward : kForward])
    {
        *mWriteSegmentTail = aByte;
        mWriteSegmentTail  = newTail;
    }
    else
    {
        error = OT_ERROR_NO_BUFS;
        InFrameDiscard();
    }

    return error;
}

// This method begins a new segment (if one is not already open).
otError NcpFrameBuffer::InFrameBeginSegment(void)
{
    otError  error       = OT_ERROR_NONE;
    uint16_t headerFlags = kSegmentHeaderNoFlag;

    // Verify that segment is not yet started (i.e., head and tail are the same).
    VerifyOrExit(mWriteSegmentHead == mWriteSegmentTail);

    // Check if this is the start of a new frame (i.e., frame start is same as segment head).
    if (mWriteFrameStart[mWriteDirection] == mWriteSegmentHead)
    {
        headerFlags |= kSegmentHeaderNewFrameFlag;
    }

    // Reserve space for the segment header.
    for (uint16_t i = kSegmentHeaderSize; i; i--)
    {
        SuccessOrExit(error = InFrameAppend(0));
    }

    // Write the flags at the segment head.
    WriteUint16At(mWriteSegmentHead, headerFlags, mWriteDirection);

exit:
    return error;
}

// This function closes/ends the current segment.
void NcpFrameBuffer::InFrameEndSegment(uint16_t aSegmentHeaderFlags)
{
    uint16_t segmentLength;
    uint16_t header;

    segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);

    if (segmentLength >= kSegmentHeaderSize)
    {
        // Reduce the header size.
        segmentLength -= kSegmentHeaderSize;

        // Update the length and the flags in segment header (at segment head pointer).
        header = ReadUint16At(mWriteSegmentHead, mWriteDirection);
        header |= (segmentLength & kSegmentHeaderLengthMask);
        header |= aSegmentHeaderFlags;
        WriteUint16At(mWriteSegmentHead, header, mWriteDirection);

        // Move the segment head to current tail (to be ready for a possible next segment).
        mWriteSegmentHead = mWriteSegmentTail;
    }
    else
    {
        // Remove the current segment (move the tail back to head).
        mWriteSegmentTail = mWriteSegmentHead;
    }
}

// This method discards the current frame being written.
void NcpFrameBuffer::InFrameDiscard(void)
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
    otMessage *message;
#endif

    VerifyOrExit(mWriteDirection != kUnknown);

    // Move the write segment head and tail pointers back to frame start.
    mWriteSegmentHead = mWriteSegmentTail = mWriteFrameStart[mWriteDirection];

#if OPENTHREAD_MTD || OPENTHREAD_FTD
    while ((message = otMessageQueueGetHead(&mWriteFrameMessageQueue)) != NULL)
    {
        otMessageQueueDequeue(&mWriteFrameMessageQueue, message);

        // Note that messages associated with current (unfinished) input frame
        // being discarded, are not yet owned by the `NcpFrameBuffer` and
        // therefore should not be freed.
    }
#endif

    mWriteDirection = kUnknown;

exit:
    UpdateReadWriteStartPointers();
}

// Returns `true` if in middle of writing a frame with given priority.
bool NcpFrameBuffer::InFrameIsWriting(Priority aPriority) const
{
    return (mWriteDirection == static_cast<Direction>(aPriority));
}

void NcpFrameBuffer::InFrameBegin(Priority aPriority)
{
    // Discard any previous unfinished frame.
    InFrameDiscard();

    switch (aPriority)
    {
    case kPriorityHigh:
        mWriteDirection = kBackward;
        break;

    case kPriorityLow:
        mWriteDirection = kForward;
        break;
    }

    // Set up the segment head and tail
    mWriteSegmentHead = mWriteSegmentTail = mWriteFrameStart[mWriteDirection];
}

otError NcpFrameBuffer::InFrameFeedByte(uint8_t aByte)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    // Begin a new segment (if we are not in middle of segment already).
    SuccessOrExit(error = InFrameBeginSegment());

    error = InFrameAppend(aByte);

exit:
    return error;
}

otError NcpFrameBuffer::InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    // Begin a new segment (if we are not in middle of segment already).
    SuccessOrExit(error = InFrameBeginSegment());

    // Write the data buffer
    while (aDataBufferLength--)
    {
        SuccessOrExit(error = InFrameAppend(*aDataBuffer++));
    }

exit:
    return error;
}

#if OPENTHREAD_MTD || OPENTHREAD_FTD
otError NcpFrameBuffer::InFrameFeedMessage(otMessage *aMessage)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aMessage != NULL, error = OT_ERROR_INVALID_ARGS);
    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    // Begin a new segment (if we are not in middle of segment already).
    SuccessOrExit(error = InFrameBeginSegment());

    // Enqueue the message in the current write frame queue.
    SuccessOrExit(error = otMessageQueueEnqueue(&mWriteFrameMessageQueue, aMessage));

    // End/Close the current segment marking the flag that it contains an associated message.
    InFrameEndSegment(kSegmentHeaderMessageIndicatorFlag);

exit:
    return error;
}
#endif

otError NcpFrameBuffer::InFrameGetPosition(WritePosition &aPosition)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    // Begin a new segment (if we are not in middle of segment already).
    SuccessOrExit(error = InFrameBeginSegment());

    aPosition.mPosition    = mWriteSegmentTail;
    aPosition.mSegmentHead = mWriteSegmentHead;

exit:
    return error;
}

otError NcpFrameBuffer::InFrameOverwrite(const WritePosition &aPosition,
                                         const uint8_t *      aDataBuffer,
                                         uint16_t             aDataBufferLength)
{
    otError  error = OT_ERROR_NONE;
    uint8_t *bufPtr;
    uint16_t segmentLength;
    uint16_t distance;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead, error = OT_ERROR_INVALID_ARGS);

    // Ensure the overwrite does not go beyond current segment tail.
    segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
    distance      = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
    VerifyOrExit(distance + aDataBufferLength <= segmentLength, error = OT_ERROR_INVALID_ARGS);

    bufPtr = aPosition.mPosition;
    while (aDataBufferLength > 0)
    {
        *bufPtr = *aDataBuffer;

        aDataBuffer++;
        aDataBufferLength--;

        bufPtr = GetUpdatedBufPtr(bufPtr, 1, mWriteDirection);
    }

exit:
    return error;
}

uint16_t NcpFrameBuffer::InFrameGetDistance(const WritePosition &aPosition) const
{
    uint16_t distance = 0;
    uint16_t segmentLength;
    uint16_t offset;

    VerifyOrExit(mWriteDirection != kUnknown);
    VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead);

    segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
    offset        = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
    VerifyOrExit(offset < segmentLength);

    distance = GetDistance(aPosition.mPosition, mWriteSegmentTail, mWriteDirection);

exit:
    return distance;
}

otError NcpFrameBuffer::InFrameReset(const WritePosition &aPosition)
{
    otError  error = OT_ERROR_NONE;
    uint16_t segmentLength;
    uint16_t offset;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
    VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead, error = OT_ERROR_INVALID_ARGS);

    segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
    offset        = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
    VerifyOrExit(offset < segmentLength, error = OT_ERROR_INVALID_ARGS);

    mWriteSegmentTail = aPosition.mPosition;

exit:
    return error;
}

otError NcpFrameBuffer::InFrameEnd(void)
{
#if OPENTHREAD_MTD || OPENTHREAD_FTD
    otMessage *message;
#endif
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);

    // End/Close the current segment (if any).
    InFrameEndSegment(kSegmentHeaderNoFlag);

    // Save and use the frame start pointer as the tag associated with the frame.
    mWriteFrameTag = mWriteFrameStart[mWriteDirection];

    // Update the frame start pointer to current segment head to be ready for next frame.
    mWriteFrameStart[mWriteDirection] = mWriteSegmentHead;

#if OPENTHREAD_MTD || OPENTHREAD_FTD
    // Move all the messages from the frame queue to the main queue.
    while ((message = otMessageQueueGetHead(&mWriteFrameMessageQueue)) != NULL)
    {
        otMessageQueueDequeue(&mWriteFrameMessageQueue, message);
        otMessageQueueEnqueue(&mMessageQueue[mWriteDirection], message);
    }
#endif

    if (mFrameAddedCallback != NULL)
    {
        mFrameAddedCallback(mFrameAddedContext, mWriteFrameTag, static_cast<Priority>(mWriteDirection), this);
    }

    mWriteDirection = kUnknown;

exit:
    return error;
}

NcpFrameBuffer::FrameTag NcpFrameBuffer::InFrameGetLastTag(void) const
{
    return mWriteFrameTag;
}

bool NcpFrameBuffer::HasFrame(Priority aPriority) const
{
    return mReadFrameStart[aPriority] != mWriteFrameStart[aPriority];
}

bool NcpFrameBuffer::IsEmpty(void) const
{
    return !HasFrame(kPriorityHigh) && !HasFrame(kPriorityLow);
}

void NcpFrameBuffer::OutFrameSelectReadDirection(void)
{
    if (mReadState == kReadStateNotActive)
    {
        mReadDirection = HasFrame(kPriorityHigh) ? kBackward : kForward;
    }
}

// Start/Prepare a new segment for reading.
otError NcpFrameBuffer::OutFramePrepareSegment(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t header;

    while (true)
    {
        // Go to the next segment (set the segment head to current segment's end/tail).
        mReadSegmentHead = mReadSegmentTail;

        // Ensure there is something to read (i.e. segment head is not at start of frame being written).
        VerifyOrExit(mReadSegmentHead != mWriteFrameStart[mReadDirection], error = OT_ERROR_NOT_FOUND);

        // Read the segment header.
        header = ReadUint16At(mReadSegmentHead, mReadDirection);

        // Check if this segment is the start of a frame.
        if (header & kSegmentHeaderNewFrameFlag)
        {
            // Ensure that this segment is start of current frame, otherwise the current frame is finished.
            VerifyOrExit(mReadSegmentHead == mReadFrameStart[mReadDirection], error = OT_ERROR_NOT_FOUND);
        }

        // Find tail/end of current segment.
        mReadSegmentTail = GetUpdatedBufPtr(mReadSegmentHead, kSegmentHeaderSize + (header & kSegmentHeaderLengthMask),
                                            mReadDirection);

        // Update the current read pointer to skip the segment header.
        mReadPointer = GetUpdatedBufPtr(mReadSegmentHead, kSegmentHeaderSize, mReadDirection);

        // Check if there are data bytes to be read in this segment (i.e. read pointer not at the tail).
        if (mReadPointer != mReadSegmentTail)
        {
            // Update the state to `InSegment` and return.
            mReadState = kReadStateInSegment;

            ExitNow();
        }

#if OPENTHREAD_MTD || OPENTHREAD_FTD
        // No data in this segment,  prepare any appended/associated message of this segment.
        if (OutFramePrepareMessage() == OT_ERROR_NONE)
        {
            ExitNow();
        }

        // If there is no message (`PrepareMessage()` returned an error), loop back to prepare the next segment.
#endif
    }

exit:

    if (error != OT_ERROR_NONE)
    {
        mReadState = kReadStateDone;
    }

    return error;
}

#if OPENTHREAD_MTD || OPENTHREAD_FTD
// This method prepares an associated message in current segment and fills the message buffer. It returns
// ThreadError_NotFound if there is no message or if the message has no content.
otError NcpFrameBuffer::OutFramePrepareMessage(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t header;

    // Read the segment header
    header = ReadUint16At(mReadSegmentHead, mReadDirection);

    // Ensure that the segment header indicates that there is an associated message or return `NotFound` error.
    VerifyOrExit((header & kSegmentHeaderMessageIndicatorFlag) != 0, error = OT_ERROR_NOT_FOUND);

    // Update the current message from the queue.
    mReadMessage = (mReadMessage == NULL) ? otMessageQueueGetHead(&mMessageQueue[mReadDirection])
                                          : otMessageQueueGetNext(&mMessageQueue[mReadDirection], mReadMessage);

    VerifyOrExit(mReadMessage != NULL, error = OT_ERROR_NOT_FOUND);

    // Reset the offset for reading the message.
    mReadMessageOffset = 0;

    // Fill the content from current message into the message buffer.
    SuccessOrExit(error = OutFrameFillMessageBuffer());

    // If all successful, set the state to `InMessage`.
    mReadState = kReadStateInMessage;

exit:
    return error;
}

// This method fills content from current message into the message buffer. It returns OT_ERROR_NOT_FOUND if no more
// content in the current message.
otError NcpFrameBuffer::OutFrameFillMessageBuffer(void)
{
    otError error = OT_ERROR_NONE;
    int     readLength;

    VerifyOrExit(mReadMessage != NULL, error = OT_ERROR_NOT_FOUND);

    VerifyOrExit(mReadMessageOffset < otMessageGetLength(mReadMessage), error = OT_ERROR_NOT_FOUND);

    // Read portion of current message from the offset into message buffer.
    readLength = otMessageRead(mReadMessage, mReadMessageOffset, mMessageBuffer, sizeof(mMessageBuffer));

    VerifyOrExit(readLength > 0, error = OT_ERROR_NOT_FOUND);

    // Update the message offset, set up the message tail, and set read pointer to start of message buffer.

    mReadMessageOffset += readLength;

    mReadMessageTail = mMessageBuffer + readLength;

    mReadPointer = mMessageBuffer;

exit:
    return error;
}
#endif // #if OPENTHREAD_MTD || OPENTHREAD_FTD

otError NcpFrameBuffer::OutFrameBegin(void)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(!IsEmpty(), error = OT_ERROR_NOT_FOUND);

    OutFrameSelectReadDirection();

    // Move the segment head and tail to start of frame.
    mReadSegmentHead = mReadSegmentTail = mReadFrameStart[mReadDirection];

#if OPENTHREAD_MTD || OPENTHREAD_FTD
    mReadMessage = NULL;
#endif

    // Prepare the current segment for reading.
    error = OutFramePrepareSegment();

exit:
    return error;
}

bool NcpFrameBuffer::OutFrameHasEnded(void)
{
    return (mReadState == kReadStateDone) || (mReadState == kReadStateNotActive);
}

uint8_t NcpFrameBuffer::OutFrameReadByte(void)
{
    otError error;
    uint8_t retval = kReadByteAfterFrameHasEnded;

    switch (mReadState)
    {
    case kReadStateNotActive:

        // Fall through

    case kReadStateDone:

        retval = kReadByteAfterFrameHasEnded;

        break;

    case kReadStateInSegment:

        // Read a byte from current read pointer and move the read pointer by 1 byte in the read direction.
        retval       = *mReadPointer;
        mReadPointer = GetUpdatedBufPtr(mReadPointer, 1, mReadDirection);

        // Check if at end of current segment.
        if (mReadPointer == mReadSegmentTail)
        {
#if OPENTHREAD_MTD || OPENTHREAD_FTD
            // Prepare any message associated with this segment.
            error = OutFramePrepareMessage();
#else
            error = OT_ERROR_NOT_FOUND;
#endif

            // If there is no message, move to next segment (if any).
            if (error != OT_ERROR_NONE)
            {
                OutFramePrepareSegment();
            }
        }

        break;

    case kReadStateInMessage:
#if OPENTHREAD_MTD || OPENTHREAD_FTD
        // Read a byte from current read pointer and move the read pointer by 1 byte.
        retval = *mReadPointer;
        mReadPointer++;

        // Check if at the end of content in message buffer.
        if (mReadPointer == mReadMessageTail)
        {
            // Fill more bytes from current message into message buffer.
            error = OutFrameFillMessageBuffer();

            // If no more bytes in the message, move to next segment (if any).
            if (error != OT_ERROR_NONE)
            {
                OutFramePrepareSegment();
            }
        }
#endif
        break;
    }

    return retval;
}

uint16_t NcpFrameBuffer::OutFrameRead(uint16_t aReadLength, uint8_t *aDataBuffer)
{
    uint16_t bytesRead = 0;

    for (bytesRead = 0; (bytesRead < aReadLength) && !OutFrameHasEnded(); bytesRead++)
    {
        *aDataBuffer++ = OutFrameReadByte();
    }

    return bytesRead;
}

otError NcpFrameBuffer::OutFrameRemove(void)
{
    otError  error = OT_ERROR_NONE;
    uint8_t *bufPtr;
    uint16_t header;
    uint8_t  numSegments;
    FrameTag tag;

    VerifyOrExit(!IsEmpty(), error = OT_ERROR_NOT_FOUND);

    OutFrameSelectReadDirection();

    // Save the frame start pointer as the tag associated with the frame being removed.
    tag = mReadFrameStart[mReadDirection];

    // Begin at the start of current frame and move through all segments.

    bufPtr      = mReadFrameStart[mReadDirection];
    numSegments = 0;

    while (bufPtr != mWriteFrameStart[mReadDirection])
    {
        // Read the segment header
        header = ReadUint16At(bufPtr, mReadDirection);

        // If the current segment defines a new frame, and it is not the start of current frame, then we have reached
        // end of current frame.
        if (header & kSegmentHeaderNewFrameFlag)
        {
            if (bufPtr != mReadFrameStart[mReadDirection])
            {
                break;
            }
        }

#if OPENTHREAD_MTD || OPENTHREAD_FTD
        // If current segment has an appended message, remove it from message queue and free it.
        if (header & kSegmentHeaderMessageIndicatorFlag)
        {
            otMessage *message;

            if ((message = otMessageQueueGetHead(&mMessageQueue[mReadDirection])) != NULL)
            {
                otMessageQueueDequeue(&mMessageQueue[mReadDirection], message);
                otMessageFree(message);
            }
        }
#endif

        // Move the pointer to next segment.
        bufPtr = GetUpdatedBufPtr(bufPtr, kSegmentHeaderSize + (header & kSegmentHeaderLengthMask), mReadDirection);

        numSegments++;

        // If this assert fails, it is a likely indicator that the internal structure of the NCP buffer has been
        // corrupted.
        assert(numSegments <= kMaxSegments);
    }

    mReadFrameStart[mReadDirection] = bufPtr;

    UpdateReadWriteStartPointers();

    mReadState       = kReadStateNotActive;
    mReadFrameLength = kUnknownFrameLength;

    if (mFrameRemovedCallback != NULL)
    {
        mFrameRemovedCallback(mFrameRemovedContext, tag, static_cast<Priority>(mReadDirection), this);
    }

exit:
    return error;
}

void NcpFrameBuffer::UpdateReadWriteStartPointers(void)
{
    // If there is no fully written high priority frame, and not in middle of writing a new frame either.
    if (!HasFrame(kPriorityHigh) && !InFrameIsWriting(kPriorityHigh))
    {
        // Move the high priority pointers to be right behind the low priority start.
        mWriteFrameStart[kPriorityHigh] = GetUpdatedBufPtr(mReadFrameStart[kPriorityLow], 1, kBackward);
        mReadFrameStart[kPriorityHigh]  = mWriteFrameStart[kPriorityHigh];
        ExitNow();
    }

    // If there is no fully written low priority frame, and not in middle of writing a new frame either.
    if (!HasFrame(kPriorityLow) && !InFrameIsWriting(kPriorityLow))
    {
        // Move the low priority pointers to be 1 byte after the high priority start.
        mWriteFrameStart[kPriorityLow] = GetUpdatedBufPtr(mReadFrameStart[kPriorityHigh], 1, kForward);
        mReadFrameStart[kPriorityLow]  = mWriteFrameStart[kPriorityLow];
    }

exit:
    return;
}

uint16_t NcpFrameBuffer::OutFrameGetLength(void)
{
    uint16_t frameLength = 0;
    uint16_t header;
    uint8_t *bufPtr;
    uint8_t  numSegments;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
    otMessage *message = NULL;
#endif

    // If the frame length was calculated before, return the previously calculated length.
    VerifyOrExit(mReadFrameLength == kUnknownFrameLength, frameLength = mReadFrameLength);

    VerifyOrExit(!IsEmpty(), frameLength = 0);

    OutFrameSelectReadDirection();

    // Calculate frame length by adding length of all segments and messages within the current frame.

    bufPtr      = mReadFrameStart[mReadDirection];
    numSegments = 0;

    while (bufPtr != mWriteFrameStart[mReadDirection])
    {
        // Read the segment header
        header = ReadUint16At(bufPtr, mReadDirection);

        // If the current segment defines a new frame, and it is not the start of current frame, then we have reached
        // end of current frame.
        if (header & kSegmentHeaderNewFrameFlag)
        {
            if (bufPtr != mReadFrameStart[mReadDirection])
            {
                break;
            }
        }

#if OPENTHREAD_MTD || OPENTHREAD_FTD
        // If current segment has an associated message, add its length to frame length.
        if (header & kSegmentHeaderMessageIndicatorFlag)
        {
            message = (message == NULL) ? otMessageQueueGetHead(&mMessageQueue[mReadDirection])
                                        : otMessageQueueGetNext(&mMessageQueue[mReadDirection], message);

            if (message != NULL)
            {
                frameLength += otMessageGetLength(message);
            }
        }
#endif

        // Add the length of current segment to the frame length.
        frameLength += (header & kSegmentHeaderLengthMask);

        // Move the pointer to next segment.
        bufPtr = GetUpdatedBufPtr(bufPtr, kSegmentHeaderSize + (header & kSegmentHeaderLengthMask), mReadDirection);

        numSegments++;

        // If this assert fails, it is a likely indicator that the internal structure of the NCP buffer has been
        // corrupted.
        assert(numSegments <= kMaxSegments);
    }

    // Remember the calculated frame length for current active frame.
    if (mReadState != kReadStateNotActive)
    {
        mReadFrameLength = frameLength;
    }

exit:
    return frameLength;
}

NcpFrameBuffer::FrameTag NcpFrameBuffer::OutFrameGetTag(void)
{
    OutFrameSelectReadDirection();

    // If buffer is empty use `kInvalidTag`, otherwise use the frame start pointer as the tag associated with
    // current out frame being read

    return IsEmpty() ? kInvalidTag : mReadFrameStart[mReadDirection];
}

} // namespace Ncp
} // namespace ot
