#include "IOTComm.h"

//******************************************************************************
//* Global Variables
//******************************************************************************
//IOTCommClass IOTComm;

//******************************************************************************
//* Constructor
//******************************************************************************
IOTCommClass::IOTCommClass() {
}

//******************************************************************************
//* Public member functions - low-level interfaces
//******************************************************************************
void IOTCommClass::setWifiName(char wifiname[]) {
	String temp = wifiname;
	char msg[MAX_WIFISSID_LEN] = {};
	msg[0] = WiFiNameFlag;
	strcat(msg,wifiname);
	strcat(msg,"#");
	
	//debug
	//Serial.println(msg);
  iotserial.write(msg);
	delay(CFG_INTERVAL);
}

void IOTCommClass::setWifiPassword(char wifipassword[]) {
	String temp = wifipassword;
	char msg[MAX_WIFIPASSWORD_LEN] = {};
	msg[0] = WiFiPasswordFlag;
	strcat(msg,wifipassword);
	strcat(msg,"#");
	
	//debug
	//Serial.println(msg);
	iotserial.write(msg);
	delay(CFG_INTERVAL);
}

void IOTCommClass::setProjectKey(char pjkey[16]) {
	strcpy(m_projectkey, "");
	for(int i = 0 ; i< 16 ; i++){
		m_projectkey[i] = pjkey[i];
	}
	setDestTopicRootPath();
	setWebSrcTopicRootPath();
	setArduinoSrcTopicRootPath();
	delay(CFG_INTERVAL);
}

void IOTCommClass::setClientKey(byte ctkey[]) {

}

void IOTCommClass::setServerAddr(byte seraddr[]) {

}

void IOTCommClass::setServerPort(double portnum) {

}

void IOTCommClass::setServerLoginID(byte serid[]) {

}

void IOTCommClass::setServerLoginPassWord(byte serpw[]) {

}

void IOTCommClass::publishMsg(char topic[2], int data) {
	char temp[MAX_DATA_LEN] = {};
	char msgd[MAX_DATA_LEN] = {};

	iotserial.listen();
	setDestTopic(topic);
	itoa(data,temp,DEC);
	msgd[0] = PubMsgFlag;
	strcat(msgd,temp);
	strcat(msgd,"#");
		
	//DEBUG
	//Serial.println(msgd);
//			
//	if(idleflag){
//		idleflag = false;
//		
//		idleflag = true;
//	}

	iotserial.write(msgd);
	delay(PUB_INTERVAL);
}

void IOTCommClass::publishMsg(char topic[2], long data) {
	char temp[MAX_DATA_LEN] = {};
	char msgd[MAX_DATA_LEN] = {};
	
	iotserial.listen();
	setDestTopic(topic);
	ltoa(data,temp,DEC);
	
	msgd[0] = PubMsgFlag;
	strcat(msgd,temp);
	strcat(msgd,"#");
	
	//DEBUG
	//Serial.println(msgd);
	iotserial.write(msgd);
	delay(PUB_INTERVAL);
}

void IOTCommClass::publishMsg(char topic[2], float data) {

}

void IOTCommClass::publishMsg(char topic[2], int data1, int data2) {
	char temp1[MAX_DATA_LEN] = {};
	char msgd[MAX_DATA_LEN] = {};
	int r = 0;
	
	iotserial.listen();
	setDestTopic(topic);
  intToCharArray(data1, data2 , temp1, 8);
	msgd[0] = PubMsgFlag;
	strcat(msgd,temp1);
	strcat(msgd,"#");
	while (msgd[r]!= 0)
	{
    r++;
	}
	
	//debug
	//Serial.println(msgd);
	iotserial.write(msgd);
	delay(PUB_INTERVAL);
}

void IOTCommClass::publishMsg(char topic[2], String str){
	char temp[MAX_DATA_LEN] = {};
	char msgd[MAX_DATA_LEN] = {};
	int r = 0;
	
	iotserial.listen();
	setDestTopic(topic);
	strcpy(temp,str.c_str());
	 
	int len = strlen(temp);
	
	if(len > 16){
		return;
	}
	
	msgd[0] = PubMsgFlag;
	strcat(msgd,temp);
	strcat(msgd,"#");
	while (msgd[r]!= 0)
	{
    r++;
	}
	
	//debug
  //Serial.print(msgd);
	iotserial.write(msgd);
	delay(PUB_INTERVAL);
}

