package com.xxl.job.executor.utils;

import com.alibaba.fastjson.JSONObject;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.auth.COSSigner;
import com.qcloud.cos.http.HttpMethodName;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.mps.v20190612.MpsClient;
import com.tencentcloudapi.mps.v20190612.models.*;
import com.xxl.job.executor.constant.CosConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by JQ.bi on 2020.6.28
 */
@Configuration
public class CloudVideoProcessUtil {

    private static RestTemplate restTemplate = new RestTemplate();

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

    private static final String SECRET_ID = "AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets";
    private static final String SECRET_KEY = "tXzuwMfplTTK3c9GFUyETilasvQfePu9";
    private static final String ENDPOINT = "mps.tencentcloudapi.com";
    private static final String COS_LOCATION = "ap-chongqing";
    private static final String COS_BUCKET_MEDIA = "media-1301855440";
    private static final String COS_BUCKET_PART = "part-1301855440";


    public static DescribeTaskDetailResponse getTaskDetailResponse(String taskId) {
        MpsClient client = getClient();
        DescribeTaskDetailRequest describeTaskDetailRequest = new DescribeTaskDetailRequest();
        describeTaskDetailRequest.setTaskId(taskId);
        DescribeTaskDetailResponse resp = null;
        try {
            resp = client.DescribeTaskDetail(describeTaskDetailRequest);
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
        return resp;
    }

    /**
     * 发起视频水印处理请求
     */
    public static String videoWatermarkHandle(String videoPath, Long watermarkTemplateId) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        MpsClient client = getClient();
        //发起视频处理请求
        ProcessMediaRequest request = new ProcessMediaRequest();
        TranscodeTaskInput transcodeTaskInput = new TranscodeTaskInput();
        transcodeTaskInput.setOutputObjectPath("/watermark/" + sdf.format(new Date()) + "/" + UUID.randomUUID() + ".mp4");
        //水印模板信息
        WatermarkInput watermarkInput = new WatermarkInput();
        watermarkInput.setDefinition(watermarkTemplateId);
        //指定视频转码模板
        transcodeTaskInput.setDefinition(30L);
        transcodeTaskInput.setWatermarkSet(new WatermarkInput[]{watermarkInput});
        MediaProcessTaskInput mediaProcessTaskInput = new MediaProcessTaskInput();
        mediaProcessTaskInput.setTranscodeTaskSet(new TranscodeTaskInput[]{transcodeTaskInput});
        request.setMediaProcessTask(mediaProcessTaskInput);
        //视频输入
        CosInputInfo cosInputInfo = new CosInputInfo();
        cosInputInfo.setRegion(COS_LOCATION);
        cosInputInfo.setBucket(COS_BUCKET_MEDIA);
        cosInputInfo.setObject("/" + videoPath);
        MediaInputInfo mediaInputInfo = new MediaInputInfo();
        mediaInputInfo.setType("COS");
        mediaInputInfo.setCosInputInfo(cosInputInfo);
        request.setInputInfo(mediaInputInfo);
        //加水印视频输出
        CosOutputStorage cosOutputStorage = new CosOutputStorage();
        cosOutputStorage.setBucket(COS_BUCKET_MEDIA);
        cosOutputStorage.setRegion(COS_LOCATION);
        TaskOutputStorage taskOutputStorage = new TaskOutputStorage();
        taskOutputStorage.setType("COS");
        taskOutputStorage.setCosOutputStorage(cosOutputStorage);
        request.setOutputStorage(taskOutputStorage);
        ProcessMediaResponse response = null;
        String taskId = "";
        try {
            response = client.ProcessMedia(request);
        } catch (TencentCloudSDKException e) {
            logger.error(e.getMessage());
        }
        if (null != response) {
            taskId = response.getTaskId();
        }
        return taskId;
    }

    /**
     * 查询数据万象任务状态
     *
     * @return
     */
    public static Map getMediaJobsResponse(String jobId) {
        String auth = generateAuth(SECRET_ID, SECRET_KEY, "/jobs/" + jobId, HttpMethodName.GET);
        if (auth.isEmpty()) {
            logger.error("腾讯云Authorization获取失败");
        }
        //请求media-1301855440.ci.ap-chongqing.myqcloud.com/jobs/jobId 接口
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", auth);
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        String response = null;
        try {
            response = restTemplate.exchange(CosConstant.URL_JOBS + "/" + jobId, HttpMethod.GET, requestEntity, String.class).getBody();
        } catch (RestClientException e) {
            logger.error(e.getMessage());
        }
        Map<String, Object> mapResp = XmlToMapUtil.multilayerXmlToMap(response);
        Map JobsDetail = (Map) ((Map) mapResp.get("Response")).get("JobsDetail");
        if ("Success".equals(JobsDetail.get("Code"))) {
            return JobsDetail;
        } else {
            return new HashMap();
        }
    }

    public static void main(String[] args) {
        String loadImage = "cutFrame/" + 12345 + "/${Number}.jpg";
        Map<String, Object> stringObjectMap = videoCutFrameHandle("/video/2020-07-22/1595381635927-JX.美白丸混剪.mp4", loadImage);
        System.err.println(stringObjectMap);
    }

