package fr.zng.xxzx.mqtt2;

import java.math.BigDecimal;

import javax.swing.JTextArea;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;

import com.alibaba.fastjson.JSONObject;

import fr.zng.xxzx.common.cacheData.ZngCacheData;
import fr.zng.xxzx.common.dao.BcFlowDao;
import fr.zng.xxzx.common.dao.DictDao;
import fr.zng.xxzx.common.dao.EquipWsdDao;
import fr.zng.xxzx.common.dao.TdFlowDao;
import fr.zng.xxzx.common.dao.UnoDao;
import fr.zng.xxzx.common.dao.UpdataDao;
import fr.zng.xxzx.common.dao.impl.BcFlowDaoImpl;
import fr.zng.xxzx.common.dao.impl.DictDaoImpl;
import fr.zng.xxzx.common.dao.impl.EquipWsdDaoImpl;
import fr.zng.xxzx.common.dao.impl.TdFlowDaoImpl;
import fr.zng.xxzx.common.dao.impl.UnoDaoImpl;
import fr.zng.xxzx.common.dao.impl.UpdataDaoImpl;
import fr.zng.xxzx.common.entity.BcFlowEntity;
import fr.zng.xxzx.common.entity.DictEntity;
import fr.zng.xxzx.common.entity.EquipWsdEntity;
import fr.zng.xxzx.common.entity.HeartDataBcEntity;
import fr.zng.xxzx.common.entity.HeartDataEntity;
import fr.zng.xxzx.common.entity.TdEndDataEntity;
import fr.zng.xxzx.common.entity.TdEndReplyDataEntity;
import fr.zng.xxzx.common.entity.TdFlowEntity;
import fr.zng.xxzx.common.entity.TdSqDataEntity;
import fr.zng.xxzx.common.entity.TdSqReplyDataEntity;
import fr.zng.xxzx.common.entity.UnoEntity;
import fr.zng.xxzx.common.entity.UpDataEntity;
import fr.zng.xxzx.common.util.CommUtil;
import fr.zng.xxzx.common.util.StringUtil;
import fr.zng.xxzx.main.XmtApplication;

/**
 * 发布消息的回调类
 * 
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
 * 每个客户机标识都需要一个回调实例。在此示例中，构造函数传递客户机标识以另存为实例数据。 在回调中，将它用来标识已经启动了该回调的哪个实例。
 * 必须在回调类中实现三个方法：
 * 
 * public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
 * 
 * public void connectionLost(Throwable cause)在断开连接时调用。
 * 
 * public void deliveryComplete(MqttDeliveryToken token)) 接收到已经发布的 QoS 1 或 QoS 2
 * 消息的传递令牌时调用。 由 MqttClient.connect 激活此回调。
 * 
 */
public class PushCallbackBc implements MqttCallback {
	private JTextArea jta;
	public Server2 client;

	public PushCallbackBc(Server2 client,JTextArea jta) {
		this.jta = jta;
		this.client = client;
	}

	public void connectionLost(Throwable cause) {
		// 连接丢失后，一般在这里面进行重连
		System.out.println("连接断开，可以做重连");
		CommUtil.doPrint(jta, "MQTT:", "连接断开,开始尝试重新连接");
		ZngCacheData.isConnect = 0;
		XmtApplication.changeConnectState(0);

	}

	public void deliveryComplete(IMqttDeliveryToken token) {
		System.out.println("deliveryComplete---------" + token.isComplete());
		CommUtil.doPrint(jta, "MQTT:", "deliveryComplete---------" + token.isComplete());
	}

