#ifndef __MESSAGEQUEUE_H__
#define __MESSAGEQUEUE_H__


#ifdef __cplusplus
#ifndef BEGIN_DECLS
#define BEGIN_DECLS extern "C" {
#endif
#ifndef END_DECLS
#define END_DECLS }
#endif
#else
#ifndef BEGIN_DECLS
#define BEGIN_DECLS
#endif
#ifndef END_DECLS
#define END_DECLS
#endif
#endif

BEGIN_DECLS

#if defined(_WIN32) && defined(UNICODE)
#include <wchar.h>
#endif

#include <amqp.h>
#include <amqp_tcp_socket.h>
#include <amqp_framing.h>
#include <limits.h>
#include <stdbool.h>
#include <pthread.h>


#include "Common.h"
//#include "DataStructure.h"
#include "SecureCodingUtil.h"
#include "Config.h"
#include "Log.h"
#include "StringUtil.h"
#include "Socket.h"
#include "ThreadUtil.h"
#include "SystemUtil.h"

#define MQ_ERR_SUCCESS                              0
#define MQ_ERR_CONFIG                               -1
#define MQ_ERR_INIT                                 -2
#define MQ_ERR_CREATE_CONNECT                       -3
#define MQ_ERR_CREATE_SOCKET                        -4
#define MQ_ERR_CONNECT_SOCKET                       -5
#define MQ_ERR_OPEN_CHANNEL                         -6
#define MQ_ERR_NO_RESPONSE                          -7
#define MQ_ERR_LIB_EXCEPTION                        -8
#define MQ_ERR_SERVER_EXCEPTION                     -9
#define MQ_ERR_LOGIN_LIBRARY                        -10
#define MQ_ERR_LOGIN_SERVER                         -11
#define MQ_ERR_SSL                                  -12
#define MQ_ERR_TCP                                  -13
#define MQ_ERR_UNKNOWN                              -14
#define MQ_ERR_CONNECTION_CLOSED                    -15
#define MQ_ERR_CHANNEL_CLOSED                       -16
#define MQ_ERR_MESSAGE_RETURNED                     -17
#define MQ_ERR_PUBLISH_FAIL                         -18
#define MQ_ERR_CANT_FIND_ORIG_MSG                   -19     // 응답전문 전송을 위해 수신 전문을 체크하였으나 데이터 없음
                                                             // 발생 가능한 경우는 이미 타임아웃 처리되어 원본 전문을 삭제 하였으나 아주 늦게 응답이 수신된 경우
                                                             // 이런경우 오류 로그만 남기고 상대편으로 전송하지 않는다.
#define MQ_ERR_CLOSE                                -20
#define MQ_ERR_TIMEOUT                              -21


#define MQ_CONF_SERVER_IP_KEY                       "MQ_SERVER_IP"
#define MQ_CONF_SERVER_PORT_KEY                     "MQ_SERVER_PORT"
#define MQ_CONF_VIRTUALHOST_KEY                     "MQ_VIRTUALHOST"
#define MQ_CONF_SERVICE_USER_ID_KEY                 "MQ_SERVICE_USER_ID"
#define MQ_CONF_SERVICE_PWD_KEY                     "MQ_SERVICE_PWD"
#define MQ_CONF_MESSAGE_SEND_EXCHANGER_NAME_KEY     "MQ_MESSAGE_SEND_EXCHANGER_NAME"
//송신 Exchange 추가(by JBY)
#define MQ_CONF_MESSAGE_SEND2_EXCHANGER_NAME_KEY     "MQ_MESSAGE_SEND2_EXCHANGER_NAME"

#define MQ_CONF_MESSAGE_RECV_EXCHANGER_NAME_KEY     "MQ_MESSAGE_RECV_EXCHANGER_NAME"
#define MQ_CONF_MESSAGE_SEND_QUEUE_NAME_KEY         "MQ_MESSAGE_SEND_QUEUE_NAME"
#define MQ_CONF_MESSAGE_SEND_RESP_QUEUE_NAME_KEY    "MQ_MESSAGE_SEND_RESP_QUEUE_NAME"
//추가 Queue 설정(by JBY)
#define MQ_CONF_MESSAGE_SEND_REAL_QUEUE_NAME_KEY    "MQ_MESSAGE_SEND_REAL_QUEUE_NAME"
#define MQ_CONF_MESSAGE_SEND_HQCT_QUEUE_NAME_KEY    "MQ_MESSAGE_SEND_HQCT_QUEUE_NAME"

