/*
 *
 *    Copyright (c) 2020-2021 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
 *      This file defines structures and utility methods for working with BDX
 *      messages, mainly for writing to and reading from PacketBuffers.
 */

#pragma once

#include <lib/support/BitFlags.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/CodeUtils.h>
#include <protocols/Protocols.h>
#include <system/SystemPacketBuffer.h>

namespace chip {
namespace bdx {

inline constexpr uint16_t kMaxFileDesignatorLen = 0xFF;

inline constexpr char kProtocolName[] = "BDX";

enum class MessageType : uint8_t
{
    SendInit           = 0x01,
    SendAccept         = 0x02,
    ReceiveInit        = 0x04,
    ReceiveAccept      = 0x05,
    BlockQuery         = 0x10,
    Block              = 0x11,
    BlockEOF           = 0x12,
    BlockAck           = 0x13,
    BlockAckEOF        = 0x14,
    BlockQueryWithSkip = 0x15,
};

enum class StatusCode : uint16_t
{
    kLengthTooLarge             = 0x0012,
    kLengthTooShort             = 0x0013,
    kLengthMismatch             = 0x0014,
    kLengthRequired             = 0x0015,
    kBadMessageContents         = 0x0016,
    kBadBlockCounter            = 0x0017,
    kUnexpectedMessage          = 0x0018,
    kResponderBusy              = 0x0019,
    kTransferFailedUnknownError = 0x001F,
    kTransferMethodNotSupported = 0x0050,
    kFileDesignatorUnknown      = 0x0051,
    kStartOffsetNotSupported    = 0x0052,
    kVersionNotSupported        = 0x0053,
    kUnknown                    = 0x005F,
};

enum class TransferControlFlags : uint8_t
{
    // first 4 bits reserved for version
    kSenderDrive   = (1U << 4),
    kReceiverDrive = (1U << 5),
    kAsync         = (1U << 6),
};

enum class RangeControlFlags : uint8_t
{
    kDefLen      = (1U),
    kStartOffset = (1U << 1),
    kWiderange   = (1U << 4),
};

/**
 * @brief
 *   Interface for defining methods that apply to all BDX messages.
 */
struct BdxMessage
{
    /**
     * @brief
     *  Parse data from an PacketBuffer into a BdxMessage struct.
     *
     *  Note that this may store pointers that point into the passed PacketBuffer,
     *  so it is essential that the underlying PacketBuffer is not modified until after this
     *  struct is no longer needed.
     *
     * @param[in] aBuffer A PacketBufferHandle with a reference to the PacketBuffer containing the data.
     *
     * @return CHIP_ERROR Return an error if the message format is invalid and/or can't be parsed
     */
    CHECK_RETURN_VALUE
    virtual CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) = 0;

    /**
     * @brief
     *  Write the message fields to a buffer using the provided BufferWriter.
     *
     *  It is up to the caller to use BufferWriter::Fit() to verify that the write was
     *  successful. This method will also not check for correctness or completeness for
     *  any of the fields - it is the caller's responsibility to ensure that the fields
     *  align with BDX specifications.
     *
     * @param aBuffer A BufferWriter object that will be used to write the message
     */
    virtual Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const = 0;

    /**
     * @brief
     *  Returns the size of buffer needed to write the message.
     */
    virtual size_t MessageSize() const = 0;

#if CHIP_AUTOMATION_LOGGING
    /**
     * @brief
     * Log all parameters for this message.
     */
    virtual void LogMessage(bdx::MessageType messageType) const = 0;
#endif // CHIP_AUTOMATION_LOGGING

    virtual ~BdxMessage() = default;
};

/*
 * A structure for representing a SendInit or ReceiveInit message (both contain
 * identical parameters).
 */
struct TransferInit : public BdxMessage
{
    bool operator==(const TransferInit &) const;

    // Proposed Transfer Control (required)
    BitFlags<TransferControlFlags> TransferCtlOptions;
    uint8_t Version = 0; ///< The highest version supported by the sender

    // Range Control
    BitFlags<RangeControlFlags> mRangeCtlFlags;

    // All required
    uint16_t MaxBlockSize = 0; ///< Proposed max block size to use in transfer
    uint64_t StartOffset  = 0; ///< Proposed start offset of data. 0 for no offset
    uint64_t MaxLength    = 0; ///< Proposed max length of data in transfer, 0 for indefinite

