package com.videogo.ui.common;

import android.content.res.Resources;
import android.text.TextUtils;
import android.view.ContextThemeWrapper;

import com.videogo.openapi.EZConstants;
import com.videogo.openapi.bean.EZCameraInfo;
import com.videogo.openapi.bean.EZCloudRecordFile;
import com.videogo.openapi.bean.EZDeviceDetailPublicInfo;
import com.videogo.openapi.bean.EZDeviceInfo;
import com.videogo.openapi.bean.EZDeviceRecordFile;
import com.videogo.openapi.bean.EZSubDeviceInfo;
import com.videogo.openapi.bean.resp.CloudPartInfoFile;
import com.videogo.util.DateTimeUtil;
import com.videogo.util.Utils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import ezviz.ezopensdk.R;

/**
 * Copyright (C) 2022 HIKVISION Inc.
 * Comments:
 *
 * @author ChengJun9
 * @date 2022/9/29 4:49 下午
 */
public class EZBusinessTool {

    /**
     * 根据videoLevel获取设备视频质量名，0-流畅，1-均衡，2-高清，3-超清，4-极清，5-3K，6-4K
     *
     * @return
     */
    public static String getDeviceQualityTitle(ContextThemeWrapper context, int videoLevel) {
        Resources res = context.getResources();
        String qualityTitle;
        switch (videoLevel) {
            case 0:// 流畅
                qualityTitle = res.getString(R.string.quality_flunet);
                break;
            case 1:// 均衡
                qualityTitle = res.getString(R.string.quality_balanced);
                break;
            case 2:// 高清
                qualityTitle = res.getString(R.string.quality_hd);
                break;
            case 3:// 超清
                qualityTitle = res.getString(R.string.quality_super_hd);
                break;
            case 4:// 极清
                qualityTitle = res.getString(R.string.quality_extreme_hd);
                break;
            case 5:// 3K
                qualityTitle = res.getString(R.string.quality_3K);
                break;
            case 6:// 4K
                qualityTitle = res.getString(R.string.quality_4K);
                break;
            default:
                qualityTitle = "unknown";
                break;
        }

        return qualityTitle;
    }

    /**
     * 获取比当前清晰度高一级的清晰度
     * @param currentQulityMode 当前清晰度
     * @param deviceDetailPublicInfo 设备详情
     * @return
     */
    public static EZConstants.EZVideoLevel getHigherVideoLevel(EZConstants.EZVideoLevel currentQulityMode, EZDeviceDetailPublicInfo deviceDetailPublicInfo) {
        if (deviceDetailPublicInfo != null && deviceDetailPublicInfo.videoQualityInfos != null) {
            int targetVideoLevel = 0;
            int dif = 100;
            for (int i = 0; i < deviceDetailPublicInfo.videoQualityInfos.size(); i++) {
                int videoLevel = deviceDetailPublicInfo.videoQualityInfos.get(i).getVideoLevel();
                // 遍历找出比当前videoLevel大 且 最接近 的清晰度值
                if (videoLevel > currentQulityMode.getVideoLevel() && videoLevel - currentQulityMode.getVideoLevel() < dif) {
                    targetVideoLevel = videoLevel;
                    dif = videoLevel - currentQulityMode.getVideoLevel();
                }
            }
            if (targetVideoLevel > 0) {
                EZCameraInfo cameraInfo = new EZCameraInfo();
                cameraInfo.setVideoLevel(targetVideoLevel);
                return cameraInfo.getVideoLevel();
            }
        }

        return currentQulityMode;
    }

    /**
     * 获取比当前清晰度低一级的清晰度
     * @param currentQulityMode 当前清晰度
     * @param deviceDetailPublicInfo 设备详情
     * @return
     */
    public static EZConstants.EZVideoLevel getLowerVideoLevel(EZConstants.EZVideoLevel currentQulityMode, EZDeviceDetailPublicInfo deviceDetailPublicInfo) {
        if (deviceDetailPublicInfo != null && deviceDetailPublicInfo.videoQualityInfos != null) {
            int targetVideoLevel = 0;
            int dif = 100;
            for (int i = 0; i < deviceDetailPublicInfo.videoQualityInfos.size(); i++) {
                int videoLevel = deviceDetailPublicInfo.videoQualityInfos.get(i).getVideoLevel();
                // 遍历找出比当前videoLevel大 且 最接近 的清晰度值
                if (videoLevel < currentQulityMode.getVideoLevel() && currentQulityMode.getVideoLevel() - videoLevel < dif) {
                    targetVideoLevel = videoLevel;
                    dif = currentQulityMode.getVideoLevel() - videoLevel;
                }
            }
            if (targetVideoLevel > 0) {
                EZCameraInfo cameraInfo = new EZCameraInfo();
                cameraInfo.setVideoLevel(targetVideoLevel);
                return cameraInfo.getVideoLevel();
            }
        }

        return currentQulityMode;
    }

