package org.springblade.third.videodevice.wvp.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.JsonUtils;
import org.springblade.community.entity.Agency;
import org.springblade.community.feign.IAgencyClient;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.mp.support.BladePage;
import org.springblade.core.tool.api.R;
import org.springblade.device.entity.Gb28181Device;
import org.springblade.device.entity.GbDeviceChannel;
import org.springblade.device.feign.IGbDeviceChannelClient;
import org.springblade.device.feign.IGbDeviceClient;
import org.springblade.third.videodevice.beans.MediaServerConfig;
import org.springblade.third.videodevice.gb28181.conf.WvpConfig;
import org.springblade.third.videodevice.gb28181.entity.GbChannel;
import org.springblade.third.videodevice.gb28181.entity.GbDevice;
import org.springblade.third.videodevice.gb28181.entity.GbRecordInfo;
import org.springblade.third.videodevice.wvp.service.WvpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @author zwx
 * @create 2021/6/28 13:52
 */
@RestController
@RequestMapping("/wvp/device")
@Slf4j
public class WvpDeviceController {

	@Autowired
	private WvpConfig wvpConfig;
	@Autowired
	private MediaServerConfig zlmConfig;
	@Autowired
	private WvpService wvpService;
	@Autowired
	private IGbDeviceClient gbDeviceClient;
	@Autowired
	private IGbDeviceChannelClient gbDeviceChannelClient;
	@Autowired
	private IAgencyClient agencyClient;

	@ApiOperation("设备绑定")
	@ApiOperationSupport(order = 11)
	@PostMapping("/bind")
	public R bind(@RequestParam(value = "deviceId", required = true) String deviceId,
											@RequestParam(value = "agencyId", required = true) Long agencyId,
											@RequestParam(value = "residentialId", required = false) Long residentialId){
		R<GbDevice> deviceR = this.wvpService.getByDeviceId(deviceId);
		GbDevice device = deviceR.getData();
		if(device == null){
			return R.fail("设备不存在");
		}else{
			Gb28181Device gb28181Device = org.springblade.core.tool.utils.BeanUtil.copy(deviceR.getData(), Gb28181Device.class);
			gb28181Device.setAgencyId(agencyId);
			gb28181Device.setResidentialId(residentialId);
			R bind = gbDeviceClient.bind(gb28181Device);
			if(bind.isSuccess()){
				Agency agency = agencyClient.getById(agencyId);
				List<GbDeviceChannel> deviceChannelList = new ArrayList<>();
				R<List<GbChannel>> channelsR = this.wvpService.getChannelByDeviceId(deviceId);
				for(GbChannel channel : channelsR.getData()){
					GbDeviceChannel deviceChannel = org.springblade.core.tool.utils.BeanUtil.copy(channel, GbDeviceChannel.class);
					deviceChannel.setPtzType(channel.getPTZType());
					deviceChannel.setTenantId(agency.getTenantId());
					deviceChannel.setAgencyId(agencyId);
					deviceChannelList.add(deviceChannel);
				}
				if(deviceChannelList.size() > 0){
					return gbDeviceChannelClient.submitBatch(deviceChannelList);
				}else{
					return R.status(true);
				}
			}else{
				return R.fail(bind.getMsg());
			}
		}
	}

	@ApiOperation(value = "分页获取国标设备列表", notes = "传入count, page")
	@ApiOperationSupport(order = 1)
	@GetMapping(value = "/query/devices")
	public R<BladePage<GbDevice>> devicePage(@RequestParam(value = "size", required = true) int size, @RequestParam(value = "current", required = true) int current){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("count", size);
		paramMap.put("page", current);
		HttpRequest request = new HttpRequest(wvpUrl + "/api/device/query/devices");
		HttpResponse response = request.form(paramMap).execute();
		int status = response.getStatus();
		log.info("【wvp-gb28181】getDevices", "【requestParam】：" + paramMap + "【response】：" + response.body());
		if(status == 200){
			JSONObject data = JSONObject.parseObject(response.body());
			String json = JsonUtils.objectToJson(data.get("list"));
			List<GbDevice> deviceList = JSONArray.parseArray(json, GbDevice.class);
			if(deviceList != null && deviceList.size() > 0){
				BladePage<GbDevice> devicePage = new BladePage<>();
				devicePage.setRecords(deviceList);
				devicePage.setCurrent((Integer) data.get("pageNum"));
				devicePage.setSize((Integer) data.get("size"));
				devicePage.setTotal((Integer) data.get("total"));
				return R.data(devicePage);
			}else{
				return R.data(new BladePage<>());
			}
		}else{
			return R.fail(null, "分页查询设备失败");
		}
	}

