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


import be.teletask.onvif.DiscoveryManager;
import be.teletask.onvif.OnvifManager;
import be.teletask.onvif.listeners.DiscoveryListener;
import be.teletask.onvif.listeners.OnvifMediaProfilesListener;
import be.teletask.onvif.listeners.OnvifResponseListener;
import be.teletask.onvif.models.Device;
import be.teletask.onvif.models.OnvifDevice;
import be.teletask.onvif.models.OnvifMediaProfile;
import be.teletask.onvif.models.OnvifServices;
import be.teletask.onvif.responses.OnvifResponse;
import com.alibaba.fastjson.JSONObject;
import com.zd.iot.vmp.media.zlm.dto.MediaServerItem;
import com.zd.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.zd.iot.vmp.onvif.IONVIFServer;
import com.zd.iot.vmp.onvif.dto.ONVIFCallBack;
import com.zd.iot.vmp.service.IStreamProxyService;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@SuppressWarnings("rawtypes")
/**
 * 处理onvif的各种操作
 */
@Service
public class ONVIFServerIMpl implements IONVIFServer {

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

    @Autowired
    private IStreamProxyService streamProxyService;

    @Override
    public void search(int timeout, ONVIFCallBack<List<String>> callBack) {
        DiscoveryManager manager = new DiscoveryManager();
        manager.setDiscoveryTimeout(timeout);
        Map<String, Device> deviceMap = new HashMap<>();
        // 搜索设备
        manager.discover(new DiscoveryListener() {
            @Override
            public void onDiscoveryStarted() {
                logger.info("Discovery started");
            }

            @Override
            public void onDevicesFound(List<Device> devices) {
                logger.info("搜索中***********");
                if (devices == null || devices.size() == 0) return;
                for (Device device : devices){
                    logger.info(device.getHostName());
                    deviceMap.put(device.getHostName(),  device);
                }
            }

            // 搜索结束
            @Override
            public void onDiscoveryFinished() {
                logger.info("搜索结束");
                ArrayList<String> result = new ArrayList<>();
                for (Device device : deviceMap.values()) {
                    logger.info(device.getHostName());
                    result.add(device.getHostName());
                }
                try {
                    callBack.run(0, result);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void getRTSPUrl(int timeout, OnvifDevice device, ONVIFCallBack<String> callBack) {
        if (device.getHostName() == null ){
            try {
                callBack.run(400, null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        OnvifManager onvifManager = new OnvifManager();
        onvifManager.setOnvifResponseListener(new OnvifResponseListener(){
            @Override
            public void onResponse(OnvifDevice onvifDevice, OnvifResponse response) {
                logger.info("[RESPONSE] " + onvifDevice.getHostName()
                        + "======" + response.getErrorCode()
                        + "======" + response.getErrorMessage());
            }
            @Override
            public void onError(OnvifDevice onvifDevice, int errorCode, String errorMessage) {
                logger.info("[ERROR] " + onvifDevice.getHostName() + "======" + errorCode + "=======" + errorMessage);
                try {
                    callBack.run(errorCode, errorMessage);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        try {
            onvifManager.getServices(device, (OnvifDevice onvifDevice, OnvifServices services) -> {
                if (services.getProfilesPath().equals("/onvif/Media")) {
                    onvifDevice.setPath(services);
                    onvifManager.getMediaProfiles(onvifDevice, new OnvifMediaProfilesListener() {
                        @Override
                        public void onMediaProfilesReceived(OnvifDevice device, List<OnvifMediaProfile> mediaProfiles) {
                            for (OnvifMediaProfile mediaProfile : mediaProfiles) {
                                logger.info(mediaProfile.getName());
                                logger.info(mediaProfile.getToken());
                                if (mediaProfile.getName().equals("mainStream") || mediaProfile.getName().equals("Profile_001")) {
                                    onvifManager.getMediaStreamURI(device, mediaProfile, (OnvifDevice onvifDevice, OnvifMediaProfile profile, String uri) -> {
                                        uri = uri.replace("rtsp://", "rtsp://"+ device.getUsername() + ":"+ device.getPassword() + "@");
                                        logger.info(onvifDevice.getHostName() + "的地址" + uri);
                                        try {
                                            callBack.run(0, uri);
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    });
                                }
                            }
                        }
                    });
                }
            });
        }catch (Exception e) {
            try {
                callBack.run(400, e.getMessage());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public JSONObject startRecord(MediaServerItem mediaServerItem,Map<String, Object> param){
        StreamProxyItem streamProxyItem=new StreamProxyItem();
        Long timeChar=new Date().getTime();
        String appName=param.get("app").toString();
        String streamName=param.get("stream").toString();
        streamProxyItem.setApp(appName);
        streamProxyItem.setCreateTime(timeChar+"");
        streamProxyItem.setStream(streamName);
        streamProxyItem.setUrl(param.get("rstpUrl").toString());
        streamProxyItem.setStatus(true);
        streamProxyItem.setType("default");
        streamProxyItem.setEnable(true);
        streamProxyItem.setEnable_hls(true);
        streamProxyItem.setEnable_mp4(true);
        streamProxyItem.setMediaServerId("your_server_id");
        String msg=streamProxyService.save(streamProxyItem);
        if(!msg.contains("保存成功")){
            logger.error("拉流代理保存失败,请检查配置！");
        }
        param.put("app",appName);
        param.put("stream",streamName);
        param.put("api","startRecord");
        param.remove("rstpUrl");
        return getCommonRecord(mediaServerItem,param);
    }

    @Override
    public Boolean isRecording(MediaServerItem mediaServerItem, Map<String, Object> param) {
        param.put("api","isRecording");
        JSONObject jsonObject=getCommonRecord(mediaServerItem,param);
        if(null!=jsonObject && jsonObject.getInteger("code")==0){
           return jsonObject.getBoolean("status");
        }
        return false;
    }
    @Override
    public String stopRecord(MediaServerItem mediaServerItem, Map<String, Object> param){
        param.put("api","stopRecord");
        JSONObject jsonObject=getCommonRecord(mediaServerItem,param);
        String separator= File.separator;
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
        String strTime=simpleDateFormat.format(new Date());
        String rootPath="/home/upload";
        String prefixPath="statics";
        String joinPath=separator+"record"+separator+param.get("app")+separator+param.get("stream")+separator+strTime+separator;
        String urlPath=rootPath+joinPath;
        String returnPath=prefixPath+joinPath;
        Integer code=jsonObject.getInteger("code");
        if(code==0){
            List<String> fileLlist=getFileName(urlPath);
            logger.error("fileLlist size:"+fileLlist.size());
            if(null!=fileLlist && fileLlist.size()>0){
                //fileLlist=fileLlist.stream().sorted(Comparator.comparing(String::toString).reversed()).collect(Collectors.toList());
                return returnPath+fileLlist.get(fileLlist.size()-1);
            }else{
                return null;
            }
        }
        return null;
    }

    @Override
    public Boolean closeStream(MediaServerItem mediaServerItem, Map<String, Object> param) {
        param.put("vhost","__defaultVhost__");
        param.put("schema","rtsp");
        param.put("api","close_streams");
        param.put("force",1);
        JSONObject jsonObject=getCommonRecord(mediaServerItem,param);
        Integer code=jsonObject.getInteger("code");
        Integer count_closed=jsonObject.getInteger("count_closed");
        if(code==0 && count_closed>0){
            return true;
        }
        return false;
    }


    private JSONObject getCommonRecord(MediaServerItem mediaServerItem,Map<String, Object> param) {
        OkHttpClient client = new OkHttpClient();
        if(null==mediaServerItem){
            logger.error("mediaServerItem为空，请检查配置！");
            return null;
        }
        String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), param.get("api"));
        FormBody.Builder builder = new FormBody.Builder();
        builder.add("secret",mediaServerItem.getSecret());
        if (param != null && param.keySet().size() > 0) {
            for (String key : param.keySet()){
                if (param.get(key) != null) {
                    builder.add(key, param.get(key).toString());
                }
            }
        }
        FormBody body = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return JSONObject.parseObject(response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static List<String> getFileName(String path) {
        List<String> list=new ArrayList<>();
        File f = new File(path);//获取路径  F:测试目录
        if (!f.exists()) {
            System.out.println(path + " not exists");//不存在就输出
            return null;
        }
        File fa[] = f.listFiles();//用数组接收  F:笔记总结C#, F:笔记总结if语句.txt
        for (int i = 0; i < fa.length; i++) {//循环遍历
            File fs = fa[i];//获取数组中的第i个
            list.add(fs.getName());
        }
        return list;
    }
}
