package com.iwunu.nbiot.lock.service.impl;
import java.util.Map;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.iwunu.nbiot.common.constant.CacheKeyConstant;
import com.iwunu.nbiot.common.util.CmdKeyUtil;
import com.iwunu.nbiot.common.util.DateUtil;
import com.iwunu.nbiot.common.util.ReportSeverEnum;
import com.iwunu.nbiot.lock.aepclient.AepCommandClient;
import com.iwunu.nbiot.lock.cache.RedisService;
import com.iwunu.nbiot.lock.entity.CmdData;
import com.iwunu.nbiot.lock.entity.IotLock;
import com.iwunu.nbiot.lock.entity.ReportLog;
import com.iwunu.nbiot.lock.service.IotCmdDataService;
import com.iwunu.nbiot.lock.service.IotLockService;
import com.iwunu.nbiot.lock.service.IotLogService;
import com.iwunu.nbiot.lock.service.LockMqttReceiveService;
import com.iwunu.nbiot.lock.util.MessageConversionAdapter;
import com.iwunu.nbiot.lock.util.MessageMapParse;
import com.iwunu.nbiot.lock.util.ReportDataKeyUtil;

@Service
public class LockMqttReceiveServiceImpl implements LockMqttReceiveService {
	private final static Logger logger = LoggerFactory.getLogger(LockMqttReceiveServiceImpl.class);
	@Autowired
	private RedisService redisService;
	@Autowired
	private IotLockService iotLockService;
	@Autowired
	private AepCommandClient aepCommandClient;
	@Autowired
	private IotLogService iotNbLogService;
	@Autowired
	private IotCmdDataService iotCmdDataService;
	@Autowired
	private MessageConversionAdapter messageConversionAdapter;
//	private final static Integer maxCmdLength = 30;
	private final static String delCmdTyp = "delete";
	public static CloseableHttpClient httpclient;
	static {
		httpclient = HttpClients.createDefault();
	}

	@Override
	public void handlerOnlineMqttMessage(String msg) {
		JSONObject receiveJson = JSONObject.parseObject(msg);
		String data = MessageMapParse.getData(receiveJson.getString("message"));
		String deviceId = receiveJson.getString("deviceId");
		Map<String, Object> datamap = MessageMapParse.parseMessage(data.length(), data);
		if (redisService.get(CacheKeyConstant.REDIS_ONLINE_KEY + deviceId) == null) {
			IotLock lock = iotLockService.findLockByDeviceId(deviceId);
			lock.setSignalInfo(Integer.valueOf(datamap.get("signal").toString()));
			lock.setElectric(Integer.valueOf(datamap.get("electric").toString()));
			lock.setIsOpen(Integer.valueOf(datamap.get("openDoor").toString()));
			lock.setReportTime(DateUtil.nowDateTime());
			lock.setSimNum(datamap.get("ccid").toString());
			iotLockService.saveAndUpdate(lock);
			redisService.setex(CacheKeyConstant.REDIS_ONLINE_KEY + deviceId, deviceId,
					CacheKeyConstant.ONLINE_CACHE_TIME);
		}
		this.handlerCmdMessage(deviceId);
	}

	@Override
	public void handlerAnswerMqttMessage(String msg) {
		JSONObject receiveJson = JSONObject.parseObject(msg);
		String data = MessageMapParse.getData(receiveJson.getString("message"));
		String deviceId = receiveJson.getString("deviceId");
		String random = MessageMapParse.getRandom(receiveJson.getString("message"));
		String stampTime = MessageMapParse.getStampTime(receiveJson.getString("message"));
		Map<String, Object> datamap = MessageMapParse.parseMessage(data.length(), data);
		String cmdType = MessageMapParse.getCmdType(data);
		CmdData cmd = iotCmdDataService.findListByCmdStampAndDeviceId(deviceId, random, stampTime);
		Integer status = Integer.parseInt(datamap.get(cmdType).toString());
		if (cmd != null) {
			if (!cmdType.contains(CmdKeyUtil.delCmdTyp)) {
				cmd.setReportContext(msg);
				cmd.setReportTime(DateUtil.nowDate());
				cmd.setStatus(status == 1 ? 1 : 2);
				iotCmdDataService.update(cmd);
			} else if (status == 1) {
				iotCmdDataService.delete(cmd);
			}
		} else {
			if (status == 1 && datamap.containsValue(CmdKeyUtil.DELETEALLCARDNO)) {
				iotCmdDataService.deleteByDeviceIdAndCmdType(deviceId, cmdType);
			}
			if (status == 1 && datamap.containsValue(CmdKeyUtil.DELETEALLPASSWORD)) {
				iotCmdDataService.deleteByDeviceIdAndCmdType(deviceId, cmdType);
			}
			if (status == 1 && datamap.containsValue(CmdKeyUtil.DELETEALLCMD)) {
				iotCmdDataService.deleteByDeviceId(deviceId);
			}
		}
		logger.info("Answer:" + JSONObject.toJSON(datamap));
		this.handlerCmdMessage(deviceId);
	}

