package com.yfd.monitor.gdw2019.transmit.event.request.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yfd.monitor.conf.DynamicTask;
import com.yfd.monitor.gdw2019.bean.Device;
import com.yfd.monitor.gdw2019.bean.DeviceChannel;
import com.yfd.monitor.gdw2019.bean.ParentPlatform;
import com.yfd.monitor.gdw2019.bean.SendRtpItem;
import com.yfd.monitor.gdw2019.transmit.SIPProcessorObserver;
import com.yfd.monitor.gdw2019.transmit.cmd.ISIPCommander;
import com.yfd.monitor.gdw2019.transmit.cmd.ISIPCommanderForPlatform;
import com.yfd.monitor.gdw2019.transmit.event.request.ISIPRequestProcessor;
import com.yfd.monitor.gdw2019.transmit.event.request.SIPRequestProcessorParent;
import com.yfd.monitor.media.zlm.ZLMRTPServerFactory;
import com.yfd.monitor.media.zlm.ZlmHttpHookSubscribe;
import com.yfd.monitor.media.zlm.dto.MediaServerItem;
import com.yfd.monitor.service.IMediaServerService;
import com.yfd.monitor.service.bean.RequestPushStreamMsg;
import com.yfd.monitor.service.redisMsg.RedisGbPlayMsgListener;
import com.yfd.monitor.storager.IRedisCatchStorage;
import com.yfd.monitor.storager.IVideoManagerStorage;
import com.yfd.monitor.storager.dao.DeviceChannelMapper;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.address.SipURI;
import javax.sip.header.CallIdHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderAddress;
import javax.sip.header.ToHeader;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * SIP命令类型： ACK请求
 */
@Component
public class AckRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {

    private Logger logger = LoggerFactory.getLogger(AckRequestProcessor.class);
    private final String method = "ACK";

    @Autowired
    private SIPProcessorObserver sipProcessorObserver;

    @Override
    public void afterPropertiesSet() throws Exception {
        // 添加消息处理的订阅
        sipProcessorObserver.addRequestProcessor(method, this);
    }

    @Autowired
    private IRedisCatchStorage redisCatchStorage;

    @Autowired
    private IVideoManagerStorage storager;

    @Autowired
    private ZLMRTPServerFactory zlmrtpServerFactory;

    @Autowired
    private ZlmHttpHookSubscribe hookSubscribe;

    @Autowired
    private IMediaServerService mediaServerService;
    @Autowired
    private DeviceChannelMapper deviceChannelMapper;

    @Autowired
    private ZlmHttpHookSubscribe subscribe;

    @Autowired
    private DynamicTask dynamicTask;

    @Autowired
    private ISIPCommander cmder;

    @Autowired
    private ISIPCommanderForPlatform commanderForPlatform;

    @Autowired
    private RedisGbPlayMsgListener redisGbPlayMsgListener;


    /**
     * 处理  ACK请求
     *
     * @param evt
     */
    @Override
    public void process(@NotNull RequestEvent evt) {
        System.out.println("[收到ACK]：" + evt.getRequest().toString());
        CallIdHeader callIdHeader = (CallIdHeader) evt.getRequest().getHeader(CallIdHeader.NAME);

        String platformGbId =
                ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
        logger.info("[收到ACK]： platformGbId->{}", platformGbId);
        logger.error("[收到ACK]： platformGbId->{}", platformGbId);
        ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
        // 取消设置的超时任务
        dynamicTask.stop(callIdHeader.getCallId());
        String channelId =
                ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
        Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformGbId, channelId);
        List<DeviceChannel> deviceChannels = deviceChannelMapper.queryAllChannels(device.getDeviceId());
        if (deviceChannels.size() > 0) {
            DeviceChannel deviceChannel = deviceChannels.get(0);
            channelId = deviceChannel.getChannelId();
        }