    // File designator (required) and additional metadata (optional, TLV format)
    // WARNING: there is no guarantee at any point that these pointers will point to valid memory. The Buffer field should be used
    // to hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
    const uint8_t * FileDesignator = nullptr;
    uint16_t FileDesLength         = 0; ///< Length of file designator string (not including null-terminator)
    const uint8_t * Metadata       = nullptr;
    size_t MetadataLength          = 0;

    // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
    System::PacketBufferHandle Buffer;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

using SendInit    = TransferInit;
using ReceiveInit = TransferInit;

/*
 * A structure for representing a SendAccept message.
 */
struct SendAccept : public BdxMessage
{
    bool operator==(const SendAccept &) const;

    // Transfer Control (required, only one should be set)
    BitFlags<TransferControlFlags> TransferCtlFlags;

    uint8_t Version       = 0; ///< The agreed upon version for the transfer (required)
    uint16_t MaxBlockSize = 0; ///< Chosen max block size to use in transfer (required)

    // Additional metadata (optional, TLV format)
    // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
    // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
    const uint8_t * Metadata = nullptr;
    size_t MetadataLength    = 0;

    // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
    System::PacketBufferHandle Buffer;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

/**
 * A structure for representing ReceiveAccept messages.
 */
struct ReceiveAccept : public BdxMessage
{
    bool operator==(const ReceiveAccept &) const;

    // Transfer Control (required, only one should be set)
    BitFlags<TransferControlFlags> TransferCtlFlags;

    // Range Control
    BitFlags<RangeControlFlags> mRangeCtlFlags;

    // All required
    uint8_t Version       = 0; ///< The agreed upon version for the transfer
    uint16_t MaxBlockSize = 0; ///< Chosen max block size to use in transfer
    uint64_t StartOffset  = 0; ///< Chosen start offset of data. 0 for no offset.
    uint64_t Length       = 0; ///< Length of transfer. 0 if length is indefinite.

    // Additional metadata (optional, TLV format)
    // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
    // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
    const uint8_t * Metadata = nullptr;
    size_t MetadataLength    = 0;

    // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
    System::PacketBufferHandle Buffer;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

/**
 * A struct for representing messages contiaining just a counter field. Can be used to
 * represent BlockQuery, BlockAck, and BlockAckEOF.
 */
struct CounterMessage : public BdxMessage
{
    bool operator==(const CounterMessage &) const;

    uint32_t BlockCounter = 0;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

using BlockQuery  = CounterMessage;
using BlockAck    = CounterMessage;
using BlockAckEOF = CounterMessage;

/**
 * A struct that represents a message containing actual data (Block, BlockEOF).
 */
struct DataBlock : public BdxMessage
{
    bool operator==(const DataBlock &) const;

    uint32_t BlockCounter = 0;

    // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
    // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
    const uint8_t * Data = nullptr;
    size_t DataLength    = 0;

    // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
    System::PacketBufferHandle Buffer;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

using Block    = DataBlock;
using BlockEOF = DataBlock;

struct BlockQueryWithSkip : public BdxMessage
{
    bool operator==(const BlockQueryWithSkip &) const;

    uint32_t BlockCounter = 0;
    uint64_t BytesToSkip  = 0;

    CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
    Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
    size_t MessageSize() const override;
#if CHIP_AUTOMATION_LOGGING
    void LogMessage(bdx::MessageType messageType) const override;
#endif // CHIP_AUTOMATION_LOGGING
};

} // namespace bdx

namespace Protocols {
template <>
struct MessageTypeTraits<bdx::MessageType>
{
    static constexpr const Protocols::Id & ProtocolId() { return BDX::Id; }

    static auto GetTypeToNameTable()
    {
        static const std::array<MessageTypeNameLookup, 10> typeToNameTable = {
            {
                { bdx::MessageType::SendInit, "SendInit" },
                { bdx::MessageType::SendAccept, "SendAccept" },
                { bdx::MessageType::ReceiveInit, "ReceiveInit" },
                { bdx::MessageType::ReceiveAccept, "ReceiveAccept" },
                { bdx::MessageType::BlockQuery, "BlockQuery" },
                { bdx::MessageType::Block, "Block" },
                { bdx::MessageType::BlockEOF, "BlockEOF" },
                { bdx::MessageType::BlockAck, "BlockAck" },
                { bdx::MessageType::BlockAckEOF, "BlockAckEOF" },
                { bdx::MessageType::BlockQueryWithSkip, "BlockQueryWithSkip" },
            },
        };

        return &typeToNameTable;
    }
};
} // namespace Protocols

} // namespace chip
