package cn.iocoder.yudao.module.pms.service.yanfan.play;

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.server.VideoSessionManager;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.device.vo.YfSipDeviceRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.vo.VideoSessionInfo;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.utils.SipUtil;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.utils.ZlmApiUtils;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.media.YfMediaServerDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.sip.device.YfSipDeviceDO;
import cn.iocoder.yudao.module.pms.service.yanfan.media.YfMediaServerService;
import cn.iocoder.yudao.module.pms.service.yanfan.play.model.Stream;
import cn.iocoder.yudao.module.pms.service.yanfan.sip.IRtspCmd;
import cn.iocoder.yudao.module.pms.service.yanfan.sip.ISipCmd;
import cn.iocoder.yudao.module.pms.service.yanfan.sip.IZmlHookService;
import cn.iocoder.yudao.module.pms.service.yanfan.sip.device.YfSipDeviceService;
import com.alibaba.fastjson.JSONObject;
import liquibase.pro.packaged.Y;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class PlayServiceImpl implements IPlayService {

    @Autowired
    private ISipCmd sipCmd;

    @Autowired
    private IRtspCmd rtspCmd;

    @Autowired
    private IZmlHookService zmlHookService;

    @Autowired
    private VideoSessionManager streamSession;

    @Autowired
    private YfSipDeviceService sipDeviceService;

    @Autowired
    private YfMediaServerService mediaServerService;

    @Autowired
    private ZlmApiUtils zlmApiUtils;

    @Override
    public Stream play(String deviceId, String channelId, boolean record) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        if (dev == null) {
            log.error("play dev is null,deviceId:{},channelId:{}", deviceId, channelId);
            return null;
        }
        String streamid;
        if (record) {
            streamid = String.format("%s_%s_%s", SipUtil.PREFIX_PLAYRECORD,
                    deviceId,
                    channelId);
        } else {
            streamid = String.format("%s_%s_%s", SipUtil.PREFIX_PLAY, deviceId, channelId);
        }
        VideoSessionInfo sinfo = streamSession.getSessionInfo(deviceId, channelId, streamid, null);
        if (sinfo == null) {
            VideoSessionInfo info = sipCmd.playStreamCmd(respVO, channelId, record);
            return zmlHookService.updateStream(info);
        } else {
            log.info("sinfo： {}", sinfo);
            YfMediaServerDO mediaInfo = mediaServerService.selectMediaServerBydeviceSipId(deviceId);
            if (mediaInfo == null) {
                log.error("mediaInfo is null,deviceId:{},channelId:{}", deviceId, channelId);
            }
            JSONObject rtpInfo = zlmApiUtils.getRtpInfo(mediaInfo, streamid);
            if (rtpInfo != null && rtpInfo.getInteger("code") == 0) {
                if (rtpInfo.getBoolean("exist")) {
                    //直播
                    if (sinfo.isPushing() && !record) {
                        return zmlHookService.updateStream(sinfo);
                    }
                    //直播录像
                    if (sinfo.isRecording() && record) {
                        return zmlHookService.updateStream(sinfo);
                    }
                } else {
                    //清理会话后 重新发起播放
                    sipCmd.streamByeCmd(respVO, channelId, streamid, null);
                    VideoSessionInfo info = sipCmd.playStreamCmd(respVO, channelId, record);
                    return zmlHookService.updateStream(info);
                }
            } else {
                log.error("获取流信息失败：{}", rtpInfo);
            }
            return null;
        }
    }

    @Override
    public String closeStream(String deviceId, String channelId, String streamId) {
        YfMediaServerDO mediaInfo = mediaServerService.selectMediaServerBydeviceSipId(deviceId);
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        JSONObject ret = zlmApiUtils.getMediaList(mediaInfo, "rtp", "rtmp", streamId);
        int code = ret.getInteger("code");
        if (code == 0) {
            int readerCount = ret.getInteger("readerCount");
            log.info("还有{}位用户正在观看该流！", readerCount);
            if (readerCount < 1) {
                sipCmd.streamByeCmd(respVO, channelId, streamId, null);
            }
        } else {
            log.info("流详细信息：{}，错误码：{}", ret, code);
        }
        return "";
    }

    @Override
    public Stream playback(String deviceId, String channelId, String startTime, String endTime) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        VideoSessionInfo info = sipCmd.playbackStreamCmd(respVO, channelId, startTime, endTime);
        return zmlHookService.updateStream(info);
    }

    @Override
    public String playbackPause(String deviceId, String channelId, String streamId) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        VideoSessionInfo sinfo = streamSession.getSessionInfo(deviceId, channelId, streamId, null);
        if (null == sinfo) {
            return "streamId不存在";
        }
        rtspCmd.setCseq(sinfo.getStream());
        rtspCmd.playPause(respVO, channelId, streamId);
        return null;
    }

    @Override
    public String playbackReplay(String deviceId, String channelId, String streamId) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        VideoSessionInfo sinfo = streamSession.getSessionInfo(deviceId, channelId, streamId, null);
        if (null == sinfo) {
            return "streamId不存在";
        }
        rtspCmd.setCseq(streamId);
        rtspCmd.playReplay(respVO, channelId, streamId);
        return null;
    }

    @Override
    public String playbackSeek(String deviceId, String channelId, String streamId, long seektime) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        VideoSessionInfo sinfo = streamSession.getSessionInfo(deviceId, channelId, streamId, null);
        if (null == sinfo) {
            return "streamId不存在";
        }
        rtspCmd.setCseq(streamId);
        rtspCmd.playBackSeek(respVO, channelId, streamId, seektime);
        return null;
    }

    @Override
    public String playbackSpeed(String deviceId, String channelId, String streamId, Integer speed) {
        YfSipDeviceDO dev = sipDeviceService.selectSipDeviceBySipId(deviceId);
        YfSipDeviceRespVO respVO = BeanUtil.toBean(dev, YfSipDeviceRespVO.class);
        VideoSessionInfo sinfo = streamSession.getSessionInfo(deviceId, channelId, streamId, null);
        if (null == sinfo) {
            return "streamId不存在";
        }
        rtspCmd.setCseq(streamId);
        rtspCmd.playBackSpeed(respVO, channelId, streamId, speed);
        return null;
    }
}