#define MQ_CONF_MESSAGE_RECV_QUEUE_NAME_KEY         "MQ_MESSAGE_RECV_QUEUE_NAME"
#define MQ_CONF_MESSAGE_RECV_RESP_QUEUE_NAME_KEY    "MQ_MESSAGE_RECV_RESP_QUEUE_NAME"
#define MQ_CONF_FILE_SEND_EXCHANER_NAME_KEY         "MQ_FILE_SEND_EXCHANER_NAME"
#define MQ_CONF_FILE_RECV_EXCHANER_NAME_KEY         "MQ_FILE_RECV_EXCHANER_NAME"
#define MQ_CONF_FILE_SEND_QUEUE_NAME_KEY            "MQ_FILE_SEND_QUEUE_NAME"
#define MQ_CONF_FILE_SEND_RESP_QUEUE_NAME_KEY       "MQ_FILE_SEND_RESP_QUEUE_NAME"
#define MQ_CONF_FILE_RECV_QUEUE_NAME_KEY            "MQ_FILE_RECV_QUEUE_NAME"

#define MQ_CONF_TARGET_ORGANIZATION_CODE            "TARGET_ORGANIZATION_CODE"
#define MQ_CONF_ORGANIZATION_CODE                   "ORGANIZATION_CODE"

#define MQ_CONF_PROCESS_TYPE_KEY                    "PROCESS_TYPE"

#define MQ_CONF_PREFETCH_SIZE_KEY                   "PREFETCH_SIZE"
#define MQ_CONF_PREFETCH_COUNT_KEY                  "PREFETCH_COUNT"

enum PROC_TYPE
{
    MQ_PROC_TYPE_GW = 0,
    MQ_PROC_TYPE_PROCESSOR,
    MQ_PROC_TYPE_SENDER,
    MQ_PROC_TYPE_RELAY,
    MQ_PROC_TYPE_COUNT,
};


extern char g_szMQServerIP[MAX_STRING_SIZE + 1];
extern int g_nMQServerPort;
extern char g_szMQVirtualHostname[MAX_STRING_SIZE + 1];
extern char g_szMQServiceID[MAX_STRING_SIZE + 1];
extern char g_szMQServicePWD[MAX_STRING_SIZE + 1];
extern char g_szMQMessageSendQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQMessageSendRespQueuename[MAX_STRING_SIZE + 1];
//추가 Queue 사용하기 위해(by JBY)
extern char g_szMQMessageSendRealQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQMessageSendHqctQueuename[MAX_STRING_SIZE + 1];

extern char g_szMQMessageRecvQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQMessageRecvRespQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQMessageSendExchangername[MAX_STRING_SIZE + 1];
//송신 Exchange 추가(by JBY)
extern char g_szMQMessageSend2Exchangername[MAX_STRING_SIZE + 1];

extern char g_szMQMessageRecvExchangername[MAX_STRING_SIZE + 1];
extern char g_szMQFileSendQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQFileSendRespQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQFileRecvQueuename[MAX_STRING_SIZE + 1];
extern char g_szMQFileSendExchangername[MAX_STRING_SIZE + 1];
extern char g_szMQFileRecvExchangername[MAX_STRING_SIZE + 1];
extern char g_szMQTargetOrganizationCode[MAX_STRING_SIZE + 1];
extern char g_szMQOrganizationCode[MAX_STRING_SIZE + 1];
extern int g_nProcessType;
extern int g_nPrefetchSize;
extern int g_nPrefetchCount;
extern int g_bBypassMode;


int InitMQConfig();
int InitProcessorMQConfig();
//추가 설정
int InitProcessor2MQConfig();

//dam test
int InitDirectLaneSendMQConfig();

int InitSenderMQConfig();
/*추가 Queue 설정*/
int InitSender2MQConfig();

