#pragma once

#include <softbus_transport/UplinkWire.h>

#include <asio.hpp>

#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>

namespace softbus::transport {

using CommandHandler = std::function<void(const softbus::api::ExecuteCommand&)>;

class TcpUplinkClient {
public:
    TcpUplinkClient(std::string host, uint16_t port);
    ~TcpUplinkClient();

    void setCommandHandler(CommandHandler handler);
    bool connect();
    void disconnect();
    bool sendCommand(const softbus::api::ExecuteCommand& command);
    bool sendRawPacket(const softbus::core::RawPacket& packet);
    bool sendAck(const softbus::core::SoftbusAck& ack);
    bool sendHeartbeat(const std::string& deviceId);
    void poll();

    bool isConnected() const { return connected_; }

private:
    void doRead();
    void handleLine(const std::string& line);

    std::string host_;
    uint16_t port_;
    asio::io_context io_;
    std::unique_ptr<asio::ip::tcp::socket> socket_;
    std::unique_ptr<asio::executor_work_guard<asio::io_context::executor_type>> workGuard_;
    std::thread ioThread_;
    CommandHandler commandHandler_;
    std::string readBuffer_;
    std::mutex sendMutex_;
    bool connected_{false};
};

} // namespace softbus::transport
