package com.fdkankan.scene.service.impl;

import static com.fdkankan.push.PushMessageConfig.ANDROID_KEY;
import static com.fdkankan.push.PushMessageConfig.ANDROID_KEY_Z;
import static com.fdkankan.push.PushMessageConfig.ANDROID_SECRET;
import static com.fdkankan.push.PushMessageConfig.ANDROID_SECRET_Z;
import static com.fdkankan.push.PushMessageConfig.IOS_KEY;
import static com.fdkankan.push.PushMessageConfig.IOS_KEY_Z;
import static com.fdkankan.push.PushMessageConfig.IOS_SECRET;
import static com.fdkankan.push.PushMessageConfig.IOS_SECRET_Z;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fdkankan.common.constant.BuildStatus;
import com.fdkankan.common.constant.ConstantFilePath;
import com.fdkankan.common.constant.ConstantUrl;
import com.fdkankan.common.constant.ExpiredStatus;
import com.fdkankan.common.constant.PayStatus;
import com.fdkankan.common.constant.SceneFrom;
import com.fdkankan.common.constant.SceneResolution;
import com.fdkankan.common.constant.SceneSource;
import com.fdkankan.common.constant.SceneStatus;
import com.fdkankan.common.constant.ServerCode;
import com.fdkankan.common.constant.UploadFilePath;
import com.fdkankan.common.response.ResultData;
import com.fdkankan.common.util.FileUtil;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.common.util.MatrixToImageWriterUtil;
import com.fdkankan.common.util.SceneUtil;
import com.fdkankan.fyun.constant.StorageType;
import com.fdkankan.fyun.oss.UploadToOssUtil;
import com.fdkankan.platform.api.dto.CameraDetail;
import com.fdkankan.platform.api.dto.UserIncrement;
import com.fdkankan.platform.api.feign.PlatformGoodsClient;
import com.fdkankan.platform.api.feign.PlatformUserClient;
import com.fdkankan.push.PushMessageConfig;
import com.fdkankan.push.PushMsgUtil;
import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
import com.fdkankan.redis.constant.RedisKey;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.scene.bean.SceneJsonBean;
import com.fdkankan.scene.entity.SceneEditControls;
import com.fdkankan.scene.entity.SceneEditInfo;
import com.fdkankan.scene.entity.SceneEditInfoExt;
import com.fdkankan.scene.entity.SceneFileBuild;
import com.fdkankan.scene.entity.ScenePlus;
import com.fdkankan.scene.entity.ScenePlusExt;
import com.fdkankan.scene.entity.ScenePro;
import com.fdkankan.scene.entity.SceneProExt;
import com.fdkankan.scene.service.IBuildSceneDTService;
import com.fdkankan.scene.service.IBuildScenePostService;
import com.fdkankan.scene.service.IBuildScenePreService;
import com.fdkankan.scene.service.ISceneEditControlsService;
import com.fdkankan.scene.service.ISceneEditInfoExtService;
import com.fdkankan.scene.service.ISceneEditInfoService;
import com.fdkankan.scene.service.ISceneFileBuildService;
import com.fdkankan.scene.service.IScenePlusExtService;
import com.fdkankan.scene.service.IScenePlusService;
import com.fdkankan.scene.service.ISceneProExtService;
import com.fdkankan.scene.service.ISceneProService;
import com.fdkankan.scene.service.ISceneService;
import com.fdkankan.scene.vo.SceneEditControlsVO;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * <p>
 * TODO
 * </p>
 *
 * @author dengsixing
 * @since 2022/4/20
 **/
@Slf4j
@Service
public class BuildScenePostServiceImpl implements IBuildScenePostService {

    @Value("${main.url}")
    private String mainUrl;
    @Value("${scene.pro.url}")
    private String sceneProUrl;
    @Value("${scene.pro.new.url}")
    private String sceneProNewUrl;
    @Value("${upload.type}")
    private String ossType;
    @Value("${oss.prefix.ali}")
    private String prefixAli;