void IOTCommClass::publishMsg(char topic[2], uint8_t * data , int len){
//	unsigned char temp[MAX_DATA_LEN] = {};
//	char msgd[MAX_DATA_LEN] = {};
//	int r = 0;
//	
//	if(len > 32)
//		return;
//		
//	setDestTopic(topic);
//	msgd[0] = PubMsgFlag;
//	
//	for(int i = 0 ; i < len ; i ++){
//		temp[i] = ((const unsigned char)data[i]);
//	}
//	
//	Serial.print(temp);
//	//memcpy(temp,data,len);
//	//strcat(msgd,temp);
//	//Serial.print((char)temp);
//	//strcat(msgd,temp[i]);
//	strcat(msgd,"#");
//	while (msgd[r]!= 0)
//	{
//    r++;
//	}
//	
//	//debug
//  //Serial.print(msgd);
//	iotserial.write(msgd);
//	delay(PUB_INTERVAL);
}

void IOTCommClass::publishStatus(char data[16]){
	char statustopic[] = "heartbeat";
	char msgd[MAX_DATA_LEN] = {};
	int r = 0;
	
	setDestTopic(statustopic);
	msgd[0] = PubMsgFlag;
	strcat(msgd,data);
	strcat(msgd,"1");
	strcat(msgd,"#");
	while (msgd[r]!= 0)
	{
    r++;
	}
	
	//debug
  //Serial.println(r);
	iotserial.write(msgd);
	delay(PUB_INTERVAL);
}

void IOTCommClass::subscribeWebTopic(char topic[2]) {
	char msgt[MAX_DATA_LEN] = {};
	getWebSrcTopic(msgt,topic);
	
	//debug
	//Serial.println(msgt);
	iotserial.write(msgt);
	delay(CFG_INTERVAL);
}

void IOTCommClass::subscribeArduinoTopic(char topic[2]) {
	char msgt[MAX_DATA_LEN] = {};
	getArduinoSrcTopic(msgt,topic);
	
	//debug
	//Serial.println(msgt);
	iotserial.write(msgt);
	delay(CFG_INTERVAL);
}

void IOTCommClass::connect() {
	
	char msgd[MAX_DATA_LEN] = {};
	msgd[0] = ConnectFlag;
	//strcat(msgd,"#");
	int times = 2;
	
	//debug
  //Serial.println(msgd);
	for(int i = 0 ; i  < times ; i ++){
		iotserial.write(msgd);
		delay(2 * CFG_INTERVAL);
	}
	
	delay(12000);
}

void IOTCommClass::setSerialPort(int m_rxd, int m_txd) {
	SoftwareSerial iotserial(m_rxd,m_txd); // RX, TX
}

void IOTCommClass::setserialBegin() {
	iotserial.begin(38400);
	delay(CFG_INTERVAL);
	//iotserial.listen();
}

void IOTCommClass::setDestTopicRootPath(){
	strcpy(m_desttopicrootpath, "");
	strncpy(m_desttopicrootpath,m_projectkey,16);
	strcat(m_desttopicrootpath,"/arduino/");
}

char lastDesttopic [MAX_TOPIC_LEN] ={};
void IOTCommClass::setDestTopic(char usertopic[]){
	char msgt[MAX_DATA_LEN] = {};
	int r = 0;
	
	//判断topic是否有变化，没有变化则不更新topic内容
	//if((lastDesttopic[0] != usertopic[0]) || (lastDesttopic[1] != usertopic[1])){
		msgt[0] = TopicFlag;
		strcat(msgt,m_desttopicrootpath);
		strcat(msgt,usertopic);
		strcat(msgt,"#");
	  lastDesttopic[0] = usertopic[0];
		lastDesttopic[1] = usertopic[1];
		//while (msgt[r]!= 0)
		//{
   	// 	r++;
		//}
		//debug
		//Serial.println(msgt);
		
	if(idleflag){
		idleflag = false;
		iotserial.write(msgt);
		idleflag = true;
	}
	delay(PUB_INTERVAL);
		//Serial.println("change topic!");
	//}
}

void IOTCommClass::setWebSrcTopicRootPath(){
	strcpy(m_srcwebtopicrootpath, "");
	strncpy(m_srcwebtopicrootpath,m_projectkey,16);
	strcat(m_srcwebtopicrootpath,"/web/");
}

void IOTCommClass::setArduinoSrcTopicRootPath(){
	strcpy(m_srcarduinotopicrootpath, "");
	strncpy(m_srcarduinotopicrootpath,m_projectkey,16);
	strcat(m_srcarduinotopicrootpath,"/arduino/");
}

void IOTCommClass::getWebSrcTopic(char * dest , char usertopic[2]){
	char msgt[MAX_DATA_LEN] = {};
	msgt[0] = SubMsgFlag;
	strcat(msgt,m_srcwebtopicrootpath);
	strcat(msgt,usertopic);
	strcat(msgt,"#");
	for(int i = 0 ;i < MAX_TOPIC_LEN ; i++){
		dest[i] = msgt[i];
	}
	//debug
	//Serial.println(dest);
}