    /**
     * 数据万象发起视频抽帧处理请求
     */
    public static Map<String, Object> videoCutFrameHandle(String videoPath, String outputPath) {
        Map<String, Object> result = new HashMap<>();
        String auth = generateAuth(SECRET_ID, SECRET_KEY, "/jobs", HttpMethodName.POST);
        if (auth.isEmpty()) {
            logger.error("腾讯云Authorization获取失败");
        }
        //拼接请求数据万象jobs接口的参数
        JSONObject input = new JSONObject();
        input.put("Object", videoPath);
        JSONObject output = new JSONObject();
        output.put("Region", COS_LOCATION);
        output.put("Bucket", COS_BUCKET_MEDIA);
        output.put("Object", outputPath);
        JSONObject operation = new JSONObject();
        operation.put("TemplateId", CosConstant.TEMPLATE_ID);
        operation.put("Output", output);
        JSONObject request = new JSONObject();
        request.put("Tag", "Snapshot");
        request.put("Input", input);
        request.put("Operation", operation);
        request.put("QueueId", CosConstant.QUEUE_ID);

        //请求media-1301855440.ci.ap-chongqing.myqcloud.com/jobs 接口
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", auth);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(request.toJSONString(), headers);
        String response = null;
        try {
            response = restTemplate.exchange(CosConstant.URL_JOBS, HttpMethod.POST, requestEntity, String.class).getBody();
        } catch (RestClientException e) {
            logger.error(e.getMessage());
        }
        Map<String, Object> mapResp = XmlToMapUtil.multilayerXmlToMap(response);
        Map JobsDetail = (Map) ((Map) mapResp.get("Response")).get("JobsDetail");
        if ("Success".equals(JobsDetail.get("Code"))) {
            Map jobStatusMap = null;
            for (int i = 0; i < 30; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    logger.error(e.getMessage());
                }
                jobStatusMap = getMediaJobsResponse(JobsDetail.get("JobId").toString());
                if ("Success".equals(jobStatusMap.get("State"))) {
                    break;
                }
            }
            if ("Success".equals(jobStatusMap.get("State"))) {
                result = getFrameUrl(outputPath);
            } else {
                result = getErrorUrl();
            }
        }
        return result;
    }

    /**
     * 数据万象获取截图服务
     */
    public static String videoCutPictureHandle(String videoPath, String outputPath) {
        String auth = generateAuth(SECRET_ID, SECRET_KEY, "/snapshot", HttpMethodName.POST);
        if (auth.isEmpty()) {
            logger.error("腾讯云Authorization获取失败");
        }
        //拼接请求数据万象jobs接口的参数
        JSONObject input = new JSONObject();
        input.put("Object", videoPath);
        JSONObject output = new JSONObject();
        output.put("Region", COS_LOCATION);
        output.put("Bucket", COS_BUCKET_MEDIA);
        output.put("Object", outputPath);
        JSONObject request = new JSONObject();
        request.put("Input", input);
        request.put("Output", output);
        request.put("Time", 0);

        //请求media-1301855440.ci.ap-chongqing.myqcloud.com/snapshot 接口
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", auth);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(request.toJSONString(), headers);
        String response = null;
        try {
            response = restTemplate.exchange(CosConstant.URL_SNAPSHOT, HttpMethod.POST, requestEntity, String.class).getBody();
        } catch (RestClientException e) {
            logger.error(e.getMessage());
        }
        if (response.isEmpty()) {
            return CosConstant.URL_COS_ADDRESS + "error.jpg";
        } else {
            return CosConstant.URL_COS_ADDRESS + outputPath;
        }
    }

    /**
     * 获取视频处理服务 MpsClient
     */
    private static MpsClient getClient() {
        MpsClient mpsClient = null;
        try {
            Credential cred = new Credential(SECRET_ID, SECRET_KEY);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(ENDPOINT);
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            mpsClient = new MpsClient(cred, COS_LOCATION, clientProfile);
        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }
        return mpsClient;
    }

    /**
     * 获取数据万象认证Auth
     *
     * @param secretId
     * @param secretKey
     * @param path
     * @param httpMethodName
     * @return
     */
    public static String generateAuth(String secretId, String secretKey, String path, HttpMethodName httpMethodName) {
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        COSSigner signer = new COSSigner();
        //设置过期时间为1个小时
        Date expiredTime = new Date(System.currentTimeMillis() + 3600L * 1000L);
        //授权的签名
        return signer.buildAuthorizationStr(
                httpMethodName,
                path,
                cred,
                expiredTime
        );
    }

    public static Map<String,Object> supplementFrameUrl(String videoMD5){
        Map<String, Object> result = new HashMap<>();
        for (int i = 0; i <= 13; i++) {
            result.put("" + i + "", CosConstant.URL_COS_ADDRESS+"cutFrame/"+videoMD5+"/"+i+".jpg");
        }
        return result;
    }

    private static Map<String, Object> getFrameUrl(String outputPath) {
        Map<String, Object> result = new HashMap<>();
        for (int i = 0; i <= 13; i++) {
            result.put("" + i + "", CosConstant.URL_COS_ADDRESS + outputPath.replace("${Number}", "" + i + ""));
        }
        return result;
    }

    private static Map<String, Object> getErrorUrl() {
        Map<String, Object> result = new HashMap<>();
        result.put("0", CosConstant.URL_COS_ADDRESS + "error.jpg");
        return result;
    }
}
