#pragma once

#include <string>
#include <vector>
#include <cstdint>

// 说明:
// - 这是一个“TCP 客户端”示例类,PC 侧主动连接相机(相机侧提供 TCP Server)。
// - send/recv 的具体实现可基于 POSIX socket 或 WinSock。
// - 协议帧格式需要按相机实际协议调整,这里用“长度 + payload”的示例。

struct ImageFrame {
	int width = 0;
	int height = 0;
	int channels = 0;

	// 时间戳。
	// 单位:毫秒(ms)
	uint64_t timestamp = 0;

	// 图片数据指针。
	// 说明:这里类型暂未确定,因此使用 void\\*。
	// 数据的实际组织形式由协议决定,例如可以是 BGR、RGB、GRAY、JPEG 等。
	// 使用方需要配合 length 或 stride 等信息来正确解析与释放内存。
	void* data = nullptr;
};

// 相机初始化参数结构体(示例)
// 说明:拆分为“控制参数”和“处理参数”,便于分别配置与管理。
struct CameraControlParams {
	// 控制参数:增益、曝光、采集 ROI、触发/采集模式
	double gain = 0; // dB 或 level,按相机 SDK
	double exposureTime = 0; // ms 或 us,按相机 SDK
	int roiWidth = 0;
	int roiHeight = 0;
	int roiOffsetX = 0;
	int roiOffsetY = 0;
	int acquisitionMode = 0; // 0=连续,1=软触发,2=硬触发(示例)
};

// 全局相机初始化参数(示例)
// 说明:也可以放到单例/配置管理模块中,这里用全局变量演示。
extern CameraControlParams m_tCameraInitParams;

class CameraTcpClient {
public:
	CameraTcpClient() = default;

	// 构造入参(推荐:由外部加载配置后传入)
	explicit CameraTcpClient(const CameraControlParams & params)
	{
		m_tCameraInitParams = params;
	}

	// 动态更新入参(可选)
	void setInitParams(const CameraControlParams & params) { CameraControlParams = params; }
	const CameraControlParams & getInitParams() const { return m_tCameraInitParams; }
	~CameraTcpClient() { disconnect(); }

	// 连接到相机 TCP Server。
	// - ip/port: 相机服务端地址
	// - timeoutMs: 建连超时
	// 返回:true 表示连接成功。
	bool connectTo(const std::string& ip, int port, int timeoutMs = 3000);

	// 主动断开连接并释放 socket 资源。
	void disconnect();

	// 当前连接是否有效。
	bool isConnected() const;

	// 探活:发送 PING 并等待响应,用于判断链路是否可用。
	bool ping(int timeoutMs = 1000);

	// 开启相机数据流(如连续图像/点云推送)。具体含义按相机协议定义。
	bool startStream();

	// 关闭相机数据流。具体含义按相机协议定义。
	bool stopStream();

	// 可选:心跳
	// 周期性调用 ping(),用于维持连接与检测掉线。
	// intervalMs: 心跳周期
	bool startHeartbeat(int intervalMs = 1000);

	// 停止心跳线程或定时器。
	void stopHeartbeat();

	// 抓取一帧图像数据。
	// outFrame: 输出图像帧
	bool capture(ImageFrame& outFrame, int timeoutMs = 3000);

	// 设置增益
	// gain: dB 或 level,按相机 SDK 定义
	bool setGain(double gain, int timeoutMs = 1000);

	// 设置曝光
	// exposureTime: ms 或 us,按相机 SDK 定义
	bool setExposure(double exposureTime, int timeoutMs = 1000);

	// 设置采集分辨率 / ROI
	// (w,h): 采集宽高
	// (offsetX, offsetY): ROI 左上角偏移
	bool setRoi(int w, int h, int offsetX = 0, int offsetY = 0, int timeoutMs = 1000);

	// 设置触发/采集模式
	// mode: 0=连续,1=软触发,2=硬触发(示例)
	bool setAcquisitionMode(int mode, int timeoutMs = 1000);

	// 软触发拍照(当 acquisitionMode=软触发时使用)
	bool triggerOnce(int timeoutMs = 1000);

private:
	int sock_ = -1; // POSIX: socket fd;Windows: SOCKET
	std::string ip_;
	int port_ = 0;
};

// 心跳建议:
// - startHeartbeat() 内部启动线程或定时器,按 intervalMs 周期发送 ping()
// - 连续 N 次 ping 失败则认为掉线,触发重连或上报报警