package cn.com.ctop.common.module.service.impl;

import cn.com.ctop.common.module.entity.*;
import cn.com.ctop.common.module.mapper.MaterialAscriptionMapper;
import cn.com.ctop.common.module.mapper.MaterialInfoMapper;
import cn.com.ctop.common.module.mapper.MaterialParameterMapper;
import cn.com.ctop.common.module.mapper.MaterialTagMapper;
import cn.com.ctop.common.module.service.*;
import cn.com.ctop.common.module.utils.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.mts.model.v20140618.QueryJobListResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

/**
 * 素材信息
 *
 * @author jeecg-boot
 * @version V1.0
 * @date 2019-10-11
 */
@Slf4j
@Service
@Primary
public class MaterialInfoServiceImpl extends ServiceImpl<MaterialInfoMapper, MaterialInfo> implements IMaterialInfoService {
    private static ExecutorService uploadExecutorService = Executors.newFixedThreadPool(5);
    @Resource
    private IVideoWatermarkTemplateService videoWatermarkTemplateService;
    @Resource
    private IVideoWatermarkTaskService videoWatermarkTaskService;
    @Autowired
    private MaterialInfoMapper materialInfoMapper;
    @Autowired
    private MaterialParameterMapper materialParameterMapper;

    @Value("${oss.replace.replace-value}")
    private String replaceValue;
    @Value("${oss.replace.replace-old-value}")
    private String replaceOldValue;
    @Value("${oss.replace.download}")
    private String downloadUrl;

    @Override
    public void watermarkVideo(String materialId, Integer videoWatermarkTemplateId, String userId) {
        VideoWatermarkTemplate videoWatermarkTemplate = videoWatermarkTemplateService.getById(videoWatermarkTemplateId);
        MaterialInfo materialInfo = this.getById(materialId);
        MpsUtils mpsUtils = new MpsUtils();
        String path = materialInfo.getUrl().substring(materialInfo.getUrl().indexOf("/", 10) + 1, materialInfo.getUrl().length());
        String jobId = mpsUtils.videoWaterMark(path, videoWatermarkTemplate.getTemplatePath(), videoWatermarkTemplate.getTemplateId(), videoWatermarkTemplate.getHeight());
        QueryJobListResponse.Job job = MpsUtils.getJobStatus(jobId);
        VideoWatermarkTask videoWatermarkTask = new VideoWatermarkTask();
        videoWatermarkTask.setJobId(jobId);
        videoWatermarkTask.setUserId(userId);
        videoWatermarkTask.setStatus(job.getState());
        videoWatermarkTaskService.save(videoWatermarkTask);
        materialInfo.setWatermarkCode(jobId);
        this.updateById(materialInfo);
    }

    @Override
    public MaterialInfo getMaterialInfoByCodeAndProjectId(String code, Long projectId) {
        QueryWrapper<MaterialInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        queryWrapper.eq("project_id", projectId);
        queryWrapper.orderByDesc("id").last("limit 1");
        return this.getOne(queryWrapper);
    }


    @Override
    public MaterialInfo getMaterialInfoByCode(String code) {
        QueryWrapper<MaterialInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        queryWrapper.orderByDesc("id").last("limit 1");
        return this.getOne(queryWrapper);
    }

    @Override
    public Map<String, Object> checkMaterialInfo(String code, Long projectId) {
        Map<String, Object> result = new HashMap<>();
        MaterialInfo info = this.getMaterialInfoByCodeAndProjectId(code, projectId);
        if (null != info) {
            //文件已存在
            ResultMapUtils.setResultMap(result, StatusCode.FILE_HAS_UPLOAD.getCode());
            result.put("url", info.getUrl());
            return result;
        } else {
            //文件尚未上传
            ResultMapUtils.setResultMap(result, StatusCode.FILE_HAS_NOT_UPLOAD.getCode());
            return result;
        }
    }

    public boolean imgLocation(String fileName) throws IOException {
        String reg = "(mp4|flv|avi|rm|rmvb|wmv|MP4)";
        Pattern p = Pattern.compile(reg);
        return p.matcher(fileName).find();
    }