    /**
     * 获取变声类型
     *
     * @param tag
     * @return
     */
    public static EZConstants.EZVoiceChangeType getVoiceChangeType(String tag) {
        switch (Integer.parseInt(tag)) {
            case -7:
                return EZConstants.EZVoiceChangeType.EZ_VOICE_CHANGE_TYPE_MAN;
            case 7:
                return EZConstants.EZVoiceChangeType.EZ_VOICE_CHANGE_TYPE_CLOWN;
            default:
                return EZConstants.EZVoiceChangeType.EZ_VOICE_CHANGE_TYPE_NORMAL;
        }
    }

    /**
     * 根据type获取取流方式名
     *
     * @param streamType
     */
    public static String getStreamType(int streamType) {
        String strStreamType;
        switch (streamType) {
            /*
              取流方式切换到私有流媒体转发模式
             */
            case 0:
                strStreamType = "private_stream";
                break;
            /*
              取流方式切换到P2P模式
             */
            case 1:
                strStreamType = "p2p";
                break;
            /*
              取流方式切换到内网直连模式
             */
            case 2:
                strStreamType = "direct_inner";
                break;
            /*
              取流方式切换到外网直连模式
             */
            case 3:
                strStreamType = "direct_outer";
                break;
            /*
              取流方式切换到云存储回放
             */
            case 4:
                strStreamType = "cloud_playback";
                break;
            /*
              取流方式切换到云存储留言
             */
            case 5:
                strStreamType = "cloud_leave_msg";
                break;
            /*
              取流方式切换到反向直连模式
             */
            case 6:
                strStreamType = "direct_reverse";
                break;
            /*
              取流方式切换到HCNETSDK
             */
            case 7:
                strStreamType = "hcnetsdk";
                break;
            default:
                strStreamType = "unknown(" + streamType + ")";
                break;
        }
        return strStreamType;
    }

    /**
     * 根据type获取视频编码格式
     *
     * @param videoEncodeType
     */
    public static String getVideoEncodeType(int videoEncodeType) {
        String strVideoEncodeType;
        switch (videoEncodeType) {
            case 0:
                strVideoEncodeType = "无编码";
                break;
            case 1:
                strVideoEncodeType = "HIK264";
                break;
            case 2:
                strVideoEncodeType = "MPEG2";
                break;
            case 3:
                strVideoEncodeType = "MPEG4";
                break;
            case 4:
                strVideoEncodeType = "MJPEG";
                break;
            case 5:
                strVideoEncodeType = "H265";
                break;
            case 6:
                strVideoEncodeType = "SVAC";
                break;
            case 256:
                strVideoEncodeType = "H264";
                break;
            default:
                strVideoEncodeType = "unknown(" + videoEncodeType + ")";
                break;
        }
        return strVideoEncodeType;
    }

    /**
     * 显示解码方式，软解或硬解
     */
    public static String getDecodeType(int type) {
        String decodeTypeName;
        if (type == 1) {
            decodeTypeName = "hard";
        } else {
            decodeTypeName = "soft";
        }
        return decodeTypeName;
    }

    /**
     * 根据设备型号判断是否是HUB设备
     */
    public static boolean isHubDevice(String deviceType) {
        if (TextUtils.isEmpty(deviceType)) {
            return false;
        }
        switch (deviceType) {
            case "CASTT":
            case "CAS_HUB_NEW":
                return true;
            default:
                return deviceType.startsWith("CAS_WG_TEST");
        }
    }

    public static void convertCloudPartInfoFile2EZCloudRecordFile(EZCloudRecordFile dst, CloudPartInfoFile src) {
        dst.setCoverPic(src.getPicUrl());
        dst.setDownloadPath(src.getDownloadPath());
        dst.setFileId(src.getFileId());
        dst.setEncryption(src.getKeyCheckSum());
        dst.setStartTime(Utils.convert14Calender(src.getStartTime()));
        dst.setStopTime(Utils.convert14Calender(src.getEndTime()));
        dst.setDeviceSerial(src.getDeviceSerial());
        dst.setCameraNo(src.getCameraNo());
        dst.setVideoType(src.getVideoType());
        dst.setCloudType(src.getCloudType());
        dst.setiStorageVersion(src.getiStorageVersion());
        dst.setFileSize(src.getFileSize());
        dst.setSpaceId(src.getSpaceId());
    }

    public static void convertCloudPartInfoFile2EZDeviceRecordFile(EZDeviceRecordFile dst, CloudPartInfoFile src) {
        dst.setStartTime(Utils.convert14Calender(src.getStartTime()));
        dst.setStopTime(Utils.convert14Calender(src.getEndTime()));
    }