void IOTCommClass::getArduinoSrcTopic(char * dest , char usertopic[2]){
	char msgt[MAX_DATA_LEN] = {};
	msgt[0] = SubMsgFlag;
	strcat(msgt,m_srcarduinotopicrootpath);
	strcat(msgt,usertopic);
	strcat(msgt,"#");
	for(int i = 0 ;i < MAX_TOPIC_LEN ; i++){
		dest[i] = msgt[i];
	}
	//debug
	//Serial.println(dest);
}

int IOTCommClass::available(){
  return iotserial.available();
}

bool IOTCommClass::readMsg(char * mtopic, char * mpayload){

	char temp[MAX_DATA_LEN * 2] = {};
	char m_temptopic[MAX_TOPIC_LEN] = {};
	int tplencharnum = 2;
	int pllencharnum = 3;
  int r = 0;
	int i = 0;
	bool vaild = false;
	
	
	for(int j = 0 ; j < MAX_DATA_LEN * 2; j++){
		vaild = true;
    temp[i] = (char)iotserial.read();
    if(temp[i] == '#'){
      break;
    }else{
      i++;
      delay(2);
    }
  }
	
	if(iotserial.overflow()){
		iotserial.flush();
		iotserial.end();
		iotserial.begin(38400);
		iotserial.listen();
		//debug
		//Serial.println("overflow!");
	}
	
  for(i = 0 ; i < MAX_DATA_LEN ; i++){
  	mpayload[i] = 0;
  }
  
  //读取数组前2个char到数组x
  char x[16] ={0};
  for(i = 0 ; i < tplencharnum ; i++){
  	x[i] = temp[i];
  }
  
  int tplen = atoi(x);
  if((tplen < 0) || tplen > MAX_DATA_LEN){
  	return false;
  }
  //debug
  //Serial.println(tplen);
  
  for(i = 0 ;i < 2 ; i ++){
  	mtopic[i] = temp[tplen + i];
  }
  //debug
  //Serial.println(mtopic);

  //读取数组topic后3个char到数组y
  char y[16] ={0};
  for(i = 0 ; i < 3 ; i++){
  	y[i] = (char)temp[tplen + 2 + i];
  }
  
  int pllen = atoi(y);
  if((pllen < 0) || pllen > MAX_DATA_LEN){
  	return false;
  }
  //debug
  //Serial.println(pllen);
  
  for(i = 0 ;i < pllen ; i ++){
  	mpayload[i] = temp[tplen + i + 2 + 3];
  }
  //debug
  //Serial.println(mpayload);
  
	return vaild;
}

char IOTCommClass::read(){
	//return (char)(iotserial.read());
}

bool IOTCommClass::intToCharArray(int data1, int data2 , char * buf , int len){
	
	//assert

	if(len == 8){
	  if(data1 < 10){
	    buf[0] = ' ';
	    buf[1] = ' ';
	    buf[2] = ' ';
	    buf[3] = (char)('0' + data1 / 1 % 10);
	  }else if(data1 >= 10 && data1 < 100){
	    buf[0] = ' ';
	    buf[1] = ' ';
	    buf[2] = (char)('0' + data1 / 10 % 10);
	    buf[3] = (char)('0' + data1 / 1 % 10);
	  }else if(data1 >= 100 && data1 < 1000){
	    buf[0] = ' ';
	    buf[1] = (char)('0' + data1 / 100 % 10);
	    buf[2] = (char)('0' + data1 / 10 % 10);
	    buf[3] = (char)('0' + data1 / 1 % 10);
	  }else if(data1 >= 1000 && data1 < 10000){
	  	buf[0] = (char)('0' + data1 / 1000 % 10);
	    buf[1] = (char)('0' + data1 / 100 % 10);
	    buf[2] = (char)('0' + data1 / 10 % 10);
	    buf[3] = (char)('0' + data1 / 1 % 10);
	  }
	  if(data2 < 10){
	    buf[4] = ' ';
	    buf[5] = ' ';
	    buf[6] = ' ';
	    buf[7] = (char)('0' + data2 / 1 % 10);
	  }else if(data2 >= 10 && data2 < 100){
	    buf[4] = ' ';
	    buf[5] = ' ';
	    buf[6] = (char)('0' + data2 / 10 % 10);
	    buf[7] = (char)('0' + data2 / 1 % 10);
	  }else if(data2 >= 100 && data2 < 1000){
	    buf[4] = ' ';
	    buf[5] = (char)('0' + data2 / 100 % 10);
	    buf[6] = (char)('0' + data2 / 10 % 10);
	    buf[7] = (char)('0' + data2 / 1 % 10);
	  }else if(data2 >= 1000 && data2 < 10000){
	  	buf[4] = (char)('0' + data2 / 1000 % 10);
	    buf[5] = (char)('0' + data2 / 100 % 10);
	    buf[6] = (char)('0' + data2 / 10 % 10);
	    buf[7] = (char)('0' + data2 / 1 % 10);
	  }
	}
	
	//debug
	//Serial.println(buf);
	return 1;
}

void IOTCommClass::listen() {
	iotserial.listen();
}