#ifndef CRABBITMQCLIENT_H
#define CRABBITMQCLIENT_H
#include "cexchange.hpp"
#include "cmessage.hpp"
#include "cqueue.hpp"
#include "../../../CAE_Solution/Libs/rabbitmq/include/rabbitmq-c/amqp.h"
#include "../../../CAE_Solution/Libs/rabbitmq/include/rabbitmq-c/framing.h"
#include "../../../CAE_Solution/Libs/rabbitmq/include/rabbitmq-c/ssl_socket.h"
#include "../../../CAE_Solution/Libs/rabbitmq/include/rabbitmq-c/tcp_socket.h"
#include "../../../CAE_Solution/Libs/rabbitmq/include/rabbitmq-c/export.h"
#include <vector>


/**
*   @brief RabbitMq封装类
**/
class CRabbitMqClient
{
public:
    CRabbitMqClient(
            std::string HostName ,
            uint32_t port ,
            std::string usr ,
            std::string psw,
            amqp_connection_state_t State,
            int channel_id,
            std::string queue_name,
            std::string exchange_name,
            std::string routing_keys_name
            );
    ~CRabbitMqClient();

public:
    /**
    * 连接RabbitMq服务器
    *
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t Connect( std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 断开与RabbitMq服务器的连接
    *
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t DisConnect( std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 交换机初始化
    *
    * @param[in]    exchange		交换机实例
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t DeclareExchange(CExchange &exchange, std::string &ErrorReturn/* = std::string("")*/);

    /**
    * 队列初始化
    *
    * @param[in]    queue			消息队列实例
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t DeclareQueue(CQueue &queue, std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 将指定队列绑定到指定交换机上
    *
    * @param[in]    queue			消息队列实例
    * @param[in]    exchange		交换机实例
    * @param[in]    bind_key		路由名
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t BindQueueToExchange(CQueue &queue, CExchange &exchange, const std::string bind_key,  std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 解绑指定队列和指定交换机
    *
    * @param[in]    queue			消息队列实例
    * @param[in]    exchange		交换机实例
    * @param[in]    bind_key		路由名
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t UnBindQueueToExchange(CQueue &queue, CExchange &exchange, const std::string bind_key,  std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 发布单个消息
    *
    * @param[in]    message			消息实例
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t PublishMessage(const CMessage &message, std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 发布批量消息
    *
    * @param[in]    messageVec		消息实例数组
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t PublishMessage(std::vector<CMessage> &messageVec, std::string &ErrorReturn/* = std::string("")*/);

    /**
    * 从指定队列中取单个消息（同步操作）
    *
    * @param[in]    queue_name_		队列名称
    * @param[in]    timeout			超时时间，为NULL有可能导致阻塞
    * @param[out]   message			消息内容
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t ConsumerMessage(std::string &message, const std::string &queue_name_, timeval timeout /*= { 5, 0 }*/,  std::string &ErrorReturn /*= std::string("")*/);

    /**
    * 从指定队列中取指定数目消息（同步操作）
    *
    * @param[in]    queue_name_		队列名称
    * @param[in]    GetNum			消息树木
    * @param[in]    timeout			超时时间，为NULL有可能导致阻塞
    * @param[out]   messageVec		消息内容数组（大小不一定等于GetNum）
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t ConsumerMessage(std::vector<std::string> &messageVec, const std::string &queue_name_, uint32_t GetNum /*= 1000*/, timeval timeout/* = { 5, 0 }*/,std::string &ErrorReturn /*= std::string("")*/);

    //还有一个amqp_basic_get函数，没有用到，暂时不实现（区别于amqp_basic_consume，get是检索，consume是消费）
private:
    /**
    * 获取错误信息文本
    *
    * @param[in]    reply			amqp_rpc_reply_t对象
    * @param[in]    strModule		模块信息（一般传当前调用的RabbitMQ-API函数名）
    * @param[out]   ErrorReturn		错误信息
    * @return		int32_t			0表示成功，其他失败
    */
    int32_t GetErrorText(const amqp_rpc_reply_t &reply, const std::string &strModule, std::string &ErrorReturn);

public:
    std::string m_strHost;
    std::string m_strUser;
    std::string m_strPwd;
    int32_t m_nPort;

    int channel_id;
    std::string queue_name;
    std::string exchange_name;
    std::string routing_keys_name;

    amqp_connection_state_t m_connectState;
public:
    std::string Error;

};





#endif // CRABBITMQCLIENT_H
