#include "cmd_transport_mqtt.h"

//static const std::string kMqttUrl = "mqq-large-cdn.offcncloud.com";//"mqq-large.offcncloud.com";//"47.95.181.254";
static const std::string kUseName = "admin";
static const std::string kPassWord = "admin";
//static const std::string kTopicServer = "whiteboard/c50d86590070538228fdfa19978a87e3/liweijieisvip_309485708";//"rtc_server";

static struct Options
{
	char* connection;         /**< connection to system under test. */
	int verbose;
	int test_no;
	int size;									/**< size of big message */
	int MQTTVersion;
	int iterations;
} options;

CmdTransportMqtt::CmdTransportMqtt(std::string uu_id, std::string room_id, TransportObserver *observer)
	:observer_(observer),
	uu_id_(uu_id),
	room_id_(room_id)
{
	mqtt_client_ = NULL;
}
bool CmdTransportMqtt::ConnectServer(std::string mqtt)
{
	options.connection = (char *)malloc(128);
	memset(options.connection, 0, 128);
	memcpy(options.connection, mqtt.c_str(), mqtt.size());

	options.verbose = 0;
	options.test_no = -1;
	options.size = 10000;
	options.MQTTVersion = MQTTVERSION_3_1;
	options.iterations = 1;

	MQTTAsync_connectOptions opts = MQTTAsync_connectOptions_initializer;
	MQTTAsync_willOptions wopts = MQTTAsync_willOptions_initializer;

	//uuid@roomid
	std::string clientid = uu_id_;
	int nRet = MQTTAsync_create(&mqtt_client_, options.connection, clientid.c_str(), MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);

	nRet = MQTTAsync_setCallbacks(mqtt_client_, this, NULL, mqtt_messageArrive, NULL);

	std::string new_token = kPassWord;
	opts.keepAliveInterval = 20;
	opts.cleansession = 1;
	opts.username = kUseName.c_str();
	opts.password = kPassWord.c_str();
	opts.MQTTVersion = options.MQTTVersion;
	opts.cleansession = true;

	opts.will = NULL;
	opts.onSuccess = mqtt_onConnectSuccess;
	opts.onFailure = mqtt_onConnectFailed;
	opts.context = this;
	opts.connectTimeout = 10;

	nRet = MQTTAsync_connect(mqtt_client_, &opts);
	if (nRet != MQTTASYNC_SUCCESS)
	{
		return false;
	}

	return true;
}
bool CmdTransportMqtt::SendRequest(std::string req)
{
	MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
	pubmsg.payload = (void *)(req.c_str());
	pubmsg.payloadlen = req.length();
	pubmsg.qos = 2;
	pubmsg.retained = 0;

	std::string sTopic = "whiteboard/";
	sTopic = sTopic + room_id_ + "/";
	sTopic = sTopic + uu_id_;

	int nRet = MQTTAsync_send(mqtt_client_, sTopic.c_str(), pubmsg.payloadlen, pubmsg.payload, pubmsg.qos, pubmsg.retained, NULL);

	return true;
}
void CmdTransportMqtt::DisConnectServer()
{
	if (mqtt_client_)
	{
		MQTTAsync_disconnect(mqtt_client_, NULL);
		mqtt_client_ = NULL;
	}
}

void CmdTransportMqtt::mqtt_onConnectSuccess(void *context, MQTTAsync_successData *response)
{
	CmdTransportMqtt *pThis = (CmdTransportMqtt *)context;
	pThis->onConnectServerResult(true);
}
void CmdTransportMqtt::mqtt_onConnectFailed(void* context, MQTTAsync_failureData* response)
{
	CmdTransportMqtt *pThis = (CmdTransportMqtt *)context;
	pThis->onConnectServerResult(false);
}

void CmdTransportMqtt::mqtt_subscribeSuccess(void *context, MQTTAsync_successData* response)
{
	CmdTransportMqtt *pThis = (CmdTransportMqtt *)context;
	pThis->onSubscribeResult(true);
}
void CmdTransportMqtt::mqtt_subscribeFailed(void *context, MQTTAsync_failureData *response)
{
	CmdTransportMqtt *pThis = (CmdTransportMqtt *)context;
	pThis->onSubscribeResult(false);
}

int CmdTransportMqtt::mqtt_messageArrive(void *context, char *topicName, int len, MQTTAsync_message* message)
{
	if (message->payloadlen <= 0)
	{
		return 0;
	}

	CmdTransportMqtt *pThis = (CmdTransportMqtt *)context;
	pThis->onMessageArrive(message);

	MQTTAsync_freeMessage(&message);
	MQTTAsync_free(topicName);

	return 0;
}


void CmdTransportMqtt::onConnectServerResult(bool success)
{
	if (!success)
	{
		if (observer_)
		{
			observer_->OnConnectServerSuccess(false);
		}
	}
	else
	{
		MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
		opts.onSuccess = mqtt_subscribeSuccess;
		opts.onFailure = mqtt_subscribeFailed;
		opts.context = this;

		std::string topic = uu_id_ + "_" + room_id_;
		MQTTAsync_subscribe(mqtt_client_, topic.c_str(), 2, &opts);//uuid_roomid

		if (observer_)
		{
			observer_->OnConnectServerSuccess(true);
		}
	}
}
void CmdTransportMqtt::onSubscribeResult(bool success)
{
	if (!success)
	{
		if (observer_)
		{
			observer_->OnSubscribeTopicSuccess(false);
		}
	}
	else
	{
		if (observer_)
		{
			observer_->OnSubscribeTopicSuccess(true);
		}
	}
}
void CmdTransportMqtt::onMessageArrive(MQTTAsync_message* message)
{
	std::string msg;
	msg.append((char *)message->payload, message->payloadlen);

	if (observer_)
	{
		observer_->OnReceiveMessage(msg);
	}
}