        //TODO 使用UDP/TCP发送RTP数据包
        SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null,
                callIdHeader.getCallId());
        System.out.println("==================sendRtpItem==================" + sendRtpItem.toString());
        if (sendRtpItem == null) {
            logger.warn("[收到ACK]：未找到通道({})的推流信息", channelId);
            logger.error("[收到ACK]：未找到通道({})的推流信息", channelId);
            return;
        }
        String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
        MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
        String streamId = sendRtpItem.getStreamId();
        System.out.println("==================sendRtpItem==================1");
        if (mediaInfo.isRtpEnable()) {
            streamId = String.format("%s_%s", device.getDeviceId(), channelId);
        }
        System.out.println("==================sendRtpItem==================2");
        logger.error("收到ACK，rtp/{}开始向上级推流, 目标={}:{}，SSRC={}", streamId, sendRtpItem.getIp(), sendRtpItem.getPort(),
                sendRtpItem.getSsrc());
        System.out.println("==================sendRtpItem==================3");
        Map<String, Object> param = new HashMap<>(12);
        param.put("vhost", "__defaultVhost__");
        param.put("app", sendRtpItem.getApp());
        param.put("stream", streamId);
        param.put("ssrc", sendRtpItem.getSsrc());
        param.put("dst_url", sendRtpItem.getIp());
        param.put("dst_port", sendRtpItem.getPort());
        param.put("is_udp", is_Udp);
        param.put("src_port", sendRtpItem.getLocalPort());
        param.put("pt", sendRtpItem.getPt());
        param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
//        param.put("use_ps", "1");
        param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
        if (!sendRtpItem.isTcp()) {
            // 开启rtcp保活
            param.put("udp_rtcp_timeout", sendRtpItem.isRtcp() ? "1" : "0");
        }
        System.out.println("==================sendRtpItem==================4");
        System.out.println("=====================param========================" + param.toString());
        if (mediaInfo == null) {
            System.out.println("==================sendRtpItem==================5");
            RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance(
                    sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(),
                    sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(),
                    sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio());
            redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject -> {
                startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
            });
        } else {
            System.out.println("==================sendRtpItem==================6");
            System.out.println("==================sendRtpItem==================7" + sendRtpItem.getLocalPort());
            System.out.println("==================sendRtpItem==================8" + sendRtpItem.isRtcp());
            // 如果是非严格模式，需要关闭端口占用
            if (sendRtpItem.getLocalPort() != 0) {
                zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc());

            }
            String videoPath = "/data-space/files/riis500/encoded_h264.h264";
            String destinationIp = "22.58.160.19";
            String rtspStr = "rtsp://192.168.22.1:31554/rtp/" + streamId;
            int destinationPort = sendRtpItem.getPort();
            String ffmpegStr="ffmpeg -re -i "+rtspStr+" -vcodec h264 -acodec aac -f rtp_mpegts rtp://"+destinationIp+":"+destinationPort;

//            try {
//                RTPStreamer.streamVideo(rtspStr, destinationIp, destinationPort);
//                RTPStreamer.sendRtp(ffmpegStr);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
            JSONObject startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
            System.out.println("==================startSendRtpStreamResult=================" + startSendRtpStreamResult.toString());
            if (startSendRtpStreamResult != null) {
                startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader);
            }
        }
    }

    private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform,
                                        JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) {
        if (jsonObject == null) {
            logger.error("RTP推流失败: 请检查ZLM服务");
        } else if (jsonObject.getInteger("code") == 0) {
            logger.error("调用ZLM推流接口, 结果： {}", jsonObject);
            logger.error("RTP推流成功[ {}/{} ]，{}->{}:{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
        } else {
            logger.error("RTP推流失败: {}, 参数：{}", jsonObject.getString("msg"), JSON.toJSONString(param));
            if (sendRtpItem.isOnlyAudio()) {
                // TODO 可能是语音对讲
            } else {
                // 向上级平台
                try {
                    commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
                } catch (SipException | InvalidArgumentException | ParseException e) {
                    logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
                }
            }
        }
    }
}