	/**
	 * 分页查询通道数
	 *
	 * @param deviceId 设备id，设备编号
	 * @param current 当前页
	 * @param size 每页条数
	 * @param query 查询内容
	 * @param online 是否在线  在线 true / 离线 false
	 * @param channelType 设备 false/子目录 true
	 * @return 通道列表
	 */
	@ApiOperation(value = "分页查询通道")
	@ApiOperationSupport(order = 2)
	@GetMapping(value = "/query/{deviceId}/channels")
	public R<BladePage<GbChannel>> deviceChannelPage(@PathVariable(value = "deviceId", required = true) String deviceId,
										int current, int size,
										@RequestParam(required = false) String query,
										@RequestParam(required = false	) Boolean online,
										@RequestParam(required = false) Boolean channelType){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("deviceId", deviceId);
		paramMap.put("count", size);
		paramMap.put("page", current);
		paramMap.put("query", query);
		paramMap.put("online", online);
		paramMap.put("channelType", channelType);
		String reqUrl = String.format("/api/device/query/devices/%s/channels", deviceId);
		HttpRequest request = new HttpRequest(wvpUrl + reqUrl);
		HttpResponse response = request.form(paramMap).execute();
		log.info("【wvp】getDeviceChannels", "【requestParam】：" + reqUrl + JSONObject.toJSONString(paramMap) + ",【response】：" + response.body());
		int status = response.getStatus();
		if(status == 200){
			JSONObject data = JSONObject.parseObject(response.body());
			String json = JsonUtils.objectToJson(data.get("list"));
			List<GbChannel> channelList = JSONArray.parseArray(json, GbChannel.class);
			if(channelList != null && channelList.size() > 0){
				BladePage<GbChannel> channelPage = new BladePage<>();
				channelPage.setRecords(channelList);
				channelPage.setCurrent((Integer) data.get("pageNum"));
				channelPage.setSize((Integer) data.get("size"));
				channelPage.setTotal((Integer) data.get("total"));
				return R.data(channelPage);
			}else{
				return R.data(new BladePage<>());
			}
		}else{
			return R.fail(null, "分页查询设备通道失败");
		}
	}

	@ApiOperation("同步设备通道")
	@ApiOperationSupport(order = 3)
	@PostMapping("/devices/{deviceId}/sync")
	public R<GbDevice> deviceSync(@PathVariable String deviceId){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		String reqUrl = String.format("/api/device/query/devices/%s/sync", deviceId);
		HttpResponse response = HttpRequest.post(wvpUrl + reqUrl).execute();
		log.info("【wvp】deviceSync", "【requestParam】：" + null + "【response】：" + response.body());
		int status = response.getStatus();
		if(status == 200){
			GbDevice gbDevice = JSONObject.parseObject(response.body(), GbDevice.class);
			if(gbDevice != null){
				return R.data(gbDevice);
			}else{
				return R.data(null);
			}
		}else{
			return R.fail(null, "设备通道同步失败");
		}
	}

	@ApiOperation("修改数据流传输模式")
	@ApiOperationSupport(order = 4)
	@PostMapping("/transport/{deviceId}/{streamMode}")
	public R<Boolean> updateDeviceTransport(@PathVariable String deviceId, @PathVariable String streamMode){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		HttpResponse response = HttpRequest.post(wvpUrl + String.format("/api/device/query/transport/%s/%s", deviceId, streamMode)).execute();
		log.info("【wvp】updateDeviceTransport", "【requestParam】：" + null + "【response】：" + response.body());
		int status = response.getStatus();
		if(status == 200){
			return R.success("修改数据流传输模式成功");
		}else{
			return R.fail("修改数据流传输模式失败");
		}
	}

	@ApiOperation("更新通道信息")
	@ApiOperationSupport(order = 5)
	@PostMapping("/channel/update/{deviceId}")
	public R<Boolean> updateDeviceChannel(@PathVariable String deviceId, GbChannel gbChannel){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		Map<String, Object> paramMap = BeanUtil.beanToMap(gbChannel);
		HttpResponse response = HttpRequest.post(wvpUrl + String.format("/api/device/query/channel/update/%s", deviceId)).form(paramMap).execute();
		log.info("【wvp】updateDeviceChannel", "【requestParam】：" + paramMap + "【response】：" + response.body());
		int status = response.getStatus();
		if(status == 200){
			return R.success("更新通道信息成功");
		}else{
			return R.fail("更新通道信息失败");
		}
	}