    @Autowired
    ISceneService sceneService;
    @Autowired
    ISceneFileBuildService sceneFileBuildService;
    @Autowired
    ISceneProService sceneProService;
    @Autowired
    ISceneProExtService sceneProExtService;
    @Autowired
    PlatformGoodsClient platformGoodsClient;
    @Autowired
    PlatformUserClient platformUserClient;
    @Autowired
    ISceneEditInfoService sceneEditInfoService;
    @Autowired
    ISceneEditControlsService sceneEditControlsService;
    @Autowired
    UploadToOssUtil uploadToOssUtil;
//    @Autowired
//    IBuildScenePreService buildScenePreService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    IScenePlusService scenePlusService;
    @Autowired
    IScenePlusExtService scenePlusExtService;
    @Autowired
    IBuildSceneDTService buildSceneDTService;
    @Autowired
    ISceneEditInfoExtService sceneEditInfoExtService;

    @Override
    public void buildScenePost(BuildSceneResultMqMessage message) {
        Integer cameraType = Integer.parseInt(message.getCameraType());
        String sceneCode = message.getSceneCode();
        String fileId = message.getFileId();
        Integer payStatus = message.getPayStatus();
        Long computeTime = message.getComputeTime();
        Boolean buildSuccess = message.getBuildSuccess();
        Integer videoVersion = message.getVideoVersion();

        Map<String, String> uploadFiles = message.getUploadFiles();
        String path = message.getPath();
        Integer pushChannel = message.getPushChannel();
        String pushToken = message.getPushToken();
        String prefix = message.getPrefix();
        try {
            if(!buildSuccess){//建模失败，修改状态为失败状态
                log.info("建模失败，修改状态为失败状态");
                // TODO: 2022/3/21 plus版本稳定后删除------------------------start
                sceneService.updateStatus(sceneCode, SceneStatus.FAILD.code());
                sceneProService.updateStatus(sceneCode, SceneStatus.FAILD.code());
                // TODO: 2022/3/21 plus版本稳定后删除------------------------send

                scenePlusService.update(
                    new LambdaUpdateWrapper<ScenePlus>()
                        .set(ScenePlus::getSceneStatus, SceneStatus.FAILD.code())
                        .eq(ScenePlus::getNum, sceneCode));

                SceneFileBuild sceneFileBuild = sceneFileBuildService.findByFileId(fileId);
                if(Objects.nonNull(sceneFileBuild)){
                    sceneFileBuild.setBuildStatus(BuildStatus.fail.code());
                    sceneFileBuildService.updateById(sceneFileBuild);
                }
                return;
            }

            //建模成功走以下逻辑
            log.info("cameraType:{}",cameraType);

            //计算场景消耗磁盘空间
            long space = this.calUseSpace(uploadFiles);

            if(cameraType < 3){
                // TODO: 2022/3/21 plus版本稳定后删除------------------------start
                sceneService.updateTime(sceneCode, space, payStatus);
                // TODO: 2022/3/21 plus版本稳定后删除------------------------send

                this.updateDb4Sm(sceneCode, space);

                uploadToOssUtil.uploadMulFiles(uploadFiles);
                return;
            }

            //读取计算结果文件生成videosJson
            JSONObject videosJson = this.getVideosJson(path, videoVersion, sceneCode, cameraType);

            //写入数据库
            // TODO: 2022/3/21 plus版本稳定后删除------------------------start
            ScenePro scenePro = this.updateDbPro(sceneCode, space, payStatus, videosJson.toJSONString(), computeTime, fileId);
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
            // TODO: 2022/3/21 plus版本稳定后删除------------------------send
            ScenePlus scenePlus = this.updateDbPlus(sceneCode, space, payStatus, videosJson.toJSONString(), computeTime, fileId);
            ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());

            //变更容量，arrearCap为true时，代表容量不足
            boolean arrearCap = this.updateSpace(scenePlus.getCameraId(), space, scenePlus.getId(), scenePro.getId());

            //如果相机容量不足，需要把场景的paystatus改为容量不足状态
            this.sealScene(arrearCap, scenePlus.getId(), scenePro.getId());

            Object[] editInfoArr = this.updateEditInfo(scenePro, scenePlus);
            SceneEditInfo sceneEditInfo = (SceneEditInfo)editInfoArr[0];
            SceneEditInfoExt sceneEditInfoExt = (SceneEditInfoExt)editInfoArr[1];
            SceneEditControls sceneEditControls = (SceneEditControls)editInfoArr[2];

            String sceneUrl = mainUrl + "/" + sceneProNewUrl;
            String outPathZh = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+sceneCode+".png";
            String outPathEn = ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+sceneCode+"_en.png";
            //生成新的分享的二维码-中文版本
            MatrixToImageWriterUtil.createQRCode(sceneUrl + sceneCode, outPathZh, false,null);
            //生成新的分享的二维码-英文版本
            MatrixToImageWriterUtil.createQRCode(sceneUrl + sceneCode + "&lang=en", outPathEn, false, null);
            //上传二维码
            uploadToOssUtil.upload(outPathZh, String.format(UploadFilePath.DOWNLOADS_QRCODE, sceneCode) + sceneCode + ".png");
            uploadToOssUtil.upload(outPathEn, String.format(UploadFilePath.DOWNLOADS_QRCODE, sceneCode) + sceneCode + "_en.png");

            Map<String, String> newUploadFiles = this.uploadFileMapHandler(sceneCode, cameraType, uploadFiles);

            // TODO: 2022/5/26 下载全景图采用打包本地文件的方式，这里应该是不需要上传到oss了，暂时保留代码并注释掉------start
            //上传计算结果中的caches/images和caches/videos
//            this.uploadCaches(sceneCode, uploadFiles, path);
            // TODO: 2022/5/26 下载全景图采用打包本地文件的方式，这里应该是不需要上传到oss了，暂时保留代码并注释掉------end

            //上传全景图俯视图
            this.uploadFloorCad(path, sceneCode, newUploadFiles);

            //上传文件
            uploadToOssUtil.uploadMulFiles(newUploadFiles);
            // TODO: 2022/3/11 同时上传一份到旧版本的目录，用于过渡期使用，待重构版本稳定后删除
            uploadToOssUtil.uploadMulFiles(uploadFiles);

            //拷贝部分文件到编辑目录，用于用户编辑
            this.copyToEditDir(sceneCode);

//            //上传日志文件
//            buildScenePreService.uploadLogFile(sceneCode, sceneProExt.getDataSource());

            //写scene.json
            this.writeSceneJson(sceneCode, videosJson,
                sceneEditInfo, sceneEditInfoExt, sceneEditControls, scenePlus, scenePlusExt, arrearCap);

            //计算成功，发短信
            this.sendSms(pushChannel,pushToken, cameraType, scenePro.getSceneName(), scenePro.getWebSite());

            log.info("场景计算结果处理结束，场景码：{}", message.getSceneCode());

        }catch (Exception e){
            log.error("场景计算结果处理出错", e);
            //发送钉钉
            String serverPath = message.getPath().substring(0,message.getPath().lastIndexOf("/")+1).concat(prefix);
//            buildSceneDTService.handFail("场景计算结果处理出错", serverPath, sceneCode, BuildScenePreServiceImpl.hostName, BuildScenePreServiceImpl.contentExt);
        }
    }

    private void uploadFloorCad(String path, String num, Map<String, String> uploadFiles){

        //户型图上传
        String  userEditPath = UploadFilePath.USER_EDIT_PATH + "floor-cad-%s.%s";
        String  userViewPath = UploadFilePath.USER_VIEW_PATH + "floor-cad-%s.%s";
        String floorCadPath = path + "/results/floorplan_cad";
        List<String> floorCadList = FileUtil.getFileList(floorCadPath);
        if(CollUtil.isNotEmpty(floorCadList)){
            floorCadList.stream().forEach(str->{
                String substring = str.substring(str.lastIndexOf(File.separator) + 1);
                String[] arr = substring.split("floor");
                String[] arr2 = arr[1].split("\\.");
                uploadFiles.put(str, String.format(userEditPath, num, arr2[0], arr2[1]));
                uploadFiles.put(str, String.format(userViewPath, num, arr2[0], arr2[1]));
            });
        }

    }

    private void writeSceneJson(String num, JSONObject videosJson, SceneEditInfo sceneEditInfo,SceneEditInfoExt sceneEditInfoExt,
        SceneEditControls sceneEditControls, ScenePlus scenePlus, ScenePlusExt scenePlusExt, boolean arrearCap)  throws Exception{
        String sceneJsonKey = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "scene.json";
        boolean exist = uploadToOssUtil.existKey(sceneJsonKey);
        //如果云端没有scene.json文件，生成一份
        if(!exist){
            SceneJsonBean sceneJson = new SceneJsonBean();
            BeanUtil.copyProperties(sceneEditInfoExt, sceneJson);
            BeanUtil.copyProperties(sceneEditInfo, sceneJson);
            SceneEditControlsVO sceneEditControlsVO = BeanUtil.copyProperties(sceneEditControls, SceneEditControlsVO.class);
            sceneJson.setControls(sceneEditControlsVO);
            sceneJson.setNum(num);
            sceneJson.setCreateTime(scenePlus.getCreateTime());
            sceneJson.setSceneResolution(scenePlusExt.getSceneResolution());
            sceneJson.setSceneFrom(scenePlusExt.getSceneFrom());
            sceneJson.setVideos(JSON.toJSONString(videosJson));
            if(arrearCap) {
                sceneJson.setPayStatus(PayStatus.NO_CAPACITY.code());
            }

            String sceneJsonStr = JSON.toJSONString(sceneJson);
            //上传sceneJson文件
            uploadToOssUtil.upload(sceneJsonStr.getBytes(), sceneJsonKey);
            //scenejson写入缓存
            redisUtil.set(String.format(RedisKey.SCENE_JSON, num), sceneJsonStr);
        }

        // TODO: 2022/4/21 plus版本稳定后删除------------------------------------------start
        String localSceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, num);
        String localSceneJson = FileUtils.readFile(localSceneJsonPath);
        if(StrUtil.isNotEmpty(localSceneJson)){
            JSONObject sceneJsonObject = JSON.parseObject(localSceneJson);
            sceneJsonObject.put("videos", JSON.toJSONString(videosJson));
            if(arrearCap) {
                sceneJsonObject.put("payStatus", PayStatus.NO_CAPACITY.code());
            }
            FileUtils.writeFile(localSceneJsonPath, sceneJsonObject.toJSONString());
        }
        // TODO: 2022/4/21 plus版本稳定后删除------------------------------------------end

    }

    private void sendSms(Integer pushChannel, String pushToken, int cameraType, String sceneName, String webSite){
        log.info("推送消息，渠道是 {}, 手机token是 {}", pushChannel, pushToken);
        if(Objects.isNull(pushChannel) && StrUtil.isBlank(pushToken))
            return;

        try{
            if(StorageType.AWS.code().equals(ossType)){
                PushMsgUtil
                    .googlePushMsg(ConstantFilePath.BASE_PATH + "/refreshToken.json", pushToken,
                        sceneName + "计算完成", "您上传的" + sceneName + "计算完成，点击查看", webSite);
                return;
            }

            PushMessageConfig demo = null;
            if(pushChannel == 0){
                if(cameraType == 10 || cameraType == 13){
                    //ios
                    log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY_Z, IOS_SECRET_Z);
                    demo = new PushMessageConfig(IOS_KEY_Z, IOS_SECRET_Z);
                    demo.sendIOSUnicast(pushToken,  "四维看看Minion",
                        sceneName + "计算完成", "您上传的" + sceneName + "计算完成，点击查看", webSite);
                }else {
                    //ios
                    log.info("IOS_KEY:{}, IOS_SECRET:{}", IOS_KEY, IOS_SECRET);
                    demo = new PushMessageConfig(IOS_KEY, IOS_SECRET);
                    demo.sendIOSUnicast(pushToken, "四维看看Pro",
                        sceneName + "计算完成", "您上传的" + sceneName + "计算完成，点击查看", webSite);
                }
            }else {
                if(cameraType == 10 || cameraType == 13){
                    //ios
                    //安卓
                    log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY_Z, ANDROID_SECRET_Z);
                    demo = new PushMessageConfig(ANDROID_KEY_Z, ANDROID_SECRET_Z);
                    demo.sendAndroidUnicast2(pushToken, "四维看看Minion",
                        sceneName + "计算完成", "您上传的" + sceneName + "计算完成，点击查看", webSite);
                }else {
                    //安卓
                    log.info("ANDROID_KEY:{}, ANDROID_SECRET:{}", ANDROID_KEY, ANDROID_SECRET);
                    demo = new PushMessageConfig(ANDROID_KEY, ANDROID_SECRET);
                    demo.sendAndroidUnicast(pushToken, "四维看看Pro",
                        sceneName + "计算完成", "您上传的" + sceneName + "计算完成，点击查看", webSite);
                }
            }
            log.info("消息推送结束！");
        }catch (Exception e){
            log.error("推送消息失败：", e);
        }
    }

    private void copyToEditDir(String num) throws IOException {

        String editImagesPath = String.format(UploadFilePath.IMG_EDIT_PATH, num);
        String viewImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);

        String editDataPath = String.format(UploadFilePath.DATA_EDIT_PATH, num);
        String viewDataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);

        Map<String, String> map = new HashMap<>();
        map.put(editImagesPath + "vision.modeldata", viewImagesPath + "vision.modeldata");
        map.put(editImagesPath + "vision2.modeldata", viewImagesPath + "vision2.modeldata");
        map.put(editDataPath + "floorplan_cad.json", viewDataPath + "floorplan_cad.json");

        for (Entry<String, String> entry : map.entrySet()) {
            uploadToOssUtil.copyFiles(entry.getValue(), entry.getKey());
        }
    }


    private void uploadCaches(String num, Map<String,String> map, String path){

        String sceneNumPath = String.format("scene/%s", num);

        List<String> ossImagesList = uploadToOssUtil.listKeys(String.format(UploadFilePath.IMG_CACHES_PATH, num));
        if(CollUtil.isNotEmpty(ossImagesList)){
            ossImagesList.parallelStream().forEach(key->{
                try {
                    uploadToOssUtil.delete(key);
                } catch (IOException e) {
                    log.error("删除全景图缓存失败，num:{},key:{}", num, key);
                }
            });
        }
        String visionPath = path + "/results/vision.txt";
        List<String> panoramaImageList = SceneUtil.getPanoramaImageList(visionPath);

        List<String> imagesList = FileUtil.getFileList(path + "/caches/images");
        log.info("caches/images_path:{}", path + "/caches/images");
        if(CollUtil.isNotEmpty(imagesList)){
            log.info("上传的caches/images文件列表：{}", imagesList.toString());
            imagesList.stream().forEach(str -> {
                String filePath = str.substring(str.lastIndexOf(File.separator) + 1);
                if(panoramaImageList.contains(filePath)){
                    map.put(str, str.replace(path, sceneNumPath));
                }
            });
        }

        List<String> ossVideosList = uploadToOssUtil.listKeys(String.format(UploadFilePath.VIDEOS_CACHES_PATH, num));
        if(CollUtil.isNotEmpty(ossVideosList)){
            ossVideosList.parallelStream().forEach(key->{
                try {
                    uploadToOssUtil.delete(key);
                } catch (IOException e) {
                    log.error("删除球幕视频缓存失败，num:{},key:{}", num, key);
                }
            });
        }
        List<String> videosList = FileUtil.getFileList(path + "/caches/videos");
        if(CollUtil.isNotEmpty(videosList)){
            log.info("上传的caches/videos文件列表：{}", videosList.toString());
            videosList.stream().forEach(str -> map.put(str, str.replace(path, sceneNumPath)));
        }
    }

    private Map<String, String> uploadFileMapHandler(String num, int cameraType, Map<String, String> map) {
        if(CollUtil.isEmpty(map)){
            return null;
        }

        String dataPath = String.format("data/data%s/", num);
        String imagePath = String.format("images/images%s/", num);
        String videoPath = String.format("video/video%s/", num);

        String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
        String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
        String videosViewPath = String.format(UploadFilePath.VIDEOS_VIEW_PATH, num);

        Map<String, String> newMap = new HashMap<>();
        for (String key : map.keySet()) {
            String value = map.get(key);
            if(value.contains(dataPath)){
                newMap.put(key, value.replace(dataPath, dataViewPath));
            }
            if(value.contains(imagePath)){
                newMap.put(key, value.replace(imagePath, imgViewPath));
            }
            if(value.contains(videoPath)){
                newMap.put(key, value.replace(videoPath, videosViewPath));
            }
        }
        return newMap;
    }

    private JSONObject getVideosJson(String path, Integer videoVersion, String projectNum, int cameraType) throws Exception {
        //读取videos_hdr_param.json, 保存点位视频的value
        Map<String, Object> videoMap = new HashMap<>();
        String videosHdr = FileUtils.readFile(path + File.separator + "results/videos/videos_hdr_param.json");
        JSONArray videoArray = null;
        if(StringUtils.isNotEmpty(videosHdr)){
            videoArray = JSONObject.parseObject(videosHdr).getJSONArray("hdr_param");
        }
        if(videoArray != null){
            for(int i = 0, len = videoArray.size(); i < len; i++) {
                videoMap.put(videoArray.getJSONObject(i).getString("name"), videoArray.getJSONObject(i).getString("value"));
                if(videoArray.getJSONObject(i).containsKey("fov")){
                    videoMap.put(videoArray.getJSONObject(i).getString("name") + "_fov", videoArray.getJSONObject(i).getString("fov"));
                }
            }
        }

        //获取upload中的video视频名称
        String uploadData = FileUtils.readFile(path + File.separator + "results" +File.separator+"upload.json");
        JSONObject uploadJson = null;
        JSONArray array = null;
        if(uploadData!=null) {
            uploadJson = JSONObject.parseObject(uploadData);
            array = uploadJson.getJSONArray("upload");
        }
        JSONObject fileJson = null;
        String fileName = "";

        //计算ts文件的大小，并拼接成json格式
        JSONArray jsonArray = new JSONArray();
        JSONObject videoJson = null;
        JSONObject videosJson = new JSONObject();
        long videoSize = 0L;
        for(int i = 0, len = array.size(); i < len; i++) {
            fileJson = array.getJSONObject(i);
            fileName = fileJson.getString("file");
            if(fileJson.getIntValue("clazz") == 11 && fileName.contains(".mp4") && !fileName.contains("-ios.mp4")){
                videoJson = new JSONObject();
                videoJson.put("id", fileName.substring(
                    0, fileName.lastIndexOf(".")).replace("videos/", ""));

                //如果ts文件存在，就计算ts大小
                if(new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).exists()){
                    videoSize = new File(path + File.separator + "results" +File.separator+ fileName.replace(".mp4", ".ts")).length();
                    videoJson.put("tsSize", videoSize);
                }
                if(videoMap.containsKey(videoJson.get("id"))){
                    videoJson.put("value", videoMap.get(videoJson.get("id")));
                }
                if(videoMap.containsKey(videoJson.get("id") + "_fov")){
                    videoJson.put("blend_fov", videoMap.get(videoJson.get("id") + "_fov"));
                }else {
                    videoJson.put("blend_fov", 7);
                }
                jsonArray.add(videoJson);
            }
        }

        videosJson.put("data", jsonArray);
        if(Objects.nonNull(videoVersion) && videoVersion >= 4){
            videosJson.put("version", 3);
            if(StorageType.OSS.code().equals(ossType)){
                videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up.xml");
            }
            if(StorageType.AWS.code().equals(ossType)){
                videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up.xml");
            }
            if(cameraType == 13){
                //转台相机
                videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
            }
        }else {
            videosJson.put("version", 1);
            if("oss".equals(ossType)){
                videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/Up2.xml");
            }
            if("aws".equals(ossType)){
                videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/Up2.xml");
            }

            if(cameraType == 13){
                //转台相机
                videosJson.put("upPath", videosJson.getString("upPath").replace(".xml", ".txt"));
            }
        }

        if(cameraType == 5 || cameraType == 6){
            videosJson.put("version", 1);
            if("oss".equals(ossType)){
                videosJson.put("upPath", prefixAli + "data/data" + projectNum + "/stitch_params.txt");
            }
            if("aws".equals(ossType)){
                videosJson.put("upPath", ConstantUrl.PREFIX_AWS + "data/data" + projectNum + "/stitch_params.txt");
            }
        }

        return videosJson;
    }

    private Long calUseSpace(Map<String, String> uploadFile) {
        File spaceFile = null;
        long space = 0L;
        for (String key : uploadFile.keySet()) {
            spaceFile = new File(key);
            if(spaceFile.exists()){
                space += spaceFile.length();
            }
        }
        return space;
    }

    private void sealScene(boolean arrearCap, Long scenePlusId, Long sceneProId){
        if(!arrearCap){
            return;
        }
        scenePlusService.update(
            new LambdaUpdateWrapper<ScenePlus>()
                .set(ScenePlus::getPayStatus, PayStatus.NO_CAPACITY.code())
                .eq(ScenePlus::getId, scenePlusId));


        // TODO: 2022/3/22 plus版本稳定后删除---------------------------start
        sceneProService.update(
            new LambdaUpdateWrapper<ScenePro>()
                .set(ScenePro::getPayStatus, PayStatus.NO_CAPACITY.code())
                .eq(ScenePro::getId, sceneProId));
        // TODO: 2022/3/22 plus版本稳定后删除---------------------------end
    }

    /**
     * <p>
     双目场景更新数据库
     * </p>
     * @author dengsixing
     * @date 2022/3/21
     * @param num
     * @param space
     **/
    private void updateDb4Sm(String num, long space){
        List<ScenePlus> ScenePlusList = scenePlusService.list(
            new LambdaQueryWrapper<ScenePlus>()
                .select(ScenePlus::getId)
                .eq(ScenePlus::getNum, num));

        if(CollUtil.isNotEmpty(ScenePlusList))
            return ;
        List<Long> sceneIds = ScenePlusList.stream().map(scene -> {
            return scene.getId();
        }).collect(Collectors.toList());

        //更新场景创建时间
        scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>()
            .in(ScenePlus::getId, sceneIds)
            .set(ScenePlus::getCreateTime, Calendar.getInstance().getTime())
            .set(ScenePlus::getSceneStatus, SceneStatus.NO_DISPLAY.code()));

        //更新使用容量
        scenePlusExtService.update(
            new LambdaUpdateWrapper<ScenePlusExt>()
                .in(ScenePlusExt::getPlusId, sceneIds)
                .set(ScenePlusExt::getSpace, space));
    }

    private ScenePro updateDbPro(String sceneCode, Long space, Integer payStatus, String videosJson, Long computeTime, String fileId) throws Exception{
        ScenePro scenePro = sceneProService.findBySceneNum(sceneCode);

        sceneProService.updateTime(sceneCode, space, payStatus, videosJson, computeTime);
        SceneFileBuild sceneFileBuild = sceneFileBuildService.findByFileId(fileId);
        if(sceneFileBuild != null){
            sceneFileBuild.setBuildStatus(BuildStatus.success.code());
            sceneFileBuildService.updateById(sceneFileBuild);
        }

        if(Objects.nonNull(scenePro)){
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
            SceneSource sceneSource = SceneSource.get(sceneProExt.getSceneSource());
            switch (sceneSource){
                case BM:
                    sceneProExt.setSceneResolution(SceneResolution.TILES_2K.code());
                    sceneProExt.setSceneFrom(SceneFrom.PRO.code());
                    break;
                case SM:
                    sceneProExt.setSceneResolution(SceneResolution.TILES_1K.code());
                    sceneProExt.setSceneFrom(SceneFrom.LITE.code());
                    break;
                case ZT:
                    sceneProExt.setSceneResolution(SceneResolution.TILES_4K.code());
                    sceneProExt.setSceneFrom(SceneFrom.MINION.code());
                    break;
                case JG:
                    sceneProExt.setSceneResolution(SceneResolution.TILES_4K.code());
                    sceneProExt.setSceneFrom(SceneFrom.LASER.code());
                    break;
            }
            sceneProExtService.updateById(sceneProExt);

        }

        return scenePro;
    }

    private ScenePlus updateDbPlus(String num, Long space, Integer payStatus, String videosJson, Long computeTime, String fileId) throws Exception{
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
        List<ScenePlus> list = scenePlusService.list(
            new LambdaQueryWrapper<ScenePlus>()
                .select(ScenePlus::getId)
                .eq(ScenePlus::getNum, num));
        if(scenePlus == null || CollUtil.isEmpty(list))
            return null;

        //修改场景状态 空间 支付状态 计算时间
        List<Long> scenePlusIds = list.stream().map(plus -> {
            return plus.getId();
        }).collect(Collectors.toList());

        scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>()
            .in(ScenePlus::getId, scenePlusIds)
            .set(ScenePlus::getSceneStatus, SceneStatus.NO_DISPLAY.code())
            .set(ScenePlus::getCreateTime, Calendar.getInstance().getTime())
            .set(ScenePlus::getPayStatus, payStatus));

        scenePlusExtService.update(new LambdaUpdateWrapper<ScenePlusExt>()
            .in(ScenePlusExt::getPlusId, scenePlusIds)
            .set(ScenePlusExt::getSpace, space)
            .set(ScenePlusExt::getComputeTime, computeTime)
            .set(ScenePlusExt::getVideos, videosJson));

        SceneFileBuild sceneFileBuild = sceneFileBuildService.findByFileId(fileId);
        if(sceneFileBuild != null){
            sceneFileBuild.setBuildStatus(BuildStatus.success.code());
            sceneFileBuildService.updateById(sceneFileBuild);
        }

        SceneSource sceneSource = SceneSource.get(scenePlus.getSceneSource());
        switch (sceneSource){
            case BM:
                scenePlusExt.setSceneResolution(SceneResolution.TILES_2K.code());
                scenePlusExt.setSceneFrom(SceneFrom.PRO.code());
                break;
            case SM:
                scenePlusExt.setSceneResolution(SceneResolution.TILES_1K.code());
                scenePlusExt.setSceneFrom(SceneFrom.LITE.code());
                break;
            case ZT:
                scenePlusExt.setSceneResolution(SceneResolution.TILES_4K.code());
                scenePlusExt.setSceneFrom(SceneFrom.MINION.code());
                break;
            case JG:
                scenePlusExt.setSceneResolution(SceneResolution.TILES_4K.code());
                scenePlusExt.setSceneFrom(SceneFrom.LASER.code());
                break;
        }
        scenePlusExtService.updateById(scenePlusExt);


        return scenePlus;
    }

    private boolean updateSpace(Long cameraId, Long space, Long scenePlusId, Long sceneProId) throws Exception{
        //更新相机使用用量
        ResultData<CameraDetail> resultData = platformGoodsClient.updateCameraDetailByCameraIdAndSpace(cameraId, space);
        if(resultData.getCode() != ServerCode.SUCCESS.code()){
            log.error("调用platform服务updateCameraDetailByCameraIdAndSpace失败，参数{},{}" ,cameraId, space);
            throw new Exception(ServerCode.FEIGN_REQUEST_FAILD.message());
        }
        CameraDetail cameraDetail = JSONObject.parseObject(JSONObject.toJSONString(resultData.getData()), CameraDetail.class);

        ResultData<UserIncrement> resultData1 = platformUserClient.getUserIncrementByCameraId(cameraId);
        if(resultData1.getCode() != ServerCode.SUCCESS.code()){
            log.error("调用platform服务getUserIncrementByCameraId失败，参数{}" ,cameraId);
            throw new Exception(ServerCode.FEIGN_REQUEST_FAILD.message());
        }
        if( resultData1.getData() == null || resultData1.getData().getIsExpired() == ExpiredStatus.Expired.code()) {
            // 新上传的场景，如果总容量小于使用容量，则该大场景保留在临时存储空间30天
            if (cameraDetail.getTotalSpace().compareTo(cameraDetail.getUsedSpace()) == -1){
                return true;
            }
        }
        return false;
    }

    private Object[] updateEditInfo(ScenePro scenePro, ScenePlus scenePlus){
        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        SceneEditControls sceneEditControls = null;
        SceneEditInfoExt sceneEditInfoExt = null;
        if(sceneEditInfo == null){
            sceneEditInfo = new SceneEditInfo();
            sceneEditInfo.setScenePlusId(scenePlus.getId());
            sceneEditInfo.setSceneProId(scenePro.getId());
            sceneEditInfo.setDescription(scenePlus.getDescription());
            sceneEditInfo.setTitle(scenePlus.getTitle());
            sceneEditInfoService.save(sceneEditInfo);

        }else{
            sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
            sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
        }
        if(sceneEditControls == null){
            sceneEditControls = new SceneEditControls();
            sceneEditControls.setEditInfoId(sceneEditInfo.getId());
            sceneEditControlsService.save(sceneEditControls);
        }
        if(sceneEditInfoExt == null){
            sceneEditInfoExt = new SceneEditInfoExt();
            sceneEditInfoExt.setScenePlusId(scenePlus.getId());
            sceneEditInfoExt.setSceneProId(scenePro.getId());
            sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
            sceneEditInfoExtService.save(sceneEditInfoExt);
        }
        return new Object[]{sceneEditInfo, sceneEditInfoExt, sceneEditControls};
    }
}
