package com.yfd.monitor.gdw2019;

import cn.hutool.core.util.StrUtil;
import com.yfd.monitor.conf.SipConfig;
import com.yfd.monitor.conf.UserSetting;
import com.yfd.monitor.gdw2019.bean.ParentPlatform;
import com.yfd.monitor.gdw2019.conf.DefaultProperties;
import com.yfd.monitor.gdw2019.transmit.ISIPProcessorObserver;
import com.yfd.monitor.storager.IVideoManagerStorage;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.sip.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Order(value = 10)
public class SipLayer implements CommandLineRunner {

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

    @Autowired
    private SipConfig sipConfig;

    @Autowired
    private ISIPProcessorObserver sipProcessorObserver;
    @Autowired
    private IVideoManagerStorage storager;

    @Autowired
    private UserSetting userSetting;

    private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
    private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();

    @Override
    public void run(String... args) {
        List<String> monitorIps = new ArrayList<>();
        // 使用逗号分割多个ip
        String separator = ",";
        if (sipConfig.getIp().indexOf(separator) > 0) {
            String[] split = sipConfig.getIp().split(separator);
            monitorIps.addAll(Arrays.asList(split));
        } else {
            monitorIps.add(sipConfig.getIp());
        }

        SipFactory.getInstance().setPathName("gov.nist");
        if (monitorIps.size() > 0) {
            for (String monitorIp : monitorIps) {
                addListeningPoint(monitorIp, sipConfig.getPort());
            }
            if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) {
                System.exit(1);
            }
        }
    }


    private void addListeningPoint(String monitorIp, int port) {
        SipStackImpl sipStack;
        try {
            Properties properties = DefaultProperties.getProperties(monitorIp, userSetting.getSipLog());
            sipStack =
                    (SipStackImpl) SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp,
                            userSetting.getSipLog()));
        } catch (PeerUnavailableException e) {
            logger.error("[Sip Server] SIP服务启动失败， 监听地址{}失败,请检查ip是否正确", monitorIp);
            return;
        }
        List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true);
        String ip = "";
        if (parentPlatforms.size() > 0) {
            ip = parentPlatforms.get(0).getDeviceIp();
        }

        try {
            System.out.println("----------------------------------------------------------------------------");
            ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");
            System.out.println("----------------------------------------------------------------------------1");
            SipProviderImpl tcpSipProvider = (SipProviderImpl) sipStack.createSipProvider(tcpListeningPoint);
            System.out.println("----------------------------------------------------------------------------2");
            tcpSipProvider.setDialogErrorsAutomaticallyHandled();
            System.out.println("----------------------------------------------------------------------------3");
            tcpSipProvider.addSipListener(sipProcessorObserver);
            System.out.println("----------------------------------------------------------------------------4");
            System.out.println(monitorIp);
            System.out.println(tcpSipProviderMap.toString());
            tcpSipProviderMap.put(monitorIp, tcpSipProvider);
            logger.info("[Sip Server] tcp://{}:{} 启动成功", monitorIp, port);
            try {
                if (StrUtil.isNotBlank(ip) && !ip.equals(monitorIp)) {
                    ListeningPoint tcpListeningPoint1 = sipStack.createListeningPoint(ip, 5060, "TCP");
                    SipProviderImpl tcpSipProvider1 = (SipProviderImpl) sipStack.createSipProvider(tcpListeningPoint1);
                    tcpSipProvider1.setDialogErrorsAutomaticallyHandled();
                    tcpSipProvider1.addSipListener(sipProcessorObserver);

                    tcpSipProviderMap.put(ip, tcpSipProvider1);


                    ListeningPoint tcpListeningPoint2 = sipStack.createListeningPoint(ip, 5083, "TCP");
                    SipProviderImpl tcpSipProvider2 = (SipProviderImpl) sipStack.createSipProvider(tcpListeningPoint2);
                    tcpSipProvider2.setDialogErrorsAutomaticallyHandled();
                    tcpSipProvider2.addSipListener(sipProcessorObserver);
                    tcpSipProviderMap.put(ip+"5083", tcpSipProvider2);
                }

            }catch (Exception e){
                e.printStackTrace();
                logger.error("[Sip Server] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
                        , ip, 5060);
            }


        } catch (TransportNotSupportedException
                | TooManyListenersException
                | ObjectInUseException
                | InvalidArgumentException e) {
            e.printStackTrace();
            logger.error("[Sip Server] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
                    , monitorIp, port);
        }

        try {
            ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");
            SipProviderImpl udpSipProvider = (SipProviderImpl) sipStack.createSipProvider(udpListeningPoint);
            udpSipProvider.addSipListener(sipProcessorObserver);
            udpSipProviderMap.put(monitorIp, udpSipProvider);
            try {
                if (StrUtil.isNotBlank(ip) && !ip.equals(monitorIp)) {
                    ListeningPoint udpListeningPoint1 = sipStack.createListeningPoint(ip, 5060, "UDP");
                    SipProviderImpl udpSipProvider1 = (SipProviderImpl) sipStack.createSipProvider(udpListeningPoint1);
                    udpSipProvider1.addSipListener(sipProcessorObserver);
                    udpSipProviderMap.put(ip, udpSipProvider1);


                    ListeningPoint udpListeningPoint2 = sipStack.createListeningPoint(ip, 5083, "UDP");
                    SipProviderImpl udpSipProvider2 = (SipProviderImpl) sipStack.createSipProvider(udpListeningPoint2);
                    udpSipProvider2.addSipListener(sipProcessorObserver);
                    udpSipProviderMap.put(ip+"5083", udpSipProvider2);
                }
            }catch (Exception e){
                e.printStackTrace();
                logger.error("[Sip Server] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
                        , ip, 5060);
            }

            logger.info("[Sip Server] udp://{}:{} 启动成功", monitorIp, port);
        } catch (Exception e) {
//		} catch (TransportNotSupportedException
//				 | TooManyListenersException
//				 | ObjectInUseException
//				 | InvalidArgumentException e) {
            e.printStackTrace();
            logger.error("[Sip Server] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"
                    , monitorIp, port);
        }
    }

    public SipProviderImpl getUdpSipProvider(String ip) {
        if (ObjectUtils.isEmpty(ip)) {
            return null;
        }
        return udpSipProviderMap.get(ip);
    }

    public SipProviderImpl getUdpSipProvider() {
        if (udpSipProviderMap.size() != 1) {
            return null;
        }
        return udpSipProviderMap.values().stream().findFirst().get();
    }

    public SipProviderImpl getTcpSipProvider() {
        if (tcpSipProviderMap.size() != 1) {
            return null;
        }
        return tcpSipProviderMap.values().stream().findFirst().get();
    }

    public SipProviderImpl getTcpSipProvider(String ip) {
        if (ObjectUtils.isEmpty(ip)) {
            return null;
        }
        return tcpSipProviderMap.get(ip);
    }

    public String getLocalIp(String deviceLocalIp) {
        if (!ObjectUtils.isEmpty(deviceLocalIp)) {
            return deviceLocalIp;
        }
        return getUdpSipProvider().getListeningPoint().getIPAddress();
    }
}
