package com.zd.iot.vmp.vmanager.onvif;

import be.teletask.onvif.models.OnvifDevice;
import com.alibaba.fastjson.JSONObject;
import com.zd.common.core.constant.HttpStatus;
import com.zd.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.zd.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.zd.iot.vmp.media.zlm.dto.MediaServerItem;
import com.zd.iot.vmp.onvif.IONVIFServer;
import com.zd.iot.vmp.service.IMediaServerService;
import com.zd.iot.vmp.vmanager.bean.WVPResult;
import com.zd.iot.vmp.web.ApiStreamController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@SuppressWarnings(value = {"rawtypes", "unchecked"})
@Api(tags = "onvif设备")
@CrossOrigin
@RestController
@RequestMapping("/api/onvif")
public class ONVIFController {

    private final static Logger logger = LoggerFactory.getLogger(ONVIFController.class);

    @Autowired
    private IMediaServerService mediaServerService;

    @Autowired
    private DeferredResultHolder resultHolder;

    @Autowired
    private IONVIFServer onvifServer;


    @ApiOperation("搜索")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
    })
    @GetMapping(value = "/search")
    public DeferredResult<ResponseEntity<WVPResult>> search(@RequestParam(required = false) Integer timeout) {
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
        UUID uuid = UUID.randomUUID();
        result.onTimeout(() -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<String> wvpResult = new WVPResult();
            wvpResult.setCode(0);
            wvpResult.setMsg("搜索超时");
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        onvifServer.search(timeout, (errorCode, onvifDevices) -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<List<String>> resultData = new WVPResult();
            resultData.setCode(errorCode);
            if (errorCode == 0) {
                resultData.setMsg("success");
                resultData.setData(onvifDevices);
            } else {
                resultData.setMsg("fail");
            }
            msg.setData(resultData);
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
        });
        return result;
    }

    @ApiOperation("获取onvif的rtsp地址")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "hostname", value = "onvif地址", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataTypeClass = String.class),
    })
    @GetMapping(value = "/rtsp")
    public DeferredResult<ResponseEntity<WVPResult>> getRTSPUrl(@RequestParam(value = "timeout", required = false, defaultValue = "3000") Integer timeout,
                                                                @RequestParam(required = true) String hostname,
                                                                @RequestParam(required = false,defaultValue = "admin") String username,
                                                                @RequestParam(required = false,defaultValue = "a12345678") String password){
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10000L);
        UUID uuid = UUID.randomUUID();
        result.onTimeout(() -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<String> wvpResult = new WVPResult();
            wvpResult.setCode(0);
            wvpResult.setMsg("获取onvif的rtsp地址超时");
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password);
        onvifServer.getRTSPUrl(timeout, onvifDevice, (errorCode, url) -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<String> resultData = new WVPResult();
            resultData.setCode(errorCode);
            if (errorCode == 0) {
                resultData.setMsg("success");
                resultData.setData(url);
            } else {
                resultData.setMsg(url);
            }
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
        });
        return result;
    }

    @ApiOperation("onvif开始录像")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "hostname", value = "IP地址", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataTypeClass = String.class),
    })
    @GetMapping(value = "/startRecord")
    public DeferredResult <ResponseEntity<WVPResult>> startRecord(@RequestParam(value = "timeout", required = false, defaultValue = "3000") Integer timeout,
                                  @RequestParam(required = true) String hostname,
                                  @RequestParam(required = false,defaultValue = "admin") String username,
                                  @RequestParam(required = false,defaultValue = "a12345678") String password)  {
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10000L);
        UUID uuid = UUID.randomUUID();
        result.onTimeout(() -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<String> wvpResult = new WVPResult();
            wvpResult.setCode(0);
            wvpResult.setMsg("获取onvif的rtsp地址超时");
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password);
        onvifServer.getRTSPUrl(timeout, onvifDevice, (errorCode, url) -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            WVPResult<String> resultData = new WVPResult();
            resultData.setCode(errorCode);
            if (errorCode == 0) {
                MediaServerItem mediaServerItem = mediaServerService.getOne("your_server_id");
                Map<String,Object> map=new HashMap<>();
                map.put("type",1);
                map.put("vhost","__defaultVhost__");
                map.put("customized_path","/home/upload");
                map.put("max_second",360000);
                String name=hostname.replace(".","");
                String appName="app"+name;
                String streamName="stream"+name;
                map.put("app",appName);
                map.put("stream",streamName);
                map.put("rstpUrl",url);
                boolean isTrue=onvifServer.isRecording(mediaServerItem,map);
                if(isTrue){
                    resultData.setCode(-1);
                    resultData.setData("false");
                    resultData.setMsg("视频录制中无法重复录制！");
                }else{
                    JSONObject object=onvifServer.startRecord(mediaServerItem,map);
                    resultData.setCode(object.getInteger("code"));
                    resultData.setData(object.getString("result"));
                    resultData.setMsg(object.getString("msg"));
                }
            } else {
                resultData.setMsg(url);
            }
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
        });
        return result;
    }


    @ApiOperation("onvif结束录像")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "hostname", value = "onvif地址", required = true, dataTypeClass = String.class),
    })
    @GetMapping(value = "/stopRecord")
    public DeferredResult <ResponseEntity<WVPResult>> stopRecord(@RequestParam(value = "timeout", required = false, defaultValue = "3000") Integer timeout,
                                 @RequestParam(value = "hostname", required = true) String hostname){
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);;
        RequestMessage msg = new RequestMessage();
        UUID uuid = UUID.randomUUID();
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
        MediaServerItem mediaServerItem = mediaServerService.getOne("your_server_id");
        Map<String,Object> map=new HashMap<>();
        hostname=hostname.replace(".","");
        String appName="app"+hostname;
        String streamName="stream"+hostname;
        map.put("type",1);
        map.put("app",appName);
        map.put("stream",streamName);
        map.put("vhost","__defaultVhost__");
        boolean isTrue=onvifServer.isRecording(mediaServerItem,map);
        if(isTrue==false){
            WVPResult<String> resultData = new WVPResult();
            resultData.setCode(HttpStatus.ERROR);
            resultData.setMsg("未进行录制，无法停止录制！");
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
            return result;
        }
        String urlPath=onvifServer.stopRecord(mediaServerItem,map);
        urlPath=urlPath.replace("/.","/");
        logger.error("返回路径是否重复日志:"+urlPath);
        Map<String,Object> closeMap=new HashMap<>();
        closeMap.put("app",appName);
        closeMap.put("stream",streamName);
        boolean isCloseTrue=onvifServer.closeStream(mediaServerItem,closeMap);
        WVPResult<String> resultData = new WVPResult();
        if(StringUtils.isNotBlank(urlPath) && isCloseTrue){
            resultData.setCode(HttpStatus.SUCCESS);
            resultData.setData(urlPath);
            resultData.setMsg("success");
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
        }else{
            resultData.setCode(HttpStatus.ERROR);
            resultData.setMsg("录制视频路径返回错误！");
            msg.setData(resultData);
            resultHolder.invokeResult(msg);
            return result;
        }
        return result;
    }

}