void AMQPStatusProcess(int nStatus, const char *szMessage);
int AMQPReplyProcess(amqp_rpc_reply_t *sAMQPReply, const char *szString, int *pbMQConnection, int *pbMQChannelOpen);
int InitMQ(struct SOCKET_THREAD_INFO *pThreadInfo);
int ConnectSocketMQ(struct SOCKET_THREAD_INFO *pThreadInfo);
int ConnectProcessorMQ(struct THREAD_INFO *pThreadInfo, int bMessage);
int ConnectSenderMQ(struct THREAD_INFO *pThreadInfo, int bMessage);
/*2개의 Exchange 사용하기 위함*/
int ConnectSenderMultiMQ(struct THREAD_INFO *pThreadInfo, int bMessage, int type, int rule);

int CloseMQ(int nIndex, amqp_connection_state_t sMQConnectionState, int *pbMQConnection, int *pbMQChannelOpen, pthread_mutex_t *pMessageQueueMutex);
int GetMessageFromQueue(amqp_connection_state_t sMQConnectionState, char *pExchangername, int nExchangernameLength, char *pData, int nDataLength, char *szCorrelationID, int nCorrelationIDLength, char *szReplyQueuename, int nReplyQueuenameLength, int *bMQConnection, int *bChannelOpen, uint64_t *pnDeliveryTag, struct timeval *pTimeVal);
//int PutMessageToQueue(struct SOCKET_THREAD_INFO *pThreadInfo, int nChannelNo, const char *pszExchangename, const char *pszResponseQueuename, const char *pszTopic, struct MESSAGE_INFO *pMessageInfo, const char *pData, int nDataLength, char *szUUID, int nUUIDLength);
//int PutMessageToQueue(struct SOCKET_THREAD_INFO *pThreadInfo, int nChannelNo, const char *pszExchangename, const char *pszResponseQueuename, const char *pszTopic, struct MESSAGE_INFO *pMessageInfo, const char *pData, int nDataLength, char *szUUIDString, int nUUIDLength, int bMakeResponseInfo);
//int PutMessageToQueue(amqp_connection_state_t sMQConnectionState, int *pbMQConnection, int *pbChannelOpen, int nChannelNo, const char *pszExchangename, const char *pszResponseQueuename, const char *pszTopic, struct MESSAGE_INFO *pMessageInfo, const char *pData, int nDataLength, char *szUUIDString, int nUUIDLength, int bMakeResponseInfo);
int PutMessageToQueue(amqp_connection_state_t sMQConnectionState, int *pbMQConnection, int *pbChannelOpen, int nChannelNo, const char *pszExchangename, const char *pszResponseQueuename, const char *pszTopic, struct MESSAGE_INFO *pMessageInfo, const char *pData, int nDataLength, char *szUUIDString, int nUUIDLength, int bMakeResponseInfo, struct DOUBLELINKEDLISTINFO *pListInfo);
int PutAckMessageToQueue(amqp_connection_state_t sMQConnectionState, const char *pszCorrelationID, const char *pszResponseQueuename, const char *pData, int nDataLength, int *pbMQConnection, int *pbChannelOpen);
int PutReplyMessageToQueue(amqp_connection_state_t sMQConnectionState, const char *pszCorrelationID, const char *pszResponseQueuename, const char *pData, int nDataLength, int *pbMQConnection, int *pbChannelOpen);
int ProcessRecvQueueResponse(struct SOCKET_THREAD_INFO *pThreadInfo, int nChannelNo, const char *aMessageBody, int nMessageBodySize, const char *szUUIDString, int nUUIDStringSize);
int ProcessRecvSocketResponse(struct SOCKET_THREAD_INFO *pThreadInfo, int nChannelNo, const char *aMessageBody, int nMessageBodySize, char *szUUIDString, int nUUIDStringSize, int bSuccess);
int QSendMessage(struct SOCKET_THREAD_INFO *pThreadInfo, int nChannelNo, const char *aMessageBody, int nMessageBodySize, const char *szUUIDString, int nUUIDStringSize, const char *szResponseQueuename, int nResponseQueuenameSize, uint64_t nDeliveryTag);
int MQReadCheck(amqp_connection_state_t sMQConnectionState);

END_DECLS

#endif
