/**
 * 设备控制命令API接口
 *
 * @author lawrencehj
 * @date 2021年2月1日
 */

package com.genersoft.iot.vmp.gb28181.controller;

import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;

@Tag(name  = "国标设备控制")
@Slf4j
@RestController
@RequestMapping("/api/device/control")
public class DeviceControl {

    @Autowired
    private IDeviceService deviceService;


	@Operation(summary = "远程启动", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
    @GetMapping("/teleboot/{deviceId}")
    public void teleBootApi(@PathVariable String deviceId) {
        if (log.isDebugEnabled()) {
            log.debug("设备远程启动API调用");
        }
        Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		deviceService.teleboot(device);
    }


	@Operation(summary = "录像控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号", required = true)
	@Parameter(name = "recordCmdStr", description = "命令， 可选值：Record（手动录像），StopRecord（停止手动录像）", required = true)
    @GetMapping("/record")
    public DeferredResult<WVPResult<String>> recordApi(String deviceId, String recordCmdStr, String channelId) {
        if (log.isDebugEnabled()) {
            log.debug("开始/停止录像API调用");
        }
        Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> deferredResult = new DeferredResult<>();

		deviceService.record(device, channelId, recordCmdStr, (code, msg, data) -> {
			deferredResult.setResult(new WVPResult<>(code, msg, data));
		});
		deferredResult.onTimeout(() -> {
			log.warn("[开始/停止录像] 操作超时, 设备未返回应答指令, {}", deviceId);
			deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return deferredResult;
	}

	@Operation(summary = "布防/撤防", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "guardCmd", description = "命令， 可选值：SetGuard（布防），ResetGuard（撤防）", required = true)
	@GetMapping("/guard")
	public DeferredResult<WVPResult<String>> guardApi(String deviceId, String guardCmd) {
		if (log.isDebugEnabled()) {
			log.debug("布防/撤防API调用");
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> result = new DeferredResult<>();
		deviceService.guard(device, guardCmd, (code, msg, data) -> {
			result.setResult(new WVPResult<>(code, msg, data));
		});
		result.onTimeout(() -> {
			log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId);
			result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return result;
	}

	@Operation(summary = "报警复位", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号", required = true)
	@Parameter(name = "alarmMethod", description = "报警方式, 报警方式条件(可选),取值0为全部,1为电话报警,2为设备报警,3为短信报警,4为\n" +
			"GPS报警,5为视频报警,6为设备故障报警,7其他报警;可以为直接组合如12为电话报警或设备报警")
	@Parameter(name = "alarmType", description = "报警类型, " +
			"报警类型。" +
			"报警方式为2时,不携带 AlarmType为默认的报警设备报警," +
			"携带 AlarmType取值及对应报警类型如下:" +
			"1-视频丢失报警;2-设备防拆报警;3-存储设备磁盘满报警;4-设备高温报警;5-设备低温报警。" +
			"报警方式为5时,取值如下:" +
			"1-人工视频报警;2-运动目标检测报警;3-遗留物检测报警;4-物体移除检测报警;5-绊线检测报警;" +
			"6-入侵检测报警;7-逆行检测报警;8-徘徊检测报警;9-流量统计报警;10-密度检测报警;" +
			"11-视频异常检测报警;12-快速移动报警。" +
			"报警方式为6时,取值如下:" +
			"1-存储设备磁盘故障报警;2-存储设备风扇故障报警")
	@GetMapping("/reset_alarm")
	public DeferredResult<WVPResult<String>> resetAlarm(String deviceId, String channelId,
																@RequestParam(required = false) String alarmMethod,
																@RequestParam(required = false) String alarmType) {
		if (log.isDebugEnabled()) {
			log.debug("报警复位API调用");
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> result = new DeferredResult<>();
		deviceService.resetAlarm(device, channelId, alarmMethod, alarmType, (code, msg, data) -> {
			result.setResult(new WVPResult<>(code, msg, data));
		});
		result.onTimeout(() -> {
			log.warn("[布防/撤防] 操作超时, 设备未返回应答指令, {}", deviceId);
			result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return result;
	}

	@Operation(summary = "强制关键帧", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号")
	@GetMapping("/i_frame")
	public void iFrame(String deviceId, @RequestParam(required = false) String channelId) {
		if (log.isDebugEnabled()) {
			log.debug("强制关键帧API调用");
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		deviceService.iFrame(device, channelId);
	}

	@Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号", required = true)
	@Parameter(name = "enabled", description = "是否开启看守位", required = true)
	@Parameter(name = "presetIndex", description = "调用预置位编号")
	@Parameter(name = "resetTime", description = "自动归位时间间隔 单位：秒")
	@GetMapping("/home_position")
	public DeferredResult<WVPResult<String>> homePositionApi(String deviceId, String channelId, Boolean enabled,
												  @RequestParam(required = false) Integer resetTime,
												  @RequestParam(required = false) Integer presetIndex) {
        if (log.isDebugEnabled()) {
			log.debug("看守位控制API调用");
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> result = new DeferredResult<>();
		deviceService.homePosition(device, channelId, enabled, resetTime, presetIndex, (code, msg, data) -> {
			result.setResult(new WVPResult<>(code, msg, data));
		});
		result.onTimeout(() -> {
			log.warn("[看守位控制] 操作超时, 设备未返回应答指令, {}", deviceId);
			result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return result;
	}

	@Operation(summary = "拉框放大", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号", required = true)
	@Parameter(name = "length", description = "播放窗口长度像素值", required = true)
	@Parameter(name = "width", description = "播放窗口宽度像素值", required = true)
	@Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true)
	@Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true)
	@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
	@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
	@GetMapping("drag_zoom/zoom_in")
	public DeferredResult<WVPResult<String>> dragZoomIn(@RequestParam String deviceId, String channelId,
											 @RequestParam int length,
											 @RequestParam int width,
											 @RequestParam int midpointx,
											 @RequestParam int midpointy,
											 @RequestParam int lengthx,
											 @RequestParam int lengthy) {
		if (log.isDebugEnabled()) {
			log.debug(String.format("设备拉框放大 API调用，deviceId：%s ，channelId：%s ，length：%d ，width：%d ，midpointx：%d ，midpointy：%d ，lengthx：%d ，lengthy：%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> result = new DeferredResult<>();
		deviceService.dragZoomIn(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> {
			result.setResult(new WVPResult<>(code, msg, data));
		});
		result.onTimeout(() -> {
			log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId);
			result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return result;
	}

	@Operation(summary = "拉框缩小", security = @SecurityRequirement(name = JwtUtils.HEADER))
	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
	@Parameter(name = "channelId", description = "通道国标编号")
	@Parameter(name = "length", description = "播放窗口长度像素值", required = true)
	@Parameter(name = "width", description = "拉框中心的横轴坐标像素值", required = true)
	@Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true)
	@Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true)
	@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
	@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
	@GetMapping("/drag_zoom/zoom_out")
	public DeferredResult<WVPResult<String>> dragZoomOut(@RequestParam String deviceId,
											  @RequestParam(required = false) String channelId,
											  @RequestParam int length,
											  @RequestParam int width,
											  @RequestParam int midpointx,
											  @RequestParam int midpointy,
											  @RequestParam int lengthx,
											  @RequestParam int lengthy){

		if (log.isDebugEnabled()) {
			log.debug(String.format("设备拉框缩小 API调用，deviceId：%s ，channelId：%s ，length：%d ，width：%d ，midpointx：%d ，midpointy：%d ，lengthx：%d ，lengthy：%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
		}
		Device device = deviceService.getDeviceByDeviceId(deviceId);
		Assert.notNull(device, "设备不存在");
		DeferredResult<WVPResult<String>> result = new DeferredResult<>();
		deviceService.dragZoomOut(device, channelId, length, width, midpointx, midpointy, lengthx,lengthy, (code, msg, data) -> {
			result.setResult(new WVPResult<>(code, msg, data));
		});
		result.onTimeout(() -> {
			log.warn("[设备拉框放大] 操作超时, 设备未返回应答指令, {}", deviceId);
			result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "操作超时, 设备未应答"));
		});
		return result;
	}
}