    public static Date getMinDate() {
        return DateTimeUtil.parseYMDStringToDate("2020-01-01");
    }

    /**
     * 是否支持对讲
     */
    public static EZConstants.EZTalkbackCapability isSupportTalk(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        // 网关下子设备的能力集挂载在自己的对象上
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportTalk();
        }
        return deviceInfo.isSupportTalk();
    }

    /**
     * 是否支持云台
     */
    public static boolean isSupportPTZ(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportPTZ();
        }
        return deviceInfo.isSupportPTZ();
    }

    /**
     * 是否支持内网直连时倍数设置
     */
    public static boolean isSupportDirectInnerRelaySpeed(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportDirectInnerRelaySpeed();
        }
        return deviceInfo.isSupportDirectInnerRelaySpeed();
    }

    /**
     * 是否支持回放倍率设置
     */
    public static boolean isSupportPlaybackRate(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportPlaybackRate();
        }
        return deviceInfo.isSupportPlaybackRate();
    }

    /**
     * 是否支持回放慢速(0.5倍和2倍)
     */
    public static boolean isSupportPlaybackSmallSpeed(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportPlaybackSmallSpeed();
        }
        return deviceInfo.isSupportPlaybackSmallSpeed();
    }

    /**
     * 获取回放最大倍速
     * =0(原始值-1被转化为0)代表默认支持1、4、8、16倍
     * =1代表不支持倍数
     * =4代表支持1、4倍
     * =8代表支持1、4、8倍
     * =16代表支持1、4、8、16倍
     */
    public static int getPlaybackMaxSpeed(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.getPlaybackMaxSpeed();
        }
        return deviceInfo.getPlaybackMaxSpeed();
    }

    /**
     * 获取云录像支持的倍数数组
     * 云录像默认支持 0.5、1、2、4、8、16、32
     */
    public static List<EZConstants.EZPlaybackRate> getCloudPlaybackRates() {
        List<EZConstants.EZPlaybackRate> rates = new ArrayList<>();
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_2_1);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_1);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_2);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_4);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_8);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_16);
        rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_32);
        return rates;
    }

    /**
     * 获取云录像支持的倍数显示字符串数组
     */
    public static List<String> getCloudPlaybackRateStrings() {
        List<EZConstants.EZPlaybackRate> rates = getCloudPlaybackRates();
        List<String> rateStrings = new ArrayList<>();
        for (EZConstants.EZPlaybackRate rate : rates) {
            rateStrings.add(rate.speed < 1 ? rate.speed + "倍" : (int) rate.speed + "倍");
        }
        return rateStrings;
    }

    /**
     * 获取SD卡录像支持的倍数数组
     * 规则：
     * 1. 先判断设备是否支持倍数回放(isSupportPlaybackRate)
     *    1.1 如果支持，通过 isSupportPlaybackSmallSpeed 和 getPlaybackMaxSpeed 获取支持倍数
     *        1.1.1 isSupportPlaybackSmallSpeed = YES：支持0.5、2倍；= NO：不支持0.5、2倍
     *        1.1.2 getPlaybackMaxSpeed = 0（原始值-1被转化为0）：默认支持1、4、8、16倍；= 1：不支持倍数；= 4：支持1、4；= 8：支持1、4、8；= 16：支持1、4、8、16
     *    1.2 如果不支持，判断是否内网直连(streamFetchType==2) && 支持内网直连倍数(isSupportDirectInnerRelaySpeed)
     *        - 是：返回 1、4、8 倍数
     *        - 否：返回 null，表示不支持倍数回放
     */
    public static List<EZConstants.EZPlaybackRate> getSDCardPlaybackRates(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo, int streamFetchType) {
        boolean supportPlaybackRate = isSupportPlaybackRate(deviceInfo, cameraInfo);

        if (supportPlaybackRate) {
            // 支持倍数回放，根据能力集组装倍数数组
            List<EZConstants.EZPlaybackRate> rates = new ArrayList<>();

            // 1.1.1 判断是否支持慢速(0.5倍和2倍)
            boolean supportSmallSpeed = isSupportPlaybackSmallSpeed(deviceInfo, cameraInfo);
            if (supportSmallSpeed) {
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_2_1);
            }

            // 1.1.2 根据 getPlaybackMaxSpeed 获取快速倍数
            int maxSpeed = getPlaybackMaxSpeed(deviceInfo, cameraInfo);
            if (maxSpeed == 1) {
                // = 1，不支持倍数，只返回1倍
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_1);
            } else if (maxSpeed == 0) {
                // = 0（原始值-1被转化为0），默认支持1、4、8、16倍
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_1);
                if (supportSmallSpeed) {
                    rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_2);
                }
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_4);
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_8);
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_16);
            } else {
                // 其他值，按maxSpeed判断支持的倍数
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_1);
                if (supportSmallSpeed) {
                    rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_2);
                }
                if (maxSpeed >= 4) {
                    rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_4);
                }
                if (maxSpeed >= 8) {
                    rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_8);
                }
                if (maxSpeed >= 16) {
                    rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_16);
                }
            }

            return rates;
        } else {
            // 不支持倍数回放，判断内网直连条件
            boolean supportDirectInner = isSupportDirectInnerRelaySpeed(deviceInfo, cameraInfo);
            if (streamFetchType == 2 && supportDirectInner) {
                // 内网直连 && 支持内网直连倍数：返回 1、4、8
                List<EZConstants.EZPlaybackRate> rates = new ArrayList<>();
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_1);
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_4);
                rates.add(EZConstants.EZPlaybackRate.EZ_PLAYBACK_RATE_8);
                return rates;
            }
            // 不支持倍数回放
            return null;
        }
    }

    /**
     * 获取SD卡录像支持的倍数显示字符串数组
     * @return 倍数字符串列表，null表示不支持倍数回放
     */
    public static List<String> getSDCardPlaybackRateStrings(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo, int streamFetchType) {
        List<EZConstants.EZPlaybackRate> rates = getSDCardPlaybackRates(deviceInfo, cameraInfo, streamFetchType);
        if (rates == null) {
            return null;
        }
        List<String> rateStrings = new ArrayList<>();
        for (EZConstants.EZPlaybackRate rate : rates) {
            rateStrings.add(rate.speed < 1 ? rate.speed + "倍" : (int) rate.speed + "倍");
        }
        return rateStrings;
    }

    /**
     * 是否支持SD卡录像封面
     */
    public static boolean isSupportSdCover(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportSdCover();
        }
        return deviceInfo.isSupportSdCover();
    }

    /**
     * 是否支持SD卡录像下载
     */
    public static boolean isSupportSDRecordDownload(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportSDRecordDownload();
        }
        return deviceInfo.isSupportSDRecordDownload();
    }

    /**
     * 是否支持缩放
     */
    public static boolean isSupportZoom(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportZoom();
        }
        return deviceInfo.isSupportZoom();
    }

    /**
     * 是否支持双目
     */
    public static boolean isSupportMultiChannel(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportMultiChannel();
        }
        return deviceInfo.isSupportMultiChannel();
    }

    /**
     * 是否支持自动清晰度
     */
    public static boolean isSupportDeviceAutoVideolevel(EZDeviceInfo deviceInfo, EZCameraInfo cameraInfo) {
        if (cameraInfo instanceof EZSubDeviceInfo) {
            EZSubDeviceInfo subDeviceInfo = (EZSubDeviceInfo) cameraInfo;
            return subDeviceInfo.isSupportDeviceAutoVideolevel();
        }
        return deviceInfo.isSupportDeviceAutoVideolevel();
    }

    /**
     * 获取设备热点前缀
     * 如果你的定制设备的热点前缀是SoftAP，那么此方法只需要配置EZVIZ和SoftAP即可，不需要配置CAMGO
     * @param deviceHotSpot 0-EZVIZ，1-SoftAP，2-CAMGO
     */
    public static String getWiFiConfigPrefix(int deviceHotSpot) {
        String WiFiConfigPrefix = "EZVIZ";
        switch (deviceHotSpot) {
            case 1:
                WiFiConfigPrefix = "SoftAP";
                break;
            case 2:
                WiFiConfigPrefix = "CAMGO";
                break;
            default:
                break;
        }
        return WiFiConfigPrefix;
    }

    /**
     * 获取录像列表中最近时间的结束时间（列表倒序排列，第一个即为最近）
     *
     * @param dataList 录像片段列表
     * @return 最近录像的结束时间，列表为空时返回 null
     */
    public static Calendar getLatestStopTimeFromList(List<CloudPartInfoFile> dataList) {
        if (dataList == null || dataList.isEmpty()) return null;
        CloudPartInfoFile firstFile = dataList.get(0);
        return Utils.convert14Calender(firstFile.getEndTime());
    }

    /**
     * 根据时间戳在录像列表中查找对应的片段索引
     *
     * @param dataList  录像片段列表
     * @param osdMillis 当前播放时间戳（毫秒）
     * @return 匹配的片段索引，未找到返回 -1
     */
    public static int findRecordIndexByTime(List<CloudPartInfoFile> dataList, long osdMillis) {
        if (dataList == null || dataList.isEmpty()) return -1;
        for (int i = 0; i < dataList.size(); i++) {
            CloudPartInfoFile file = dataList.get(i);
            if (osdMillis >= file.getStartMillis() && osdMillis <= file.getEndMillis()) {
                return i;
            }
        }
        return -1;
    }

}
