
#include <ace/Init_ACE.h>
#include <ace/Reactor.h>
#include <ace/Process_Mutex.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "LSC_Logger.h"
#include "MQ_CCU_Config.h"
#include "MQ_CCU_Adapter.h"
#include "EH_ToolKit.h"

#define DEF_LOG_LEAVE      "D"

static void oepnDebug();

int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {  //主函数
//	与程序进程管理有关？
	if(argc == 2) {
		string flag = argv[1];
		if (flag == "-v") {
			// cout<<"konkeyunzhiyi:"<< MQ_VERSION << endl;
			exit(0);
		}
	}

	//对ACE::init()组件进行初始化
	if (ACE::init() == -1) {
		LOGE("Init ACE failed.\n");
		ACE_OS::exit(-1); //exit函数告诉系统程序已完成，从而终止进程。
	}
	ACE_OS::signal(SIGPIPE, SIG_IGN); //signal函数将action设置为signum的action。
	//消息转储核心转储集
    EH_ToolKit::SetCoredumpMsgDump();

    //开启日志并开始记录
	if (LSC_LOGGER::instance()->open("konkeyunzhiyi", DEF_LOG_LEAVE) != 0) {
		LOGE("Init lsc logger failed.\n"); 
		ACE_OS::exit(1);
	}

	//创建ACE_进程 konkeyunzhiyi
	ACE_Process_Mutex processMutex("konkeyunzhiyi"); //进程名检测
	if (processMutex.tryacquire() < 0) {  //
		//相同的进程正在运行，当前进程将中止 。异常的判段处理
		LOGE("The same process is running.current process will abort.\n");
		return -1;
	} else {
		LOGI("konke yunzhiyi Starting...Version:%d \n",MQ_VERSION);
		LOGI("konke yunzhiyi Starting...Version 编译时间:%s %s \n",__DATE__,__TIME__);
		LOGI("konkeyunzhiyi acquired.\n");
	}

	// if(KK_CcuConfig::GetInstance()->Open()!=0){
	// 	LOGE("Ccu Config failed.\n");
	// 	ACE_OS::exit(-1);
	// 	return -1;
	// }

	//暂不开启延时。
	//sleep(10);

	int ret = MQ_CCU_Config::GetInstance()->open();
	if(ret != 0){
		LOGE("load config failed.\n");
		ACE_OS::exit(1);
	}
	//更新日志级别，
//	LSC_LOGGER::instance()->set_log_leave(MQ_CCU_Config::GetInstance()->getLogLevel());

	//MQ_CCU_Adapter 适配器 还有相关启动。
	ret = MQ_CCU_Adapter::GetInstance()->open();
	if(ret != 0){
		LOGE("mqtt init failed.\n");
		ACE_OS::exit(1);
	}

	if(argc == 2 && string(argv[1]) == "-d") {
		LOGI("000000000000000000000000000000000000000000\n");
		oepnDebug();
	}

	return ACE_Reactor::instance()->run_reactor_event_loop();
}

static int serverSocket;

static void processReq(string req) {  //处理请求
LOGI("1111111111111111111111111111111processReq req:%s \n",req.c_str());
	if(req == "new_mqtt_tcp"){
		KK_MQTTSDK::GetInstance()->reinit("tcp://127.0.0.1:23883");
	}else if(req == "new_mqtt_ssl"){
		KK_MQTTSDK::GetInstance()->reinit("ssl://120.55.149.201:8883");
	}else if(req == "con_mqtt_0") {
		KK_MQTTSDK::GetInstance()->con(0);
	}else if(req == "con_mqtt_1") {
		KK_MQTTSDK::GetInstance()->con(1);
	}else if(req == "discon_mqtt") {
		KK_MQTTSDK::GetInstance()->discon();
	}else if(req == "del_mqtt") {
		KK_MQTTSDK::GetInstance()->destroy();
	}else{
		LOGW("not support req:%s.\n",req.c_str());
	}
}

static void* run0(void* opt){
	char buff[512];
	struct sockaddr_in clientAddr; /*描述Internet套接字地址的结构。*/
	int n;
	int len = sizeof(clientAddr);
	while (true){
		LOGI("2222222222222222222222222222222\n");
		//接收信息
		//recvfrom函数从套接字将一个数据包读入缓冲区。size参数指定要读取的最大字节数。
		n = ACE_OS::recvfrom(serverSocket, buff, sizeof(buff), 0, (struct sockaddr*)&clientAddr, &len);
		if (n>0){
			buff[n] = 0;
			LOGI("recv from [%s : %d]:  %s\n",inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),buff);
			//处理请求
			processReq(string(buff));
		}
		else{
			//从接收失败。
			LOGE("recvfrom failed. \n");
		}
	}
	return NULL;
}


static void oepnDebug(){
	LOGI("333333333333333333333333\n");
	struct sockaddr_in addr; /*描述Internet套接字地址的结构。*/
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=htonl(INADDR_ANY);
	addr.sin_port=htons(8761);

	//创建mqtt调试服务器
	if ((serverSocket = ACE_OS::socket(AF_INET, SOCK_DGRAM, 0)) < 0){
		LOGE("create mqtt debug server failed. \n");
		return ;
	}

	//将mqtt调试服务器绑定到本地端口
	/*名称：绑定
	原型：int bind（int socket，struct sockaddr*addr，socklen_ntlength）
	说明：
	bind函数为套接字分配一个地址。addr和length参数指定地址
	地址的详细格式取决于命名空间。地址的第一部分总是格式
	标识符，它指定一个名称空间，并说明地址采用该名称空间的格式。
	成功时返回值为0，失败时返回值为-1。为此函数定义了以下errno错误条件：
	EBADF套接字参数不是有效的文件描述符。*/
	if (ACE_OS::bind(serverSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0){ /*描述通用套接字地址的结构。*/
		ACE_OS::close(serverSocket);
		LOGE("bind mqtt debug server to local port failed. \n");
	}

	//线程创建
	/*创建一个新线程，从执行START-ROUTINE开始
	正在传递ARG。创造属性来自属性。新的
	句柄存储在*NEWTHREAD中。*/
	pthread_t tid;
	LOGI("444444444444444444444444444\n");
	pthread_create(&tid, NULL, run0, NULL);
}