	public void messageArrived(String topic, MqttMessage message) throws Exception {
		// subscribe后得到的消息会执行到这里面
		System.out.println("接收消息主题 : " + topic);
		System.out.println("接收消息Qos : " + message.getQos());
		System.out.println("接收消息内容 : " + new String(message.getPayload()));
		

		String data = new String(message.getPayload());
		if ("".equals(data))
			return;

		try {
			 if (Server2.SUBSCRIBETOPIC.equals(topic)) {

				CommUtil.doPrint(jta, "MQTT:", "接收消息主题 : " + topic);
				CommUtil.doPrint(jta, "MQTT:", "接收消息Qos : " + message.getQos());
				CommUtil.doPrint(jta, "MQTT:", "接收消息内容 : " + new String(message.getPayload()));
				// 心跳
				HeartDataBcEntity heartEn =  JSONObject.parseObject(data, HeartDataBcEntity.class);
				if(heartEn != null) {
					if("0".equals(heartEn.Type)) {
						// 心跳
						CommUtil.doPrint(jta, "MQTT:", "收到心跳: " + heartEn.Dev);
						CommUtil.doPrint(jta, "MQTT:", "收到心跳: " + heartEn.TID);
						CommUtil.doPrint(jta, "MQTT:", "当前重量: " + heartEn.Kg);
						CommUtil.doPrint(jta, "MQTT:", "温湿度: " + heartEn.Humidity + " "+heartEn.Temp);
					} else {
						// 交易
						BigDecimal gar = new BigDecimal(heartEn.PayKg).multiply(new BigDecimal("1000")).setScale(0);
						String garbage = gar+"";

						BcFlowEntity en = new BcFlowEntity();
						en.setDel("0");
						if(heartEn.Dev!=null&&!"null".equals(heartEn.Dev)){
							en.setImei(heartEn.Dev);
						} else {
							en.setImei(heartEn.TID);
						}
						
						en.setPayKg(new BigDecimal(garbage));
						en.setHumidity(heartEn.Humidity);
						en.setName(heartEn.Name);
						en.setPayName(heartEn.PayName);
						en.setPayNumber(heartEn.PayNumber);
						en.setRfData(heartEn.RFData);
						en.setRfid(heartEn.RFID);
						en.setTemp(heartEn.Temp);
						BcFlowDao dao = new BcFlowDaoImpl();
						int ret =dao.insert(en);
						if(ret>0) {
							CommUtil.doPrint(jta, "MQTT:", "插入成功 " + ret);
						} else {
							CommUtil.doPrint(jta, "MQTT:", "插入失败");
						}
					}
				}
			}
			
			else {
				CommUtil.doPrint(jta, "MQTT:", "未知消息主题");
			}

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("订阅消息解析失败");
			CommUtil.doPrint(jta, "MQTT:", "订阅消息解析失败");
		}

	}

	/**
	 * 温湿度插入
	 * */
	private int insertWsd(EquipWsdEntity en){
		EquipWsdDao dao = new EquipWsdDaoImpl();
		return dao.insert(en);
	}
	/**
	 * 发布消息
	 * 
	 * @param message
	 */
	private int publish(int topic, String message) {
		System.out.println("发布消息:" + message);
		int ret = 0;
		client.message = new MqttMessage();
		client.message.setQos(2);
		client.message.setRetained(false);
		client.message.setPayload(message.getBytes());
		try {
			if (topic == 1) {
				client.publish(client.topic, client.message);
			} else if (topic == 2) {
				client.publish(client.topic2, client.message);
			} 

		} catch (MqttPersistenceException e) {
			e.printStackTrace();
			ret = -1;
			CommUtil.doPrint(jta, "MQTT:", "MQTT通信异常，请检查网络连接或MQTT服务器");
		} catch (MqttException e) {
			e.printStackTrace();
			ret = -1;
			CommUtil.doPrint(jta, "MQTT:", "MQTT通信异常，请检查网络连接或MQTT服务器");
		}
		return ret;
	}
	
	
	/**
	 * 审核用户名
	 * 
	 * @param uno
	 * @return
	 */
	private Boolean checkUno(String uno) {
		UnoDao dao = new UnoDaoImpl();
		UnoEntity en = dao.getVillageUserCinfoByUno(uno);
		if (en != null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 插入投递记录
	 * 
	 * @return
	 */
	private int InsertTdFlow(TdFlowEntity en) {
		TdFlowDao dao = new TdFlowDaoImpl();
		return dao.insert(en);
	}

	private int checkWsd(String imei) {
		EquipWsdDao dao = new EquipWsdDaoImpl();
		return dao.checkWsd(imei);
	}

	/**
	 * 插入异常投递记录
	 * 
	 * @return
	 */
	private int InsertTdFlowErr(TdFlowEntity en) {
		TdFlowDao dao = new TdFlowDaoImpl();
		return dao.insertErr(en);
	}
}