package com.sptg.video.cloud.biz.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.video.cloud.api.dto.VCDeviceDto;
import com.sptg.video.cloud.api.entity.VCDevice;
import com.sptg.video.cloud.api.entity.SysParams;
import com.sptg.video.cloud.api.entity.VCPusherConfig;
import com.sptg.video.cloud.api.feigns.VCDeviceFeign;
import com.sptg.video.cloud.api.utils.VideoCloudHttpUtil;
import com.sptg.video.cloud.biz.service.VCDeviceServiceInterface;
import com.sptg.video.cloud.biz.service.VCPusherConfigServiceInterface;
import com.sptg.video.cloud.biz.service.VCSysParamsServiceInterface;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * @author zwx
 * @create 2020/10/16 12:32
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class VCDeviceController implements VCDeviceFeign {

    private final VCDeviceServiceInterface vcDeviceServiceInterface;

    private final VCSysParamsServiceInterface sysParamsServiceInterface;

    private final VCPusherConfigServiceInterface vcPusherConfigServiceInterface;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    @PostMapping(value = "/vcDevice/pagingQuery")
    public ResultBean<Page<VCDevice>> pagingQuery(@RequestBody PageBean<VCDevice, VCDeviceDto> pageBean) {
        Page<VCDevice> devicePage = this.vcDeviceServiceInterface.pagingQuery(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS, devicePage);
    }

    @Override
    @GetMapping(value = "/vcDevice/findDeviceById/{id}")
    public VCDevice findDeviceById(@PathVariable(value = "id") Long id) {
        return this.vcDeviceServiceInterface.findDeviceById(id);
    }

    @Override
    @GetMapping(value = "/vcDevice/findDeviceByNum/{deviceNum}")
    public VCDevice findDeviceByNum(@PathVariable(value = "deviceNum") String deviceNum) {
        return this.vcDeviceServiceInterface.findDeviceByNum(deviceNum);
    }

    /**
     * 同步视频云的设备列表，支持单个设备同步和多个设备同步
     * @param deviceDto
     * @return
     */
    @Override
    @PostMapping(value = "/vcDevice/sync/list")
    public ResultBean<String> syncDeviceList(@RequestBody VCDeviceDto deviceDto) {
        SysParams sysParams = this.sysParamsServiceInterface.findSysParamsByAcountPwd(deviceDto.getAccountName(), null);
        return this.vcDeviceServiceInterface.syncDeviceList(sysParams, deviceDto);
    }

    /**
     * 获取设备视频地址
     * @param deviceDto
     * @return
     */
    @Override
    @PostMapping(value = "/vcDevice/getDevUrl")
    public ResultBean<String> deviceGetDevUrl(@RequestBody VCDeviceDto deviceDto) {
        SysParams sysParams = this.sysParamsServiceInterface.findSysParamsByAcountPwd(deviceDto.getAccountName(), null);
        String rtspUrl = this.vcDeviceServiceInterface.deviceGetDevUrl(sysParams, deviceDto);
        if(rtspUrl != null && StringUtils.hasText(rtspUrl)){
            Map<String, Object> map = new HashMap<>();
            map.put("deviceNum", deviceDto.getDeviceNum());
            map.put("rtspUrl", rtspUrl);
//            String httpFlvUrl = this.getHttpFlvUrl(map);
            return new ResultBean<>(ResultEnum.SUCCESS, rtspUrl);
        }
        return new ResultBean<>(ResultEnum.SUCCESS, null);
    }

    @Override
    @PostMapping(value = "/vcDevice/pusher")
    public ResultBean<String> devicePusher(@RequestBody VCDeviceDto vcDeviceDto) {
        log.error("videoCloud:id---" + vcDeviceDto.getDeviceNum());
        log.error("videoCloud:rtspUrl---" + vcDeviceDto.getRtspUrl());
        String rtspUrl = vcDeviceDto.getRtspUrl();
        String deviceNum = vcDeviceDto.getDeviceNum();
        Assert.hasText(deviceNum, "推流id不能为空");
        Assert.hasText(rtspUrl, "设备播放地址为空，无法推流");
        return this.vcDeviceServiceInterface.devicePusher(vcDeviceDto);
    }

    @Override
    @PostMapping(value = "/vcDevice/mediaServer/streamOnline")
    public ResultBean<String> mediaServerStreamOnline(@RequestBody VCDeviceDto vcDeviceDto) {
        VCPusherConfig vcPusherConfig = vcPusherConfigServiceInterface.findById(1L);
        String deviceNum = vcDeviceDto.getDeviceNum();
        Assert.hasText(deviceNum, "推流id不能为空");
        String getMediaInfoUrl = vcPusherConfig.getMediaServer() + "/index/api/getMediaInfo?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=";
        getMediaInfoUrl = getMediaInfoUrl + deviceNum;
        ResponseEntity<Map> response = this.restTemplate.getForEntity(getMediaInfoUrl, Map.class);
        Map body = response.getBody();
        boolean online = (boolean)body.get("online");
        VCDevice vcDevice = this.vcDeviceServiceInterface.findDeviceByNum(deviceNum);
        if(online){
            vcDevice.setPusherStatus(0);
            this.vcDeviceServiceInterface.updateById(vcDevice);
            return new ResultBean<>(ResultEnum.SUCCESS, "流存在");
        }else{
            vcDevice.setPusherStatus(1);
            this.vcDeviceServiceInterface.updateById(vcDevice);
            return new ResultBean<>(ResultEnum.SUCCESS, "流不存在");
        }
    }

    @Override
    @PostMapping(value = "/vcDevice/mediaServer/addFFmpegSource")
    public ResultBean<String> msAddFFmpegSource(@RequestBody VCDeviceDto vcDeviceDto) {
        VCPusherConfig vcPusherConfig = vcPusherConfigServiceInterface.findById(1L);
        String deviceNum = vcDeviceDto.getDeviceNum();
        String rtspUrl = vcDeviceDto.getRtspUrl();
        Assert.hasText(rtspUrl, "rtsp流地址不能为空");
        Assert.hasText(deviceNum, "推流id不能为空");
        String addFFmpegUrl = vcPusherConfig.getMediaServer() + "/index/api/addFFmpegSource?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&src_url=";
        addFFmpegUrl = addFFmpegUrl + rtspUrl + "&dst_url=" + vcPusherConfig.getDstUrl() + deviceNum + "&timeout_ms=300000&enable_hls=0&enable_mp4=0";
        ResponseEntity<Map> response = this.restTemplate.getForEntity(addFFmpegUrl, Map.class);
        Map body = response.getBody();
        int success = (int)body.get("code");
        if(success == 0){
            Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(body.get("data")), Map.class);
            String key = (String)dataMap.get("key");
            VCDevice vcDevice = this.vcDeviceServiceInterface.findDeviceByNum(vcDeviceDto.getDeviceNum());
            vcDevice.setKey(key);
            //flv：http://somedomain.com/live/0.flv
            String flvUrl = vcPusherConfig.getMediaServer() + "/live/" + deviceNum + ".flv";
            //m3u8：http://somedomain.com/live/0/hls.m3u8
            String m3u8Url = vcPusherConfig.getMediaServer() + "/live/" + deviceNum + "/hls.m3u8";
            //mp4：http://somedomain.com/live/0.live.mp4
            String mp4Url = vcPusherConfig.getMediaServer() + "/live/" + deviceNum + ".live.mp4";
            vcDevice.setFlvUrl(flvUrl);
            vcDevice.setMp4Url(mp4Url);
            vcDevice.setM3u8Url(m3u8Url);
            this.vcDeviceServiceInterface.updateById(vcDevice);
            return new ResultBean<>(ResultEnum.SUCCESS, "推流成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "推流失败");
        }
    }

    @Override
    @PostMapping(value = "/vcDevice/mediaServer/delFFmpegSource")
    public ResultBean<String> msDelFFmpegSource(@RequestBody VCDeviceDto vcDeviceDto) {
        VCPusherConfig vcPusherConfig = vcPusherConfigServiceInterface.findById(1L);
        String key = vcDeviceDto.getKey();
        String deviceNum = vcDeviceDto.getDeviceNum();
        Assert.hasText(key, "推流key不能为空");
        Assert.hasText(deviceNum, "设备编号不能为空");
        String delFFmpegSourceUrl = vcPusherConfig.getMediaServer() + "/index/api/delFFmpegSource?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=" + key;
        ResponseEntity<Map> response = this.restTemplate.getForEntity(delFFmpegSourceUrl, Map.class);
        Map body = response.getBody();
        int success = (int)body.get("code");
        if(success == 0){
            Map dataMap = JSONObject.parseObject(JSONObject.toJSONString(body.get("data")), Map.class);
            Boolean flag = (Boolean) dataMap.get("flag");
            if(flag) {
                return new ResultBean<>(ResultEnum.SUCCESS, "关闭流成功");
            }else{
                return new ResultBean<>(ResultEnum.FAILURE, "关闭流失败");
            }
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "关闭流失败");
        }
    }

    @Override
    @PostMapping(value = "/vcDevice/pusher/status")
    public ResultBean<String> devicePusherStatus(@RequestBody VCDeviceDto deviceDto) {
        String deviceNum = deviceDto.getDeviceNum();
        if(StringUtils.hasText(deviceNum)){
            return this.vcDeviceServiceInterface.devicePusherStatus(deviceDto);
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "设备号不能为空");
        }
    }

    @Override
    @PostMapping(value = "/vcDevice/pusher/delete")
    public ResultBean<String> devicePusherDelete(@RequestBody VCDeviceDto deviceDto) {
        String deviceNum = deviceDto.getDeviceNum();
        if(StringUtils.hasText(deviceNum)){
            return this.vcDeviceServiceInterface.devicePusherDelete(deviceDto);
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "设备号不能为空");
        }
    }

    /**
     * 获取设备视频地址
     * @param deviceDto
     * @return
     */
    @Override
    @PostMapping(value = "/vcDevice/getDevHttpFlvUrl")
    public ResultBean<String> deviceGetHttpFlvUrl(@RequestBody VCDeviceDto deviceDto) {
        String deviceNum = deviceDto.getDeviceNum();
        SysParams sysParams = this.sysParamsServiceInterface.findSysParamsByAcountPwd(deviceDto.getAccountName(), null);
        String rtspUrl = this.vcDeviceServiceInterface.deviceGetDevUrl(sysParams, deviceDto);
        ResultBean<String> resultBean = new ResultBean<>(ResultEnum.FAILURE, null);
        if(rtspUrl != null && StringUtils.hasText(rtspUrl)){
            Map<String, Object> map = new HashMap<>();
            map.put("deviceNum", deviceNum);
            map.put("rtspUrl", rtspUrl);
            String httpFlvUrl = this.getHttpFlvUrl(map);
            if(StringUtils.hasText(httpFlvUrl)){
                resultBean = new ResultBean<>(ResultEnum.SUCCESS, httpFlvUrl);
                return resultBean;
            }
        }
        return resultBean;
    }

    private String getHttpFlvUrl(Map<String, Object> map){
        VideoCloudHttpUtil httpUtil = new VideoCloudHttpUtil(null);
        String url = "http://192.168.0.228:2009/get/httpFlv";
//        String url = "http://localhost:2009/get/httpFlv";
        String httpFlvUrl = httpUtil.deviceGetHttpFlvUrl(map, url);
        return httpFlvUrl;
    }

    /**
     * 获取账户下所有设备的视频播放地址
     * @param vcDeviceDto
     * @return
     */
    @PostMapping(value = "/vcDevice/getDevUrlList")
    public ResultBean<Boolean> syncDeviceDevUrlList(@RequestBody VCDeviceDto vcDeviceDto){
        SysParams sysParams = this.sysParamsServiceInterface.findSysParamsByAcountPwd(vcDeviceDto.getAccountName(), null);
        this.vcDeviceServiceInterface.deviceGetDevUrlList(sysParams, vcDeviceDto.getAccountName());
        return new ResultBean<>(ResultEnum.SUCCESS, true);
    }

    @Override
    @GetMapping(value = "/vcDevice/getList")
    public ResultBean<List<VCDevice>> getList() {
        List<VCDevice> list = this.vcDeviceServiceInterface.getList();
        return new ResultBean<List<VCDevice>>(ResultEnum.SUCCESS, list);
    }

    @Override
    @PostMapping(value = "/vcDevice/updateBatch")
    public ResultBean<String> updateBatch(@RequestBody List<VCDevice> vcDeviceList) {
        boolean b = this.vcDeviceServiceInterface.updateBatchById(vcDeviceList);
        if(b){
            return new ResultBean<>(ResultEnum.SUCCESS, "视频云设备更新成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "视频云设备更新失败");
        }
    }

    @Override
    @PostMapping(value = "/vcDevice/update")
    public ResultBean<String> update(@RequestBody VCDevice vcDevice) {
        boolean b = this.vcDeviceServiceInterface.updateById(vcDevice);
        if(b){
            return new ResultBean<>(ResultEnum.SUCCESS, "视频云设备更新成功");
        }else{
            return new ResultBean<>(ResultEnum.FAILURE, "视频云设备更新失败");
        }
    }
}
