package cn.service.atv.impl;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import cn.pojo.atv.*;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson2.JSONObject;
import cn.facade.abs.IService;
import cn.common.page.response.Result;
import cn.component.util.HttpService;
import cn.api.websocket.AtvWebSocket;
import cn.facade.constant.AtvConst;
import cn.constant.CharsetKit;
import cn.orm.sqltoy.model.Page;
import cn.orm.sqltoy.plus.Wrappers;
import cn.orm.sqltoy.plus.query.LambdaQueryWrapper;
import cn.orm.sqltoy.plus.query.QueryWrapper;
import cn.pojo.atv.vo.AtvEquipmentOnlineStatus;
import cn.service.atv.IAtvService;
import cn.util.core.IsKit;
import cn.util.core.LogKit;
import cn.util.core.TypeKit;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

@Service
public class AtvServiceImpl extends IService implements IAtvService
{
	@Resource
	private HttpService httpService;
	@Resource
	private AtvWebSocket atvWebSocket;

	/***远程喊话*/
	@Override
	public boolean playVoice(String id, MultipartFile files) throws Exception {
		QueryWrapper<AtvTts> wrapper = Wrappers.wrapper(AtvTts.class)
				.eq("id",id);
		AtvTts entity = daoService.findOne(wrapper);
		if(IsKit.isNull(entity)) {
			return false;
		}
		String userId = _getUniqueId(entity.getTrainId());
		return atvWebSocket.sendVoiceMessage(userId, entity.getId(), files.getBytes());
	}

	/***远程广播*/
	@Override
	public boolean uploadTts(AtvTts entity)
	{
    	Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code",AtvConst.CMD_CODE_NUM5);
		jsonObject.put("timestamp", timestamp);
		jsonObject.put("messageId", entity.getId());
		JSONObject json = new JSONObject();
		json.put("ttsText", entity.getTtsText());
		jsonObject.put("data", json);
		String userId = _getUniqueId(entity.getTrainId());
		return atvWebSocket.sendTtsMessage(0, userId, entity.getId(), jsonObject.toString());
	}

   /**此方法暂时没有用*/
	@Override
	public boolean uploadText(AtvBroadcast entity)
	{
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code",AtvConst.CMD_CODE_NUM5);
		jsonObject.put("timestamp", timestamp);
		jsonObject.put("messageId", entity.getId());
		JSONObject json = new JSONObject();
		json.put("ttsText", entity.getBroadText());
		//json.put("broadType", entity.getBroadType());
		//json.put("broadNum", entity.getBroadNum());
		jsonObject.put("data", json);
		String userId = _getUniqueId(entity.getTrainId());
		return atvWebSocket.sendTtsMessage(0, userId,String.valueOf(entity.getId()), jsonObject.toString());
	}
	/**
	 *	http://localhost:8080/audio/文件audio_link
	 */
	@Override
	public boolean playTts(String id)
	{
		QueryWrapper<AtvTts> wrapper = Wrappers.wrapper(AtvTts.class)
				.eq("id",id);
		AtvTts entity = daoService.findOne(wrapper);
		if(IsKit.isNull(entity)) {
			return false;
		}
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code", AtvConst.CMD_CODE_NUM7);
		jsonObject.put("timestamp", timestamp);
		jsonObject.put("messageId", entity.getId());
		JSONObject json = new JSONObject();
		json.put("audioSn", entity.getAudioSn());
		jsonObject.put("data", json);
		String userId = _getUniqueId(entity.getTrainId());
		return atvWebSocket.sendTtsMessage(1, userId, entity.getId(), jsonObject.toString());
	}
	/**三种方式（QueryWrapperTest）应都可以，待验证*/
	@Override
	public Page<?> logPlayback(String trainId, String startTime, String endTime, Integer number, Integer pageSize) 
	{
		QueryWrapper<AtvTrainWorkingLog> queryWrapper = Wrappers.wrapper(AtvTrainWorkingLog.class)
				.eq("trainId", trainId)
				.ge("createTime", startTime)
				.le("createTime", endTime); 
		Map<String, Object> pageMap = new HashMap<>();
		pageMap.put("pageSize", pageSize);
		pageMap.put("pageNum", number);
		Page<?> page = daoService.getPage(pageMap);
		return daoService.findPage(queryWrapper,page);
	
	}
	@Override
	public Long logCount(String trainId, String startTime, String endTime)
	{
		LambdaQueryWrapper<AtvTrainWorkingLog> lambdaQueryWrapper = Wrappers.lambdaWrapper(AtvTrainWorkingLog.class)
				.eq(AtvTrainWorkingLog::getTrainId, trainId)
				.ge(AtvTrainWorkingLog::getCreateTime, startTime)
				.le(AtvTrainWorkingLog::getCreateTime, endTime);
		return daoService.count(lambdaQueryWrapper);
	}

