/*  Copyright 2025 Leuze electronic GmbH + Co. KG
 *
 *  Licensed under the Apache License, Version 2.0
 */

#ifndef LEUZE_ETH_COMM_UDP_H
#define LEUZE_ETH_COMM_UDP_H

#include <array>
#include <condition_variable>
#include <deque>
#include <iostream>
#include <mutex>
#include <string>

#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/laser_scan.hpp>

#include <boost/bind/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/circular_buffer.hpp>

#include "leuze_rod_driver/common.h"
#include "leuze_rod_driver/eth_comm_tcp.h"
#include "leuze_rod_driver/scan_data_parser.h"

using namespace boost::placeholders;

namespace leuze_rod_ros2_drivers
{
    /************************************************************************************************************
     * @class   EthCommUDP
     * 
     * @brief   This class ensures UDP commmunication with a ROD scanner. It supports capturing of an UDP process
     *          data (MDI packets).
     ************************************************************************************************************/
    class EthCommUDP : public ScanDataParser
    {
        public:

            /****************************************************************************************************/

            /**
             *@brief    constructor 
             *@param    port
             */
            EthCommUDP(int port);

            /**
             *@brief    destructor 
             */
            ~EthCommUDP();

            /****************************************************************************************************/

            /**
             *@brief    get connection state
             *@return   state of connection
             */
            bool getStateConnected() const { return state_connected_; }

            /**
             *@brief    disconnect from socket
             */
            void disconnect();

            /****************************************************************************************************/

            bool getConnectionState();

        private:

            /* UDP */
            int udp_port_;
            boost::asio::ip::udp::socket*               udp_socket_;
            boost::asio::ip::udp::endpoint              udp_endpoint_;
            std::array<char, SCANPAR_BUFF_SIZE_RING>    udp_buffer_;            
            
            /* Common */
            boost::thread io_service_thread_;
            boost::asio::io_service io_service_;
            boost::asio::streambuf inbuf_;
            std::istream instream_;

            bool state_connected_;
            double last_scan_time_;

            /****************************************************************************************************/

            /**
             *@brief    handle receiving and parsing of TCP packets
             *@param    error
             */
            // void udpSockReadHandler(const boost::system::error_code& error);

            /**
             *@brief    handle receiving and parsing of UDP packets
             *@param    error
             *@param    bytes_transferred
             */
            void udpSockReadHandler(const boost::system::error_code& error, std::size_t bytes_transferred);

            /****************************************************************************************************/
    };

}
#endif // end eth_comm_udp_H