	@ApiOperation("设备开始点播")
	@ApiOperationSupport(order = 6)
	@GetMapping("/play/start/{deviceId}/{channelId}")
	public R<JSONObject> deviceStartPlay(@PathVariable(value = "deviceId", required = true) String deviceId, @PathVariable(value = "channelId", required = true) String channelId){
		return this.wvpService.play(deviceId, channelId);
	}

	@ApiOperation("设备停止点播")
	@ApiOperationSupport(order = 7)
	@GetMapping("/play/stop/{deviceId}/{channelId}")
	public R<String> deviceStopPlay(@PathVariable(value = "deviceId", required = true) String deviceId, @PathVariable(value = "channelId", required = true) String channelId){
		return this.wvpService.stop(deviceId, channelId);
	}

	@ApiOperation("设备录像查询")
	@ApiOperationSupport(order = 8)
	@GetMapping("/query/record/{deviceId}/{channelId}")
	public R<GbRecordInfo> deviceRecord(@PathVariable(value = "deviceId", required = true) String deviceId,
										@PathVariable(value = "channelId", required = true) String channelId,
										String startTime, String endTime){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("startTime", startTime);
		paramMap.put("endTime", endTime);
		String reqUrl = String.format("/api/gb_record/query/%s/%s", deviceId, channelId);
		HttpResponse response = HttpRequest.get(wvpUrl + reqUrl).form(paramMap).execute();
		log.info("【wvp】deviceRecord", "【requestParam】：" + reqUrl + JSONObject.toJSONString(paramMap)+ "【response】：" + response.body());
		int status = response.getStatus();
		if(status == 200){
			GbRecordInfo gbRecordInfo = JSONObject.parseObject(response.body(), GbRecordInfo.class);
			return R.data(gbRecordInfo);
		}else{
			return R.fail("设备录像查询失败");
		}
	}

	@ApiOperation("查询设备视频流信息")
	@ApiOperationSupport(order = 9)
	@GetMapping("/query/mediaInfo")
	public R<Map<String, Object>> mediaInfo(@RequestParam(value = "mediaServerId", required = false, defaultValue = "mediaServerId") String mediaServerId,
		                                    @RequestParam(value = "streamId", required = false) String streamId,
											@RequestParam(value = "vhost", required = false, defaultValue = "__defaultVhost__")String vhost,
											@RequestParam(value = "app", required = false, defaultValue = "rtp") String app,
											@RequestParam(value = "schema", required = false, defaultValue = "rtmp") String schema){
		String requestUrl = String.format("/index/api/getMediaInfo?secret=%s&vhost=%s&schema=%s&app=%s&stream=%s", zlmConfig.getSecret(), vhost, schema, app, streamId);
		String mediaInfoUrl = zlmConfig.getServerHost() + requestUrl;
		HttpResponse response = HttpRequest.get(mediaInfoUrl).execute();
		log.info("【wvp】deviceRecord", "【requestParam】：" + requestUrl + "【response】：" + response.body());
		int status = response.getStatus();
		Map<String, Object> resultMap = JSONObject.parseObject(response.body(), Map.class);
		if(status == 200){
			return R.data(resultMap);
		}else{
			return R.fail((String) resultMap.get("msg"));
		}
	}


	@ApiOperation("删除设备")
	@ApiOperationSupport(order = 10)
	@GetMapping("/query/{deviceId}/delete")
	public R<String> delete(@PathVariable(value = "deviceId") String deviceId){
		String wvpUrl = wvpConfig.getServerHost() + ":" + wvpConfig.getServerPort();
		String reqUrl = String.format("/api/device/query/devices/%s/delete", deviceId);
		HttpResponse response = HttpRequest.delete(wvpUrl + reqUrl).execute();
		log.info("【wvp】deleteDevice", "【requestParam】：" + reqUrl + "【response】：" + response.body());
		String data = response.body();
		int status = response.getStatus();
		if(status == 200){
			return R.success("设备删除成功");
		}else{
			return R.fail("设备删除失败");
		}
	}

}