	@Override
	public List<AtvEquipmentOnlineStatus> findOnlineStatus(String trainId, String startTime) 
	{
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("trainId",trainId);
		paramMap.put("startTime",startTime);
		return TypeKit.cast(daoService.getEntityListBySql("atv_findOnlineStatus",
				paramMap,AtvEquipmentOnlineStatus.class));
	}


	/**1:设备日志、背景音频、报警音频
	 * 2:仅设备日志
	 * 3:仅设备背景音频
	 * 4:仅设备报警音频*/
	@Override
	public Boolean downloadLog(Map<String,Object> pageMap) 
	{
		LogKit.info("downloadLog："+pageMap.get("sn"));
		//页面编码从1开始
		int method = TypeKit.objToInt(pageMap.get("method")) - 1;
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code",AtvConst.CMD_CODE_NUM14);
		jsonObject.put("timestamp", timestamp);
		JSONObject json = new JSONObject();
		json.put("method", method);
		json.put("deviceNo", pageMap.get("sn"));
		json.put("StartDate",pageMap.get("beginTime"));
		json.put("EndDate", pageMap.get("endTime"));
		jsonObject.put("data", json);

		return atvWebSocket.sendEquipmentMessage(_getUniqueId(pageMap), jsonObject.toString());
	}

	@Override
	public Result<?> upgradeAll(Map<String,Object> pageMap) 
	{
		String lineId = TypeKit.objToStr(pageMap.get("lineId"));
		String trainId = TypeKit.objToStr(pageMap.get("trainId"));
		String sn = TypeKit.objToStr(pageMap.get("sn"));
		String fileName = TypeKit.objToStr(pageMap.get("fileNameList"));
		String filePrefix = TypeKit.objToStr(pageMap.get("filePrefix"));
		String dirName = TypeKit.objToStr(pageMap.get("dirName"));
		String uploadPath = fileService.getFileFullPath(dirName);
		if(IsKit.isNullOrEmpty(fileName )){
			return Result.warnMsg("文件名为空!");
		}
		/*CharsetKit.SYMBOL_HIFEN文件前缀与文件名之间的分隔符
		String filePath = uploadPath + filePrefix +CharsetKit.SYMBOL_HIFEN + fileName;
		String fileUrl = httpService.getUrl() + CharsetKit.SYMBOL_BACK_SLASH
				+ dirName + CharsetKit.SYMBOL_BACK_SLASH
				+ filePrefix +CharsetKit.SYMBOL_HIFEN + fileName;*/
		String filePath = uploadPath;
		String fileUrl = httpService.getUrl() + CharsetKit.SYMBOL_BACK_SLASH
				+ dirName + CharsetKit.SYMBOL_BACK_SLASH;
		if(IsKit.isNullOrEmpty(filePrefix)){
			filePath =filePath + fileName;
			fileUrl = fileUrl + fileName;
		}
		else{
			filePath = filePath + filePrefix +CharsetKit.SYMBOL_HIFEN + fileName;
			fileUrl = fileUrl + filePrefix + CharsetKit.SYMBOL_HIFEN + fileName;;
		}

		String md5Sum;
		try {
			md5Sum = DigestUtils.md5Hex(new FileInputStream(filePath));
		} catch (Exception e) {
			LogKit.info(e);
			return Result.warnMsg("升级失败,加密失败!");
		}
		//升级当前车辆所有同类设备。trainId为空 页面状态tate.updateForm.status为：2
		if(IsKit.isNotNullOrEmpty(trainId)) 
		{
			QueryWrapper<AtvEquipment> wrapper = Wrappers.wrapper(AtvEquipment.class)
					.select("equipmentType")
					.eq("trainId",trainId)
					.eq("sn",sn);
			AtvEquipment entityE = daoService.findOne(wrapper);
			if(IsKit.isNull(entityE)) {
				return Result.warnMsg("升级失败，设备数据不对!");
			}			

			Long timestamp = System.currentTimeMillis();
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("cmd_code",AtvConst.CMD_CODE_NUM13);
			jsonObject.put("timestamp", timestamp);
			JSONObject json = new JSONObject();
			json.put("method",AtvConst.METHOD_NUM0);
			json.put("devicetype", _equipmentType(entityE.getEquipmentType()));
			json.put("fileUrl", fileUrl);
			json.put("md5Sum", md5Sum);
			jsonObject.put("data", json);

			boolean result = atvWebSocket.sendEquipmentMessage(_getUniqueId(pageMap), jsonObject.toString());
			if (result) {
				return Result.okMsg("升级成功!");
			}
			return Result.warnMsg("升级失败，车辆离线!");
		}

		//当前线路所有车辆同类设备：trainId为空 页面状态tate.updateForm.status为：3
		LambdaQueryWrapper<AtvTrain> wrapperT = Wrappers.lambdaWrapper(AtvTrain.class)
				.eq(AtvTrain::getLineId,lineId);
		List<AtvTrain> atvTrainList = daoService.findList(wrapperT);
		int count = 0;
		for (AtvTrain entityT : atvTrainList) {
			QueryWrapper<AtvEquipment> wrapperE = Wrappers.wrapper(AtvEquipment.class)
					.select("equipmentType")
					.eq("trainId", entityT.getId())
					.eq("sn", sn);
			AtvEquipment entityE = daoService.findOne(wrapperE);
			if (IsKit.isNull(entityE)) {
				continue;
			}

			Long timestamp = System.currentTimeMillis();
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("cmd_code", AtvConst.CMD_CODE_NUM13);
			jsonObject.put("timestamp", timestamp);
			JSONObject json = new JSONObject();
			json.put("method", AtvConst.METHOD_NUM0);
			json.put("devicetype", entityE.getEquipmentType());
			json.put("fileUrl", fileUrl);
			json.put("md5Sum", md5Sum);
			jsonObject.put("data", json);
			if (atvWebSocket.sendEquipmentMessage(_getUniqueId(pageMap), jsonObject.toString())) {
				count++;
			}
		}
		if (count == 0) {
			return Result.ok("部分升级成功!");
		} else if (count == atvTrainList.size()) {
			return Result.okMsg("升级成功!");
		} else {
			return Result.okMsg("升级失败，车辆离线!");
		}
	}
	//页面状态tate.updateForm.status为：1
	@Override
	public Boolean upgradeOne(Map<String,Object> pageMap) 
	{
		String sn = TypeKit.objToStr(pageMap.get("sn"));
		String fileName = TypeKit.objToStr(pageMap.get("fileNameList"));
		String filePrefix = TypeKit.objToStr(pageMap.get("filePrefix"));
		String dirName = TypeKit.objToStr(pageMap.get("dirName"));
		String uploadPath = fileService.getFileFullPath(dirName);

		if(IsKit.isNullOrEmpty(fileName )){
			return false;
		}
		/*CharsetKit.SYMBOL_HIFEN文件前缀与文件名之间的分隔符**/
		String filePath = uploadPath;
		String fileUrl = httpService.getUrl() + CharsetKit.SYMBOL_BACK_SLASH
				+ dirName + CharsetKit.SYMBOL_BACK_SLASH;

		if(IsKit.isNullOrEmpty(filePrefix)){
			filePath =filePath + fileName;
			fileUrl = fileUrl + fileName;
		}
		else{
			filePath = filePath + filePrefix +CharsetKit.SYMBOL_HIFEN + fileName;
			fileUrl = fileUrl + filePrefix + CharsetKit.SYMBOL_HIFEN + fileName;;
		}

		String md5Sum;
		try {
			md5Sum = DigestUtils.md5Hex(new FileInputStream(filePath));
		} catch (Exception e) {
			LogKit.info(e);
			return false;
		}
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code", AtvConst.CMD_CODE_NUM13);
		jsonObject.put("timestamp", timestamp);
		JSONObject json = new JSONObject();
		json.put("method", AtvConst.METHOD_NUM1);
		json.put("deviceNo", sn);
		json.put("fileUrl",fileUrl);
		json.put("md5Sum", md5Sum);
		jsonObject.put("data", json);

		return atvWebSocket.sendEquipmentMessage(_getUniqueId(pageMap), jsonObject.toString());
	} 