    public static void main(String[] args) {
        String reg = "(mp4|flv|avi|rm|rmvb|wmv)";
        Pattern p = Pattern.compile(reg);
    }

    @Autowired
    private MaterialAscriptionMapper materialAscriptionMapper;
    @Autowired
    private MaterialTagMapper materialTagMapper;

    @Override
    public Map<String, Object> insert(JSONObject jsonObject) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            String type = jsonObject.getString("type");
            if ("IMAGE".equals(type)) {
                JSONArray imageArr = jsonObject.getJSONArray("imageArr");
                if (!Check.isNull(imageArr)) {
                    jsonObject.remove("imageArr");
                    for (int i = 0; i < imageArr.size(); i++) {
                        String url = imageArr.getString(i);
                        if (!Check.isNull(url)) {
                            jsonObject.remove("code");
                            jsonObject.remove("materialName");
                            url = "https:" + url;
                            String localPath = LoadFileUtil.downLoadFromUrl(url, PropertiesUtils.getValue("kuaishou_config", "video_sava_path"));
                            String md5 = LoadFileUtil.getMD5(localPath);
                            jsonObject.put("code", md5);
                            LoadFileUtil.delFile(localPath);
                            String fileName = url.substring(url.lastIndexOf("/") + 1);
                            String fileNameStr = null;
                            if (!Check.isNull(fileName)) {
                                String[] split = fileName.split("-");
                                fileNameStr = split[0];
                            }
                            jsonObject.put("materialName", AesEncryptUtil.getUrlDecoderString(fileNameStr));
                            insertMaterialInfo(url, type, jsonObject);
                        }

                    }
                }

            } else {
                String url = "";
                if (!Check.isNull(jsonObject.getString("url"))) {
                    url = "https:" + jsonObject.getString("url");
                }
                insertMaterialInfo(url, type, jsonObject);
            }