	@Override
	public void handlerOpenlockMqttMessage(String msg) {
		JSONObject receiveJson = JSONObject.parseObject(msg);
		String deviceId = receiveJson.getString("deviceId");
		String data = MessageMapParse.getData(receiveJson.getString("message"));
		String random = MessageMapParse.getRandom(receiveJson.getString("message"));
		Map<String, Object> datamap = MessageMapParse.parseMessage(data.length(), data);
		if (datamap.get("openDoor") != null) {
			iotNbLogService.updateLog(deviceId, random, Integer.parseInt(datamap.get("openDoor").toString()));
			redisService.del(CacheKeyConstant.REDIS_OPEN_KEY + deviceId);
		}
		this.handlerCmdMessage(deviceId);
	}

	/**
	 * 处理缓存内容
	 * 
	 * @param deviceId
	 */
	public void handlerCmdMessage(String deviceId) {
		this.cacheDeviceOnlineStatus(deviceId);
		synchronized (deviceId) {
			JSONObject param = new JSONObject();
			// 处理开锁信息，通过接口下发到AEP平台
			if (redisService.get(CacheKeyConstant.REDIS_OPEN_KEY + deviceId) != null) {
				String openLockData = messageConversionAdapter
						.getOpenLockData(redisService.get(CacheKeyConstant.REDIS_OPEN_KEY + deviceId));
				param.put("deviceId", deviceId);
				param.put("payload", openLockData);
				aepCommandClient.sendMessagePost(param);
			}
			// 处理缓存卡/密码信息。通过接口下发到AEP平台
			if (redisService.listSize(CacheKeyConstant.CACHE_CMD_KEY + deviceId) > 0) {
				param = new JSONObject();
				/** 批量处理模块 **/
//				List<String> cmds = new ArrayList<String>();
//				param =  new JSONObject();
//				Long listsize = redisService.listSize(CacheKeyConstant.CACHE_CMD_KEY+deviceId);
//				while(redisService.listSize(CacheKeyConstant.CACHE_CMD_FINGER_KEY+deviceId)>0) {
//					cmds.add(redisService.leftPop(CacheKeyConstant.CACHE_CMD_KEY+deviceId).toString());
//					if(listsize.intValue()>maxCmdLength && cmds.size()==maxCmdLength) {
//						String cmdData = messageConversionAdapter.getSendDatas(cmds);
//						param.put("deviceId", deviceId);
//						param.put("payload", cmdData);
//						aepCommandClient.sendMessagePost(param);
//						cmds = new ArrayList<String>();
//					}
//				}
				String cmdData = redisService.leftPop(CacheKeyConstant.CACHE_CMD_KEY + deviceId).toString();
				JSONObject cmd = JSONObject.parseObject(cmdData);
				String startTime = cmd.getString("startTime");
				String endTime = cmd.getString("endTime");
				String minType = cmd.getString("cmdType");
				Integer pitNum = cmd.getInteger("pitNum");
				String data = cmd.getString("cmdContext");
				String random = cmd.getString("random");
				String stamptime = cmd.getString("stamptime");
				if (minType.contains(delCmdTyp)) {
					data = "00000000";
					endTime = "";
					startTime = "";
				}
				String sendData = messageConversionAdapter.getSendData(data, pitNum,
						ReportDataKeyUtil.REPORT_TYPE_KEY.get(minType), startTime, endTime);
				String cmdPackage = messageConversionAdapter.getSendCmdData(sendData, random, stamptime);
				param.put("deviceId", deviceId);
				param.put("payload", cmdPackage);
				aepCommandClient.sendMessagePost(param);
			}
			// 处理缓存指纹信息。通过接口下发到AEP平台
			if (redisService.listSize(CacheKeyConstant.CACHE_CMD_FINGER_KEY + deviceId) > 0) {
				param = new JSONObject();
				String fingerData = redisService.leftPop(CacheKeyConstant.CACHE_CMD_FINGER_KEY + deviceId).toString();
				JSONObject finger = JSONObject.parseObject(fingerData);
				String startTime = finger.getString("startTime");
				String endTime = finger.getString("endTime");
				String minType = finger.getString("cmdType");
				Integer pitNum = finger.getInteger("pitNum");
				String data = finger.getString("cmdContext");
				String random = finger.getString("random");
				String stamptime = finger.getString("stamptime");
				String finger1 = data.substring(0, data.length() / 2);
				String finger2 = data.substring(data.length() / 2, data.length());
				String sendData1 = messageConversionAdapter.getSendFingerData(finger1, pitNum,
						ReportDataKeyUtil.REPORT_TYPE.get(minType), startTime, endTime);
				String sendData2 = messageConversionAdapter.getSendFingerData(finger2, pitNum,
						ReportDataKeyUtil.REPORT_TYPE.get(minType), null, null);
				String package1 = messageConversionAdapter.getSendCmdData(sendData1, random, stamptime);
				String package2 = messageConversionAdapter.getSendCmdData(sendData2, random, stamptime);
				param.put("deviceId", deviceId);
				param.put("payload", package1);
				JSONObject result = aepCommandClient.sendMessagePost(param);
				if (result != null) {
					logger.info("first :" + result.toJSONString());
					param.put("payload", package2);
					result = aepCommandClient.sendMessagePost(param);
				}
				if (result != null) {
					logger.info("second :" + result.toJSONString());
				}
			}
		}
	}

