package com.yeejoin.precontrol.common.service.hk.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.precontrol.common.component.InitContext;
import com.yeejoin.precontrol.common.entity.hk.model.dto.HKRequestDto;
import com.yeejoin.precontrol.common.enums.media.MediaHkApiConfigKey;
import com.yeejoin.precontrol.common.enums.media.StreamType;
import com.yeejoin.precontrol.common.enums.media.StreamingProtocol;
import com.yeejoin.precontrol.common.enums.media.TransportLayerProtocol;
import com.yeejoin.precontrol.common.service.hk.HkPlatFormService;
import com.yeejoin.precontrol.common.utils.hk.HKSDKUtil;
import com.yeejoin.precontrol.common.utils.hk.ReturnUnifiedData;
import com.yeejoin.precontrol.common.vo.hik.HKResult;
import com.yeejoin.precontrol.common.vo.hik.Online;
import com.yeejoin.precontrol.common.vo.hik.Regions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: songLei
 * @Description: 海康平台业务接口实现类
 * @Date: 2021/4/29 11:48
 * @Version: 1.0
 */
@Service
@Slf4j
public class HkPlatFormServiceImpl implements HkPlatFormService {
	/**
	 * 文件服务器地址
	 */
	@Value("${hk.server}")
	String HKServer;

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 获取监控点预览取流URL
	 * 说明：
	 * 1.平台正常运行；平台已经添加过设备和监控点信息。
	 * 2.平台需要安装mgc取流服务。
	 * 3.三方平台通过openAPI获取到监控点数据，依据自身业务开发监控点导航界面。
	 * 4.调用本接口获取预览取流URL，协议类型包括：rtsp、rtmp、hls。
	 * 5.通过开放平台的开发包进行实时预览或者可以播放标准的RTST, RTMP, HLS流的播放器进行实时预览。
	 * 6.为保证数据的安全性，取流URL设有有效时间，有效时间为5分钟。
	 * @Date 2021/4/29 11:58
	 */
	@Override
	public Object getMonitoringPointPreviewURL(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		// 监控点唯一标识，可通过分页获取监控点资源获取
		jsonBody.put("cameraIndexCode", dto.getCameraIndexCode());
		// 码流类型：0:主码流 1:子码流 2:第三码流 参数不填，默认为主码流
		jsonBody.put("streamType", StreamType.MAIN_CODE.getType());
		// 取流协议（应用层协议）：“rtsp”:RTSP协议,“rtmp”:RTMP协议（只支持H264视频编码和AAC音频编码）“hls”:HLS协议
		// （HLS协议只支持海康SDK协议、EHOME协议、GB28181协议、ONVIF协议接入的设备；只支持H264视频编码和AAC音频编码）
		// 参数不填，默认为RTSP协议
		jsonBody.put("protocol", StreamingProtocol.HLS.getType());
		// 传输协议（传输层协议）：0:UDP 1:TCP 默认是TCP 注：GB28181 2011及以前版本只支持UDP传输
		jsonBody.put("transmode", TransportLayerProtocol.TCP.getType());
		// 标识扩展内容，格式：key=value，
		// 多个扩展时，以“&”隔开；
		// 调用方根据其播放控件支持的解码格式选择相应的封装类型；支持的内容详见附录F expand扩展内容说明
		jsonBody.put("expand", "transcode=0");
		jsonBody.put("streamform", "ps");
		String body = jsonBody.toJSONString();
		Object parse1 = JSON.parse(body);
		String s = parse1.toString();
		String result = HKSDKUtil.doPost(s,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.MONITORING_POINT_PREVIEW_URL.getKey()));
		JSONObject json = JSON.parseObject(ReturnUnifiedData.returnData(result).toString());
		String url = json.getString("url");
		if (url.contains("http://vms.jepcc.com:83")) {
			url = url.replace("http://vms.jepcc.com:83", HKServer);
		} else if (url.contains("http://119.3.82.88:83")) {
			url = url.replace("http://119.3.82.88:83", HKServer);
		}
		Map<String, String> urlPath = new HashMap<String, String>(2);
		urlPath.put("url", url);
		return urlPath;
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 分页获取监控点资源 获取监控点列表接口可用来全量同步监控点信息，返回结果分页展示。
	 * @Date 2021年4月30日10:06:42
	 */
	@Override
	public Object getMonitoringPointPage(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("pageNo", dto.getPageNo());
		jsonBody.put("pageSize", dto.getPageSize());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.PAGE_MONITORING_POINT_RESOURCES.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 根据区域编号获取下级监控点列表 根据指定的区域编号获取该区域下的监控点列表信息，返回结果分页展示。
	 *              注：返回的监控点不包括下级区域的。
	 * @Date 2021年4月30日10:20:11
	 */
	@Override
	public Object getMonitoringPointChildren(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("pageNo", dto.getPageNo());
		jsonBody.put("pageSize", dto.getPageSize());
		jsonBody.put("regionIndexCode", dto.getRegionIndexCode());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.MONITORING_POINT_CHILDREN.getKey()));
		JSONObject json = JSON.parseObject(ReturnUnifiedData.returnData(result).toString());
		JSONArray jsonArray = json.getJSONArray("list");
		List<HKResult> hkResults = jsonArray.toJavaList(HKResult.class);
		HKRequestDto newDto = new HKRequestDto();
		newDto.setPageNo(1);
		newDto.setPageSize(1000);
		newDto.setRegionIndexCode(dto.getRegionIndexCode());
		List<Online> onlines = this.getIsOnline(dto);
		if(CollectionUtils.isNotEmpty(hkResults)){
			hkResults.stream().forEach(item ->{
				item.setOnline(onlines.stream().filter(x -> x.getIndexCode().equals(item.getCameraIndexCode())).findFirst().get().getOnline());
			});
		}
		return hkResults;
	}

	/**
	 * @Method
	 * @Author songLei
	 * @Version 1.0
	 * @Description 根据编号获取监控点详细信息 获取单个监控点信息是指根据监控点唯一标识来获取指定的监控点信息。
	 * @Date 2021/4/30 10:47
	 */
	@Override
	public Object getMonitoringPointDetails(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("cameraIndexCode", dto.getCameraIndexCode());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.MONITORING_POINT_DETAILS.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 获取监控点回放取流URL 1.平台正常运行；平台已经添加过设备和监控点信息。 2.平台需要安装mgc取流服务。
	 *              3.三方通过openAPI获取到监控点数据，依据自身业务开发监控点导航界面。
	 *              4.调用本接口获取回放取流URL，协议类型包括：rtsp、rtmp、hls（只支持云存储）。
	 *              5.通过开放平台的开发包进行录像回放或者使用可以播放标准的RTST, RTMP,
	 *              HLS流的播放器进行录像回放。（开发包使用说明参考开发包的使用说明文档）
	 * @Date 2021/4/30 16:59
	 */
	@Override
	public Object getMonitoringPointPlayBack(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("cameraIndexCode", dto.getCameraIndexCode());
		jsonBody.put("recordLocation", 0);
		jsonBody.put("protocol", StreamingProtocol.HLS.getType());
		jsonBody.put("transmode", TransportLayerProtocol.TCP.getType());
		jsonBody.put("beginTime", dto.getBeginTime());
		jsonBody.put("endTime", dto.getEndTime());
		jsonBody.put("uuid", dto.getCameraIndexCode());
		jsonBody.put("expand", "streamform=ps");
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.MONITORING_POINT_PLAYBACK_URL.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 批量添加区域 支持区域的批量添加。 三方可以自行指定区域的唯一标识，也可以由ISC平台自行生成。
	 * @param dto
	 * @Date 2021/5/7 16:04
	 */
	public Object batchAddRegion(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("clientId", dto.getClientId());
		jsonBody.put("regionIndexCode", dto.getRegionIndexCode());
		jsonBody.put("parentIndexCode", dto.getParentIndexCode());
		jsonBody.put("regionName", dto.getRegionName());
		jsonBody.put("regionCode", dto.getRegionCode());
		jsonBody.put("regionType", dto.getRegionType());
		jsonBody.put("description", dto.getDescription());
		JSONArray jsonArray = new JSONArray();
		jsonArray.add(jsonArray);
		String body = jsonArray.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.BATCH_ADD_REGION.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 该接口用于设置监控点的预置点信息， 若参数传已经存在的预置点编号，则可修改预置点信息
	 * @param dto
	 * @Date 2021/5/7 16:04
	 */
	public Object setAddition(HKRequestDto dto) {
		/** 组装请求参数 */
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("cameraIndexCode", dto.getClientId());
		jsonBody.put("presetName", dto.getRegionIndexCode());
		jsonBody.put("presetIndex", dto.getParentIndexCode());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.SET_ADDITION.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 获取根区域信息
	 * @Date 2021年9月15日17:26:13
	 */
	@Override
	public Object getRootZone() {
		JSONObject jsonBody = new JSONObject();
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body,
				InitContext.memoryDataMap.get(MediaHkApiConfigKey.GET_ROOT_ZONE.getKey()));
		return ReturnUnifiedData.returnData(result);
	}

	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 分页获取区域列表
	 * @Date 2021年9月15日17:26:13
	 */
	@Override
	public Object getRegions(HKRequestDto dto) {
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("pageNo", dto.getPageNo());
		jsonBody.put("pageSize", dto.getPageSize());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body, InitContext.memoryDataMap.get(MediaHkApiConfigKey.GET_REGIONS.getKey()));
		JSONObject json = JSON.parseObject(ReturnUnifiedData.returnData(result).toString());
		JSONArray jsonArray = json.getJSONArray("list");
		List<Regions> regions = jsonArray.toJavaList(Regions.class);
		regions.removeIf(item -> item.getParentIndexCode().equals("-1"));
		return regions;
	}
	/**
	 * @Author songLei
	 * @Version 1.0
	 * @Description 获取视频在线状态
	 * @Date 2021年9月15日17:26:13
	 */
	@Override
	public List<Online> getIsOnline(HKRequestDto dto){
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("pageNo", dto.getPageNo());
		jsonBody.put("pageSize", dto.getPageSize());
		jsonBody.put("indexCodes", dto.getIndexCodes());
		String body = jsonBody.toJSONString();
		String result = HKSDKUtil.doPost(body, InitContext.memoryDataMap.get(MediaHkApiConfigKey.IS_ONLINE.getKey()));
		JSONObject json = JSON.parseObject(ReturnUnifiedData.returnData(result).toString());
		JSONArray jsonArray = json.getJSONArray("list");
		List<Online> onlines = jsonArray.toJavaList(Online.class);
		return onlines;
	}
}