            ResultMapUtils.setResultMap(resultMap, StatusCode.COMMON_SUCCESS.getCode());
        } catch (Exception e) {
            ResultMapUtils.setResultMap(resultMap, StatusCode.MATERIAL_UPLOAD_FAIL.getCode());
            e.printStackTrace();

        }


        return resultMap;
    }

    @Resource
    private IMaterialCutFrameService materialCutFrameService;

    private void insertMaterialInfo(String url, String type, JSONObject jsonObject) {
        MaterialInfo info = new MaterialInfo();
        Long projectId = jsonObject.getLong("projectId");
        String code = jsonObject.getString("code");
        info.setId(code + projectId);
        info.setCode(code);
        if (!Check.isNull(jsonObject.getString("watermarkUrl"))) {
            info.setWatermarkUrl(jsonObject.getString("watermarkUrl"));
        }
        info.setUrl(url);
        info.setUserId(jsonObject.getString("userId"));
        info.setProjectId(projectId);
        info.setWatermarkCode(jsonObject.getString("watermarkCode"));
        info.setStatus(0);
        info.setMaterialName(jsonObject.getString("materialName"));
        info.setWatermarkMaterialName(jsonObject.getString("watermarkMaterialName"));
        info.setMaterialDescribe(jsonObject.getString("materialDescribe"));
        info.setCreateTime(new Date());
        info.setUpdateTime(new Date());
        info.setType(type);
        this.save(info);
        Map<String, Object> deleteMap = new HashMap<>();
        deleteMap.put("material_id", info.getCode());
        JSONObject ascription = jsonObject.getJSONObject("ascription");
        if (!Check.isNull(ascription)) {
            MaterialAscription materialAscription = new MaterialAscription();
            materialAscription.setMaterialId(info.getId());
            // 剪辑人
            materialAscription.setClipId(ascription.getString("clipId"));
            // 拍摄人id
            materialAscription.setShotId(ascription.getString("shotId"));
            // 策划id
            materialAscription.setPlanId(ascription.getString("planId"));
            //平面id
            materialAscription.setPlaneId(ascription.getString("planeId"));
            materialAscriptionMapper.deleteByMap(deleteMap);
            int i = materialAscriptionMapper.insert(materialAscription);
            if (i > 0) {
                log.info("素材归属信息入库完成，MaterialId:{}", info.getId());
            }

        }

        JSONArray tag = jsonObject.getJSONArray("tag");
        if (!Check.isNull(tag)) {
            materialTagMapper.deleteByMap(deleteMap);
            for (int i = 0; i < tag.size(); i++) {
                String tagStr = tag.getString(i);
                if (!Check.isNull(tagStr)) {
                    MaterialTag materialTag = new MaterialTag();
                    materialTag.setMaterialId(info.getId());
                    materialTag.setTag(tagStr);
                    materialTagMapper.insert(materialTag);
                }
            }
        }

        getFile(info);

    }


    /**
     * 获取素材详细信息
     *
     * @param materialId
     * @return
     */

    //@Autowired
    //private MaterialInfoMapper materialInfoMapper;
    @Override
    public JSONObject getDetail(String materialId) {
        JSONObject json = new JSONObject();

        MaterialInfo materialInfo = this.getById(materialId);
        if (!Check.isNull(materialInfo.getAuditorId())) {
            String auditorName = materialInfoMapper.selectUserNameById(materialInfo.getAuditorId());
            json.put("auditorName", auditorName);
        } else {
            json.put("auditorName", "");
        }

        List<String> tagList = materialTagMapper.selectByMaterialId(materialInfo.getCode());
        if (!Check.isNull(tagList)) {
            json.put("tag", tagList);
        }
        QueryWrapper<MaterialParameter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("material_id", materialInfo.getCode());
        queryWrapper.orderByDesc("create_time");
        queryWrapper.last("limit 1");
        MaterialParameter materialParameter = materialParameterMapper.selectOne(queryWrapper);

        if (!Check.isNull(materialParameter)) {
            json.put("parameter", materialParameter);
        }

        JSONObject ascriptionJson = materialAscriptionMapper.selectByMaterialId(materialInfo.getCode());
        if (!Check.isNull(ascriptionJson)) {
            json.put("ascription", ascriptionJson);
        }

        return json;
    }

    /**
     * 工作台报表
     *
     * @param userId
     * @return
     */
    @Override
    public JSONObject report(String userId) {

        JSONObject json = new JSONObject();
        try {
            Map<String, Object> requestMap = new HashMap<>();
            requestMap.put("userId", userId);

            Integer totalCount = materialInfoMapper.selectCountByMap(requestMap);
            json.put("total", totalCount);

            requestMap.put("status", 0);
            Integer waitAudit = materialInfoMapper.selectCountByMap(requestMap);
            json.put("waitAudit", waitAudit);

            requestMap.put("status", 1);
            Integer passAudit = materialInfoMapper.selectCountByMap(requestMap);
            json.put("passAudit", passAudit);

            requestMap.put("status", 2);
            Integer refuseAudit = materialInfoMapper.selectCountByMap(requestMap);
            json.put("refuseAudit", refuseAudit);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    @Override
    public String getRoleCodeByUserId(String userId) {
        return materialInfoMapper.getRoleCodeByUserId(userId);
    }


    @Override
    public void getFile(MaterialInfo materialInfo) {
        uploadExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                /*try {*/
                log.info("获取素材基本信息，code:{}", materialInfo.getCode());
                if (!Check.isNull(materialInfo)) {
                    long l = System.currentTimeMillis();
                    String videoUrl = materialInfo.getUrl();
                    String url = videoUrl.replace(replaceOldValue, replaceValue);
                    log.info("replaceUrl:{}", url);
                    String localUrl = null;
                    it.sauronsoftware.jave.MultimediaInfo m = null;
                    FileInputStream fis = null;
                    try {
                        localUrl = LoadFileUtil.downLoadFromUrl(url, downloadUrl);

                        File file = new File(localUrl);
                        it.sauronsoftware.jave.Encoder encoder = new Encoder();
                        /*try {*/
                        m = encoder.getInfo(file);
                        long duration = m.getDuration();
                        long secondDuration = duration / 1000;
                        MaterialParameter materialParameter = new MaterialParameter();
                        materialParameter.setMaterialId(materialInfo.getCode());
                        // 视频秒数
                        materialParameter.setSecond(secondDuration);
                        // 视频格式
                        materialParameter.setFormat(m.getFormat());
                        // 视频宽
                        String width = String.valueOf(m.getVideo().getSize().getWidth());
                        materialParameter.setWidth(width);
                        // 视频高
                        String height = String.valueOf(m.getVideo().getSize().getHeight());
                        materialParameter.setHeight(height);


                        fis = new FileInputStream(file);
                        FileChannel fc = fis.getChannel();
                        BigDecimal fileSize = new BigDecimal(fc.size());
                        String size = fileSize.divide(new BigDecimal(1048576), 2, RoundingMode.HALF_UP) + "MB";
                        materialParameter.setSize(size);
                        materialParameter.setUpdateTime(new Date());

                        Map<String, Object> deleteMap = new HashMap<>();
                        deleteMap.put("material_id", materialInfo.getId());
                        materialParameterMapper.deleteByMap(deleteMap);
                        int insert = materialParameterMapper.insert(materialParameter);
                        if (insert > 0) {
                            log.info("素材基本信息入库完成，用时：{} s", (System.currentTimeMillis() - l) / 1000);
                        }
                        Thread thread = new Thread() {
                            @Override
                            public void run() {
                                try {
                                    log.info("开始抽帧");
                                    materialCutFrameService.getCutFrame(videoUrl, materialInfo.getCode(), secondDuration, height, width);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        };
                        thread.start();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (EncoderException e) {
                        e.printStackTrace();

                    } finally {
                        try {
                            if (fis != null) {
                                fis.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                    /* */

                       /* } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            file.delete();
                        }*/
                }
                /*} catch (Exception e) {
                    e.printStackTrace();
                }*/
            }


        });
    }

    @Override
    public void setExcellent(String code, Integer excellent) {
        MaterialInfo info = this.getMaterialInfoByCode(code);
        info.setExcellent(excellent);
        this.updateById(info);
    }

    @Override
    public Integer getKuaishouUpVideoCount(String code) {
        return materialInfoMapper.getKuaishouUpVideoCount(code);
    }

    @Override
    public Integer getToutiaoUpVideoCount(String code) {
        return materialInfoMapper.getToutiaoUpVideoCount(code);
    }


    /**
     * 获取素材概括信息
     *
     * @param code
     * @return
     */
    @Override
    public JSONObject getGeneralizationInfo(String code) {
        return materialInfoMapper.getGeneralizationInfo(code);
    }


    @Autowired
    private IMaterialImageInfoService materialImageInfoService;

    /**
     * 素材库关联上传素材 1
     *
     * @param json
     * @return
     */
    @Override
    public Map<String, Object> correlationUpload(JSONObject json) {
        String userId = json.getString("userId");
        Map<String, Object> resultMap = new HashMap<>();
        try {
            String type = json.getString("type");
            String url = "";
            if (!Check.isNull(json.getString("url"))) {
                url = "https:" + json.getString("url");
            }

            MaterialInfo info = new MaterialInfo();
            Long projectId = json.getLong("projectId");
            String code = json.getString("code");
            info.setId(code + projectId);
            info.setCode(code);
            if (!Check.isNull(json.getString("watermarkUrl"))) {
                info.setWatermarkUrl(json.getString("watermarkUrl"));
            }
            info.setUrl(url);
            info.setUserId(userId);
            info.setProjectId(projectId);
            info.setWatermarkCode(json.getString("watermarkCode"));
            info.setStatus(0);
            info.setMaterialName(json.getString("materialName"));
            info.setWatermarkMaterialName(json.getString("watermarkMaterialName"));
            info.setMaterialDescribe(json.getString("materialDescribe"));
            info.setCreateTime(new Date());
            info.setUpdateTime(new Date());
            info.setType(type);
            this.save(info);

            JSONArray imageArr = json.getJSONArray("imageArr");
            if (!Check.isNull(imageArr)) {
                JSONObject imageJson = new JSONObject();
                imageJson.put("videoId", info.getCode());
                imageJson.put("userId", userId);
                imageJson.put("projectId", projectId);
                imageJson.put("imageArr", imageArr);
                materialImageInfoService.insertImage(imageJson);
            }

            Map<String, Object> deleteMap = new HashMap<>();
            deleteMap.put("material_id", info.getCode());
            JSONObject ascription = json.getJSONObject("ascription");
            if (!Check.isNull(ascription)) {
                MaterialAscription materialAscription = new MaterialAscription();
                materialAscription.setMaterialId(info.getCode());
                // 剪辑人
                materialAscription.setClipId(ascription.getString("clipId"));
                // 拍摄人id
                materialAscription.setShotId(ascription.getString("shotId"));
                // 策划id
                materialAscription.setPlanId(ascription.getString("planId"));
                //平面id
                materialAscription.setPlaneId(ascription.getString("planeId"));
                materialAscriptionMapper.deleteByMap(deleteMap);
                int i = materialAscriptionMapper.insert(materialAscription);
                if (i > 0) {
                    log.info("素材归属信息入库完成，MaterialId:{}", info.getId());
                }

            }

            JSONArray tag = json.getJSONArray("tag");
            if (!Check.isNull(tag)) {
                materialTagMapper.deleteByMap(deleteMap);
                for (int i = 0; i < tag.size(); i++) {
                    String tagStr = tag.getString(i);
                    if (!Check.isNull(tagStr)) {
                        MaterialTag materialTag = new MaterialTag();
                        materialTag.setMaterialId(info.getCode());
                        materialTag.setTag(tagStr);
                        materialTagMapper.insert(materialTag);
                    }
                }
            }

            getFile(info);

            ResultMapUtils.setResultMap(resultMap, StatusCode.COMMON_SUCCESS.getCode());
        } catch (Exception e) {
            ResultMapUtils.setResultMap(resultMap, StatusCode.MATERIAL_UPLOAD_FAIL.getCode());
            e.printStackTrace();

        }


        return resultMap;


    }

    @Override
    public Map<String, Object> insertImage(JSONObject imageJson) {
        Map<String, Object> resultMap = new HashMap<>();
        ResultMapUtils.setResultMap(resultMap, StatusCode.COMMON_SUCCESS.getCode());
        try {
            materialImageInfoService.insertImage(imageJson);
        } catch (Exception e) {
            ResultMapUtils.setResultMap(resultMap, StatusCode.MATERIAL_UPLOAD_FAIL.getCode());
            e.printStackTrace();
        }

        return resultMap;
    }

    public List<String> getEffiCode() {
        return materialInfoMapper.getEffiSignature();
    }


    public List<MaterialInfo> effiMaterialInfo() {
        List<MaterialInfo> materialInfoList = new ArrayList<>();
        List<String> effiSignatureList = materialInfoMapper.getEffiSignature();
        for (String code : effiSignatureList) {
            MaterialInfo materialInfo = materialInfoMapper.getMaterialInfoByCode(code);

            if (materialInfo == null) {
                continue;
            }
            //判断是否已经同步到快手平台
            Integer kuaishouMaterialUpCount = materialInfoMapper.getKuaishouUpVideoCount(code);
            if (kuaishouMaterialUpCount > 0) {
                materialInfo.setKuaishouVideoIsUp(1);
            } else {
                materialInfo.setKuaishouVideoIsUp(0);
            }
            //判断是否已经同步到抖音平台
            Integer toutiaoMaterialUpCount = materialInfoMapper.getToutiaoUpVideoCount(code);
            if (toutiaoMaterialUpCount > 0) {
                materialInfo.setToutiaoVideoIsUp(1);
            } else {
                materialInfo.setToutiaoVideoIsUp(0);
            }
            materialInfoList.add(materialInfo);
        }

        return materialInfoList;
    }

    @Override
    public List<MaterialInfo> getListByDate(String startDate, String endDate) {
        return materialInfoMapper.getListByDate(startDate, endDate);
    }
}