	@Override
	public void handlerLockLogMqttMessage(String msg) {
		JSONObject receiveJson = JSONObject.parseObject(msg);
		String deviceId = receiveJson.getString("deviceId");
		this.saveLog(receiveJson);
		this.handlerCmdMessage(deviceId);
	}

	public void saveLog(JSONObject receiveJson) {
		Integer status = 0;
		Integer pitNumReport = null;
		String data = MessageMapParse.getData(receiveJson.getString("message"));
		String deviceId = receiveJson.getString("deviceId");
		String random = MessageMapParse.getRandom(receiveJson.getString("message"));
		String stampTime = MessageMapParse.getStampTime(receiveJson.getString("message"));
		String reportTime = DateUtil.stampToDate(Long.valueOf(stampTime,16)-60 * 60 * 8 );
		Map<String, Object> datamap = MessageMapParse.parseMessage(data.length(), data);
		if (datamap == null) {
			return;
		}
		String cmdType = MessageMapParse.getCmdType(data);
		ReportLog log = new ReportLog();
		log.setDeviceId(deviceId);
		log.setLockType(1);
		log.setRandom(random);
		log.setCreateTime(DateUtil.nowDateTime());
		log.setReportTime(reportTime);
		if (datamap.get("status") != null) {
			status = Integer.valueOf(datamap.get("status").toString());
		}
		log.setStatus(status);
		Integer reporttype = ReportSeverEnum.getType(cmdType);
		log.setType(reporttype);
		log.setData(datamap.get(cmdType).toString());
		log.setElectric(datamap.get("electric").toString());
		if (datamap.get("pitNumReport") != null) {
			pitNumReport = Integer.valueOf(datamap.get("pitNumReport").toString());
		}
		log.setPitNum(Integer.valueOf(pitNumReport));
		iotNbLogService.saveLog(log);
	}
    public void cacheDeviceOnlineStatus(String deviceId) {
    	redisService.setex("online_"+deviceId,"1",8);
    }
    
    public static void main(String[] args) {
    	
    	System.out.println( DateUtil.stampToDate(Long.valueOf(DateUtil.getStamp(),16)-60 * 60 * 8 ));
		System.out.println(DateUtil.nowDateTime());
	}
    
}