	@Override
	public Boolean rebootAll(Map<String,Object> whereMap)
	{
		QueryWrapper<AtvEquipment> wrapper = Wrappers.wrapper(AtvEquipment.class)
				.select("equipment_type");
		Set<Map.Entry<String,Object>> entryseSet = whereMap.entrySet();
		for (Map.Entry<String, Object> entry: entryseSet) {
			wrapper.eq(entry.getKey(), entry.getValue());   
		}		
		AtvEquipment entityE = daoService.findOne(wrapper);
		if(IsKit.isNull(entityE)) {
			return false;
		}
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code", AtvConst.CMD_CODE_NUM8);
		jsonObject.put("timestamp", timestamp);
		JSONObject json = new JSONObject();
		json.put("method",AtvConst.METHOD_NUM0);
		json.put("devicetype", _equipmentType(entityE.getEquipmentType()));
		jsonObject.put("data", json);

		return atvWebSocket.sendEquipmentMessage(_getUniqueId(whereMap), jsonObject.toString());		
	}
	@Override
	public Boolean rebootOne(Map<String,Object> whereMap)
	{
		Long timestamp = System.currentTimeMillis();
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("cmd_code", AtvConst.CMD_CODE_NUM8);
		jsonObject.put("timestamp", timestamp);
		JSONObject json = new JSONObject();
		json.put("method",AtvConst.METHOD_NUM1);
		json.put("deviceNo", whereMap.get("sn"));
		jsonObject.put("data", json);

		return atvWebSocket.sendEquipmentMessage(_getUniqueId(whereMap), jsonObject.toString());
	}
	private String _getUniqueId(Map<String,Object> whereMap) 
	{
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("trainId",whereMap.get("trainId"));
		return _buildUniqueId(paramMap); 
	}
	private String _getUniqueId(String trainid) 
	{
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("trainId",trainid);
		return _buildUniqueId(paramMap); 
	}
	private String _buildUniqueId(Map<String,Object> paramMap) 
	{
		Map<String,Object> resultMap = daoService.getMapBySql("atv_getCounrtyAreaLineCodeByTrainId",paramMap);
		StringBuilder sb = new StringBuilder()
				.append(resultMap.get("countryCode")).append(AtvConst.CMD_SEP)
				.append(resultMap.get("areaCode")).append(AtvConst.CMD_SEP)
				.append(resultMap.get("lineSn")).append(AtvConst.CMD_SEP)
				.append(resultMap.get("trainSn"));
		return sb.toString();
	}
	/**获取设备类型 AtvConst所定义的值*/
	private String _equipmentType(int equipmentType) {
		return switch (equipmentType) {
			case 1 -> "0x02";
			case 2 -> "0x04";
			case 3 -> "0x03";
			case 4 -> "0x05";
			case 8 -> "0x08";
			case 9 -> "0x07";
			case 10 -> "0x09";
			case 11 -> "0x10";
			case 12 -> "0x11";
			default -> "0";
		};
	}
}
