/**
 * @file UDPStreamerClient.h
 * @brief Header file for class UDPStreamerClient
 * @date 24/06/2026
 * @author Martino Ferrari
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.
 *
 * @details This header file contains the declaration of the class UDPStreamerClient
 * with all of its public, protected and private members.
 *
 * The UDPStreamerClient is an input DataSource that receives signal data from
 * a UDPStreamer server over the network. It reuses the StreamHub hub's network
 * code base: transport, fragment reassembly, multicast and auto-reconnect are
 * delegated to the shared UDPSClient receiver, and this class only implements
 * the UDPSClientListener callbacks to validate the CONFIG and decode DATA into
 * the real-time signal memory.
 */

#ifndef UDPSTREAMERCLIENT_H_
#define UDPSTREAMERCLIENT_H_

/*---------------------------------------------------------------------------*/
/*                        Standard header includes                           */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                        Project header includes                            */
/*---------------------------------------------------------------------------*/
#include "EventSem.h"
#include "FastPollingMutexSem.h"
#include "MemoryDataSourceI.h"
#include "StreamString.h"
#include "TypeDescriptor.h"
#include "UDPSClient.h"

/*---------------------------------------------------------------------------*/
/*                           Class declaration                               */
/*---------------------------------------------------------------------------*/

namespace MARTe {

/**
 * @brief Per-signal decode metadata resolved from the server CONFIG packet.
 */
struct UDPStreamerClientSignal {
    StreamString   name;          /**< Signal name (must match server). */
    TypeDescriptor type;          /**< MARTe2 destination type. */
    uint8          quantType;     /**< UDPS_QUANT_* code from CONFIG. */
    uint32         numElements;   /**< Element count (scalar = 1). */
    float64        rangeMin;      /**< Dequantisation lower bound. */
    float64        rangeMax;      /**< Dequantisation upper bound. */
    uint32         srcByteSize;   /**< Destination byte size for the signal. */
    uint32         wireElemBytes; /**< Bytes per element on the wire. */
    uint32         bufferOffset;  /**< Offset of this signal in the flat buffer. */
};

/**
 * @brief A DataSource that receives signal data from a UDPStreamer server.
 *
 * @details This input DataSource owns a shared ::MARTe::UDPSClient (the same
 * receiver used by the StreamHub hub) which runs a background thread, connects
 * to the server, reassembles fragmented updates and auto-reconnects on silence.
 * The CONFIG and DATA payloads are delivered through the UDPSClientListener
 * callbacks; DATA is decoded into a double-buffered staging area which the
 * real-time thread copies into signal memory during Synchronise().
 *
 * Two operating modes are selected by the presence or absence of MulticastGroup.
 *
 * @par Top-level configuration parameters
 * | Parameter       | Type    | Default      | Description |
 * |-----------------|---------|--------------|-------------|
 * | ServerAddress   | string  | "127.0.0.1"  | UDPStreamer server IP address. |
 * | Port            | uint16  | 44500        | Server port (CONNECT/UDP unicast, TCP control multicast). |
 * | MulticastGroup  | string  | *(absent)*   | Enables multicast mode. IPv4 multicast address. |
 * | DataPort        | uint16  | Port+1       | UDP port for DATA datagrams in multicast mode. |
 * | MaxPayloadSize  | uint32  | 1400         | Maximum payload bytes per datagram (excluding header). |
 * | CPUMask         | uint32  | 0xFFFFFFFF   | CPU affinity bitmask for the background thread. |
 * | StackSize       | uint32  | 65536        | Stack size in bytes for the background thread. |
 *
 * The client's signal configuration must match the server's: signal count,
 * names and element counts are validated against the received CONFIG.
 */
class UDPStreamerClient : public MemoryDataSourceI,
                          public UDPSClientListener {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief Constructor. Initialises all members to safe defaults.
     */
    UDPStreamerClient();

    /**
     * @brief Destructor. Stops the background receiver and frees memory.
     */
    virtual ~UDPStreamerClient();

    /**
     * @brief Parses top-level configuration and configures the UDPSClient.
     */
    virtual bool Initialise(StructuredDataI &data);

    /**
     * @brief Validates signal types and builds the per-signal metadata array.
     */
    virtual bool SetConfiguredDatabase(StructuredDataI &data);

    /**
     * @brief Allocates signal memory plus readyBuffer and scratchBuffer.
     */
    virtual bool AllocateMemory();

    /**
     * @brief Returns "MemoryMapSynchronisedInputBroker" for InputSignals.
     */
    virtual const char8 *GetBrokerName(StructuredDataI &data,
                                       const SignalDirection direction);

    /**
     * @brief Copies the latest received data into signal memory.
     */
    virtual bool Synchronise();

    /**
     * @brief Starts the background receiver on the first state transition.
     */
    virtual bool PrepareNextState(const char8 *const currentStateName,
                                  const char8 *const nextStateName);

    /* ---- UDPSClientListener callbacks (invoked from the receiver thread) ---- */

    /**
     * @brief Validates a reassembled CONFIG payload against the local signals.
     */
    virtual void OnUDPSConfig(const uint8 *payload, uint32 payloadSize);

    /**
     * @brief Decodes a reassembled DATA payload into the staging buffer.
     */
    virtual void OnUDPSData(const uint8 *payload, uint32 payloadSize);

    /**
     * @brief Logs that the server connection is established.
     */
    virtual void OnUDPSConnected();

    /**
     * @brief Invalidates the CONFIG so stale data is not published.
     */
    virtual void OnUDPSDisconnected();

private:
    /**
     * @brief Decodes a single snapshot from a DATA payload into @p dst.
     * @details Mirrors the StreamHub hub layout (UDPSourceSession): an 8-byte
     * HRT timestamp, an optional 4-byte sample count (Accumulate mode), then
     * per-signal data in CONFIG order. For accumulated scalars the most recent
     * sample is published.
     */
    void DecodeSnapshot(const uint8 *payload, uint32 size, uint8 *dst);

    /* Configuration parameters */
    StreamString serverAddress;  /**< Server IP address. */
    uint16       port;           /**< Server port. */
    uint32       maxPayloadSize; /**< Max payload bytes per datagram. */
    uint32       cpuMask;        /**< Background thread CPU affinity. */
    uint32       stackSize;      /**< Background thread stack size. */
    StreamString multicastGroup; /**< Multicast group IP; empty = unicast. */
    uint16       dataPort;       /**< UDP port for DATA datagrams (multicast). */
    bool         useMulticast;   /**< True when MulticastGroup is set. */

    /* Signal metadata */
    uint32                   numSigs;       /**< Number of signals. */
    UDPStreamerClientSignal *signalInfos;   /**< Per-signal metadata (heap). */
    uint32                   totalSrcBytes; /**< Total destination signal bytes. */
    bool                     configValidated; /**< True after a valid CONFIG. */
    uint8                    publishMode;   /**< UDPS_PUBLISH_* from CONFIG. */

    /* Shared receiver (same code base as the StreamHub hub) */
    UDPSClient client;      /**< Transport, reassembly and reconnect. */
    bool       receiverUp;  /**< True once the receiver thread is started. */

    /* Double-buffering for RT safety */
    uint8              *readyBuffer;   /**< Protected copy of decoded signal data. */
    uint8              *scratchBuffer; /**< Receiver-thread-private decode buffer. */
    FastPollingMutexSem bufMutex;      /**< Protects readyBuffer. */
    EventSem            dataSem;       /**< Wakes the RT thread on new data. */
    bool                newDataReady;  /**< Set when readyBuffer has fresh data. */
};

} /* namespace MARTe */

#endif /* UDPSTREAMERCLIENT_H_ */
