#pragma once

#include <QObject>
#include <QtPlugin>
#include "interfaces/plugin_interface.hpp"
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/topic/Topic.hpp>
#include "DDSSampleMachine.hpp"
#include "DDSSampleMachinePubSubTypes.hpp"
#include "PLCController.hpp"
#include "ConfigDialog.hpp"

using namespace eprosima::fastdds::dds;
using namespace SampleModule;

// 导出宏定义
#ifdef AQTSAMPLEMACHINEPLUG_LIBRARY
#define AQTSAMPLEMACHINEPLUG_EXPORT Q_DECL_EXPORT
#else
#define AQTSAMPLEMACHINEPLUG_EXPORT Q_DECL_IMPORT
#endif

/**
 * @brief 采样机DDS插件类
 * 
 * 实现采样机的DDS通信功能，包括：
 * - 采样机控制命令的发送
 * - 采样机状态的接收
 * - 数据点信息的管理
 */
class AQTSAMPLEMACHINEPLUG_EXPORT AQTSampleMachinePlug : public QObject, public AuseftDDSPluginInterface, public DataReaderListener
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID AuseftDDSPluginInterface_iid FILE "AQTSampleMachinePlug.json")
    Q_INTERFACES(AuseftDDSPluginInterface)

public:
    /**
     * @brief 构造函数
     * @param parent 父对象指针
     */
    explicit AQTSampleMachinePlug(QObject *parent = nullptr);
    
    /**
     * @brief 析构函数
     * 负责清理DDS资源
     */
    ~AQTSampleMachinePlug();

    // 实现插件接口
    /**
     * @brief 初始化插件
     * @param domainId DDS域ID
     * @param domainName DDS域名称
     * @return 初始化是否成功
     */
    Q_INVOKABLE bool init(uint32_t domainId, const QString& domainName) override;

    /**
     * @brief 获取所有数据点信息
     * @return 数据点信息列表
     */
    Q_INVOKABLE QList<DataPointInfo> getDataPoints() override;

    /**
     * @brief 发布数据到DDS网络
     * @param dataList 要发布的数据列表
     * @return 发布是否成功
     */
    Q_INVOKABLE bool publishData(const QList<DataItem>& dataList) override;

    /**
     * @brief 显示配置对话框
     * @return 是否成功显示对话框
     */
    Q_INVOKABLE bool showConfig() override;

    /**
     * @brief 显示配置对话框
     * @return 是否成功显示对话框
     */
    Q_INVOKABLE bool showConfigDialog() override;

    /**
     * @brief 配置插件
     * @return 是否成功显示配置界面
     */
    Q_INVOKABLE bool config() override;

    // 实现 DataReaderListener 接口
    void on_data_available(DataReader* reader) override;

private slots:
    // 处理配置对话框的配置完成信号
    void onDialogConfigurationChanged(const QString& config);

private:
    // DDS 实体
    DomainParticipant* participant_;    ///< DDS参与者
    Publisher* publisher_;              ///< DDS发布者
    Subscriber* subscriber_;            ///< DDS订阅者

    // 命令相关（改为订阅）
    Topic* commandTopic_;               ///< 命令主题
    DataReader* commandReader_;         ///< 命令读取器（改为读取器）
    TypeSupport commandType_;           ///< 命令类型支持

    // 配置相关（改为订阅）
    Topic* configTopic_;                ///< 配置主题
    DataReader* configReader_;          ///< 配置读取器（改为读取器）
    TypeSupport configType_;            ///< 配置类型支持

    // 采样点相关（改为订阅）
    Topic* pointsTopic_;                ///< 采样点主题
    DataReader* pointsReader_;          ///< 采样点读取器
    TypeSupport pointsType_;            ///< 采样点类型支持

    // 机器信息相关（保持发布）
    Topic* machineinfoTopic_;          ///< 机器信息主题
    DataWriter* machineinfoWriter_;     ///< 机器信息写入器
    TypeSupport machineinfoType_;       ///< 机器信息类型支持

    // PLC 相关
    PLCController plc_;
    bool plcConnected_;
    
    // PLC 数据区定义
    struct PLCDataAreas {
        static const int DB_CONFIG = 1;     // 配置数据块号
        static const int DB_COMMAND = 2;    // 命令数据块号
        static const int DB_STATUS = 3;     // 状态数据块号
        static const int DB_POINTS = 4;     // 点位数据块号
    };
    
    // PLC 通信方法
    bool writeToPLC(const SampleConfig& config);
    bool writeToPLC(const SampleCommand& command);
    bool writeToPLC(const SamplePoints& points);
    bool readFromPLC(SampleMachineInfo& info);

    // 初始化辅助函数
    /**
     * @brief 初始化DDS实体
     * @return 初始化是否成功
     */
    bool initDDSEntities();

    /**
     * @brief 清理DDS实体
     */
    void cleanupDDSEntities();

    // 数据转换辅助函数
    // DataItem 列表转换为具体类型
    SampleConfig dataItemsToConfig(const QList<DataItem>& items);
    SampleCommand dataItemsToCommand(const QList<DataItem>& items);
    SamplePoints dataItemsToPoints(const QList<DataItem>& items);
    SampleMachineInfo dataItemsToMachineInfo(const QList<DataItem>& items);

    // 具体类型转换为 DataItem 列表
    QList<DataItem> configToDataItems(const SampleConfig& config);
    QList<DataItem> commandToDataItems(const SampleCommand& command);
    QList<DataItem> pointsToDataItems(const SamplePoints& points);
    QList<DataItem> machineInfoToDataItems(const SampleMachineInfo& info);

    // 应用新的配置
    bool applyConfiguration(const QString& config);
    
    ConfigDialog* configDialog_;
}; 
