package com.fdkankan.scene.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
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.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.common.constant.*;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.common.response.ResultData;
import com.fdkankan.common.user.SSOLoginHelper;
import com.fdkankan.common.user.SSOUser;
import com.fdkankan.common.util.*;
import com.fdkankan.fyun.constant.StorageType;
import com.fdkankan.fyun.oss.UploadToOssUtil;
import com.fdkankan.platform.api.dto.Camera;
import com.fdkankan.platform.api.dto.CameraDetail;
import com.fdkankan.platform.api.feign.PlatformGoodsClient;
import com.fdkankan.redis.constant.RedisKey;
import com.fdkankan.redis.constant.RedisLockKey;
import com.fdkankan.redis.util.RedisLockUtil;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.scene.bean.IconBean;
import com.fdkankan.scene.bean.RequestSceneProV4;
import com.fdkankan.scene.bean.TagBean;
import com.fdkankan.scene.callback.FdkkMiniReqErrorCallback;
import com.fdkankan.scene.callback.FdkkMiniReqSuccessCallback;
import com.fdkankan.scene.entity.*;
import com.fdkankan.scene.httpclient.FdkankanMiniClient;
import com.fdkankan.scene.mapper.ISceneProMapper;
import com.fdkankan.scene.service.*;
import com.fdkankan.scene.vo.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

/**
 * <p>
 * pro场景表 服务实现类
 * </p>
 *
 * @author dengsixing
 * @since 2021-12-23
 */
@Slf4j
@Service
public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro> implements ISceneProService {

    @Value("${oss.prefix.ali}")
    private String prefixAli;
    @Value("${oss.prefix.url}")
    private String ossUrlPrefix;
    @Value("${upload.type}")
    private String type;
    @Value("${hot.domain.list}")
    private String hotDomainList;
    @Value("${hot.delete}")
    private String hotDelete;
    @Value("${main.url}")
    private String mainUrl;
    @Value("${scene.url}")
    private String sceneUrl;
    @Value("${scene.pro.url}")
    private String sceneProUrl;
    @Value("${scene.pro.new.url}")
    private String sceneProNewUrl;
    @Value("${ecs.checkFile.maxTimes:5}")
    private int maxCheckTimes;
    @Value("${ecs.checkFile.waitTime:5000}")
    private int waitTime;
    @Value("${http.host.4dkankanMini}")
    private String fkankanMiniHost;
    @Value("${http.api-v4.upgradeToV4ResultSync}")
    private String URL_UPGRADE_TO_V4_RESULT_SYNC;

    @Autowired
    @Qualifier("uploadToOssUtil")
    UploadToOssUtil uploadToOssUtil;
    @Autowired
    ISceneProExtService sceneProExtService;
    @Autowired
    ISceneProEditService sceneProEditService;
    @Autowired
    ISceneProEditExtService sceneProEditExtService;
    @Autowired
    ISceneService sceneService;
    @Autowired
    RedisLockUtil redisLockUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    ISceneDataDownloadService sceneDataDownloadService;
    @Autowired
    PlatformGoodsClient platformGoodsClient;
    @Autowired
    ISceneProService sceneProService;
    @Autowired
    ISceneEditInfoService sceneEditInfoService;
    @Autowired
    ISceneEditControlsService sceneEditControlsService;
    @Autowired
    IScenePlusService scenePlusService;
    @Autowired
    IScenePlusExtService scenePlusExtService;
    @Autowired
    ISceneDownloadLogService sceneDownloadLogService;
    @Autowired
    SSOLoginHelper ssoLoginHelper;
    @Autowired
    IFdkkLaserService fdkkLaserService;
    @Resource
    ISceneProMapper sceneProMapper;
    @Autowired
    private FdkankanMiniClient fdkankanMiniClient;

    @Override
    public List<SceneVO> convert(List<ScenePro> list){
        List<SceneVO> sceneVOS = list.parallelStream().map(scenePro -> {
            SceneVO sceneVo = new SceneVO();
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
            SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
            BeanUtils.copyProperties(sceneProEditExt, sceneVo);
            BeanUtils.copyProperties(sceneProEdit, sceneVo);
            BeanUtils.copyProperties(sceneProExt, sceneVo);
            BeanUtils.copyProperties(scenePro, sceneVo);

            sceneVo.setCreateTime(DateUtil.format(scenePro.getCreateTime(), DateExtUtil.dateStyle4));
            sceneVo.setCreateDate(scenePro.getCreateTime().getTime());

            return sceneVo;

        }).collect(Collectors.toList());

        return sceneVOS;
    }

    @Override
    public List<SceneVO> convert2(List<SceneProPO> list){
        List<SceneVO> sceneVOS = list.parallelStream().map(po -> {
            SceneVO sceneVo = new SceneVO();
            SceneProEdit sceneProEdit = sceneProEditService.findByProId(po.getId());
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
            BeanUtils.copyProperties(sceneProEditExt, sceneVo);
            BeanUtils.copyProperties(sceneProEdit, sceneVo);
            BeanUtils.copyProperties(po, sceneVo);

            sceneVo.setCreateTime(DateUtil.format(po.getCreateTime(), DateExtUtil.dateStyle4));
            sceneVo.setCreateDate(po.getCreateTime().getTime());

            return sceneVo;

        }).collect(Collectors.toList());

        return sceneVOS;
    }

    @Override
    public Long getSceneCount(Long cameraId,Long userId) {
        LambdaQueryWrapper<ScenePro> queryWrapper = new LambdaQueryWrapper<ScenePro>()
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .notIn(ScenePro::getSceneType, SceneType.YJHZXNFY.code());
        if(cameraId !=null){
            queryWrapper.eq(ScenePro::getCameraId ,cameraId);
        }
        if(userId !=null){
            queryWrapper.eq(ScenePro::getUserId ,userId);
        }
        return this.count(queryWrapper);
    }

    @Override
    public ScenePro findBySceneNum(String sceneNum) {
        return this.getOne(new LambdaQueryWrapper<ScenePro>()
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .eq(ScenePro::getNum, sceneNum));
    }

    @Override
    public ScenePro findDeleteSceneBySceneNum(String sceneNum) {

        List<ScenePro> list = this.list(new LambdaQueryWrapper<ScenePro>()
                .eq(ScenePro::getTbStatus, TbStatus.DELETE.code())
                .eq(ScenePro::getNum, sceneNum));
        if(CollUtil.isEmpty(list)){
            return null;
        }
        return list.get(0);

    }

    @Override
    public SceneProPO getSceneStatusByUnicode(String unicode, Integer tbStatus) {
        return baseMapper.getSceneStatusByUnicode(unicode, tbStatus);
    }

    @Override
    public List<SceneProPO> findByUserIdAndCameraType(Long userId, Integer cameraType) {
        return baseMapper.findByUserIdAndCameraType(userId, cameraType);
    }

    public List<SceneProPO> findByUserId(Long userId, List<String> excludeNums) {
        return baseMapper.findByUserId(userId,excludeNums);
    }

    @Override
    public List<SceneProPO> findBySceneNums(List<String> sceneCodeList, Integer cameraType) {
        return baseMapper.findBySceneNums(sceneCodeList, cameraType);
    }

    @Override
    public void updateStatus(String sceneNum, int sceneStatus) {
        this.update(new LambdaUpdateWrapper<ScenePro>()
                .eq(ScenePro::getNum, sceneNum)
                .set(ScenePro::getSceneStatus, sceneStatus));
    }

    @Override
    public ResultData resetUploadFloorJson(SceneEditParamVO sceneEdit) throws Exception{
        if(StrUtil.isEmpty(sceneEdit.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(sceneEdit.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        //更新scene.json文件
        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null)
        {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }else {
            new File(dataBuffer.toString() + "scene.json").createNewFile();
        }
        if(!StrUtil.isEmpty(sceneEdit.getSceneData())){
            JSONObject sceneObject = JSONObject.parseObject(sceneEdit.getSceneData());
            Set<String> set =sceneObject.keySet();

            for(String key : set){
                scenejson.put(key, sceneObject.get(key));
            }
        }

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
        //重置将floorEditVer回归floorPublishVer
        sceneProEdit.setFloorPublishVer(sceneProEdit.getFloorEditVer());
        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditService.updateById(sceneProEdit);

        //更新scene.json文件
        if(strsceneInfos!=null){
            scenejson.put("floorEditVer", sceneProEdit.getFloorEditVer());
            scenejson.put("floorPublishVer", sceneProEdit.getFloorEditVer());
            scenejson.put("cadInfo", sceneProEditExt.getCadInfo());
            FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
            log.info("写入scene.json文件完成, sceneCode:{}", sceneEdit.getNum());
        }
        log.info("重置画墙重建模型版本成功");

        return ResultData.ok();
    }

    @Override
    public ResultData uploadFloorJson(SceneEditParamVO sceneEdit) throws Exception {

        String lockKey = String.format(RedisLockKey.LOCK_UPLOAD_FLOORJSON_REBUILD, sceneEdit.getNum());
        Boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_2_HOUR);
        if(!lock){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5036);
        }

        try {

            long start = System.currentTimeMillis();
            log.info("画墙重建模型开始时间：" + start);
            if(StrUtil.isEmpty(sceneEdit.getNum())){
                throw new BusinessException(ErrorCode.PARAM_REQUIRED);
            }

            ScenePro scenePro = findBySceneNum(sceneEdit.getNum());
            if(scenePro == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            }
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

            SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
            if(sceneProEdit == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            }

            //更新scene.json文件
            String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + sceneEdit.getNum() + File.separator + "scene.json");
            JSONObject scenejson = new JSONObject();
            if(strsceneInfos!=null)
            {
                scenejson = JSONObject.parseObject(strsceneInfos);
            }else {
                new File(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + sceneEdit.getNum() + File.separator + "scene.json").createNewFile();
            }
            if(!StrUtil.isEmpty(sceneEdit.getSceneData())){
                JSONObject sceneObject = JSONObject.parseObject(sceneEdit.getSceneData());
                Set<String> set =sceneObject.keySet();

                for(String key : set){
                    scenejson.put(key, sceneObject.get(key));
                }
            }

            //保存floor.json前端下次进入需要使用
            if(StrUtil.isEmpty(sceneEdit.getWebFloor())){
                sceneEdit.setWebFloor(sceneEdit.getFloor());
            }

            //上传过模型只更新floor.json
            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneEdit.getNum() + File.separator + "floor.json", new String(sceneEdit.getWebFloor().getBytes(), "UTF-8"));

            //更新scene.json文件
            if(strsceneInfos!=null)
            {
                scenejson.put("floorEditVer", sceneProEdit.getFloorEditVer() + 1);
                scenejson.put("floorPublishVer", sceneProEdit.getFloorPublishVer());
                FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneEdit.getNum()+File.separator+"scene.json", scenejson.toString());
                log.info("写入scene.json文件完成——"+sceneEdit.getNum());
            }

            //floorEditVer字段增加1
            sceneProEdit.setFloorEditVer(sceneProEdit.getFloorEditVer() + 1);
            sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
            sceneProEditService.updateById(sceneProEdit);

            String path = sceneProExt.getDataSource();
            if(path != null && !"".equals(path) && path.startsWith("http")){
                path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
            }
            String target = path + "_edit";
            File editPath = new File(target);
            if(!editPath.exists()){
                editPath.mkdirs();
            }
            //创建文件夹软连接并且复制data.json和project.json
            if(new File(target + File.separator + "capture").exists()){
                new File(target + File.separator + "capture").delete();
            }
            if(new File(target + File.separator + "caches").exists()){
                //删除link
                new File(target + File.separator + "caches" + File.separator + "images").delete();
                //删除所有文件
                FileUtils.delAllFile(target + File.separator + "caches");
            }
            if(new File(target + File.separator + "results").exists()){
                FileUtils.delAllFile(target + File.separator + "results");
            }
            //创建文件夹,并link文件夹
            new File(target + File.separator + "caches").mkdirs();
            CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture");
            if(new File(path + File.separator + "caches" + File.separator + "images").exists()){
                CreateObjUtil.createSoftConnection(path + File.separator + "caches" + File.separator + "images", target + File.separator + "caches" + File.separator + "images");
            }

            FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
            FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);

            //data.json增加extras为执行重建算法
            String project = FileUtils.readFile(target + File.separator+"project.json");
            if(project != null){
                JSONObject projectJson = JSONObject.parseObject(project);
                projectJson.put("parent", projectJson.get("uuid"));
                projectJson.put("uuid", UUID.randomUUID().toString());
                projectJson.put("time", System.currentTimeMillis());
                FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
            }

            String data = FileUtils.readFile(target + File.separator+"data.json");
            if(data != null){
                JSONObject floorplanJson = new JSONObject();
                floorplanJson.put("has_floorplan_json", true);
                floorplanJson.put("has_vision_txt", true);

                JSONObject dataJson = JSONObject.parseObject(data);
                dataJson.put("extras", floorplanJson);
                //V5表示不需要生成high，low文件
                dataJson.put("skybox_type", "SKYBOX_V5");
                dataJson.put("split_type", "SPLIT_V4");
                FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
            }

            //文件上传的位置可以自定义
            log.info("画墙重建模型开始");
            File targetFile = new File(target + File.separator + "extras" + File.separator + "floorplan.json");
            if(!targetFile.getParentFile().exists()){
                targetFile.getParentFile().mkdirs();
            }
            if(targetFile.exists()){
                FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "floorplan.json");
            }
            // 保存
            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floorplan.json", new String(sceneEdit.getFloor().getBytes(), "UTF-8"));

            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneEdit.getNum() + File.separator + "floor.json", new String(sceneEdit.getWebFloor().getBytes(), "UTF-8"));
            //下载vision.modeldata，解压成vision.txt,并且删除vision.modeldata
            log.info("下载vision.modeldata文件");
            if("aws".equals(type)){
                FileUtils.downLoadFromUrl(ConstantUrl.PREFIX_AWS + "images/images" + sceneEdit.getNum() + "/vision.modeldata" + "?m="+new Date().getTime(),
                        "vision.modeldata", target + File.separator + "extras" + File.separator);
            }
            if("oss".equals(type)){
                FileUtils.downLoadFromUrl(prefixAli + "images/images" + sceneEdit.getNum() + "/vision.modeldata" + "?m="+new Date().getTime(),
                        "vision.modeldata", target + File.separator + "extras" + File.separator);
            }
            CreateObjUtil.convertVisionmodeldataToTxt(target + File.separator + "extras" + File.separator + "vision.modeldata",
                    target + File.separator + "extras" + File.separator + "vision.txt");
            log.info("解压完成，删除vision.modeldata文件");
            FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "vision.modeldata");

            log.info("下载vision2.modeldata文件");
            if("oss".equals(type)){
                FileUtils.downLoadFromUrl(prefixAli + "images/images" + sceneEdit.getNum() + "/vision2.modeldata" + "?m="+new Date().getTime(),
                        "vision2.modeldata", target + File.separator + "extras" + File.separator);
            }
            if("aws".equals(type)){
                FileUtils.downLoadFromUrl(ConstantUrl.PREFIX_AWS + "images/images" + sceneEdit.getNum() + "/vision2.modeldata" + "?m="+new Date().getTime(),
                        "vision2.modeldata", target + File.separator + "extras" + File.separator);
            }
            CreateObjUtil.convertVisionmodeldataToTxt(target + File.separator + "extras" + File.separator + "vision2.modeldata",
                    target + File.separator + "extras" + File.separator + "vision2.txt");
            log.info("解压完成，删除vision2.modeldata文件");
            FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "vision2.modeldata");

            //重新计算算法
            log.info("重新计算大场景：开始建模——"+sceneEdit.getNum());
            //判断V2还是V3
            if("V2".equals(scenePro.getBuildType())){
                CreateObjUtil.build3dModelOld(target , "1");
            }
            if("V3".equals(scenePro.getBuildType())){
                CreateObjUtil.build3dModel(target , "1");
            }
            log.info("重新计算大场景：开始转换成lzma文件——"+sceneEdit.getNum());
            CreateObjUtil.convertTxtToDam( target + File.separator + "results" + File.separator+"tex"+
                    File.separator+"modeldata.txt", target + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam");
            CreateObjUtil.convertDamToLzma(target + File.separator + "results");
            CreateObjUtil.convertTxtToDam( target + File.separator + "results" +File.separator+"tex"+
                    File.separator+"modeldata.txt", target + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
            File lzmaFile = new File(target + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma");
            if(!lzmaFile.exists())
            {
                log.info("lzam文件不存在——"+sceneEdit.getNum());
                Thread.sleep(3000);
            }

            File sceneFile = new File(ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneEdit.getNum() + File.separator + ConstantFileName.modelUUID + "_50k_texture_jpg_high1");
            if(!sceneFile.exists())
            {
                log.info("high1文件夹不存在——"+sceneEdit.getNum());
                sceneFile.mkdirs();
            }

            //将重新建模的tex里的文件和lzma文件复制到Message.filePath+"images"+File.separator+"images"+sceneNum下。
            List<String> list1 = FileUtils.readfileNamesForDirectory(target+File.separator+ "results" + File.separator +"tex",".jpg");
            if(list1 == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
            log.info("新生成的贴图有：——"+list1.size());
            for(int i=0; i<list1.size(); ++i)
            {
                String imgName = list1.get(i);
                FileUtils.copyFile(target+File.separator + "results" + File.separator+"tex"+File.separator+imgName,
                        ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneEdit.getNum() + File.separator + ConstantFileName.modelUUID + "_50k_texture_jpg_high1"+File.separator+imgName, true);
            }
            FileUtils.copyFile(target+File.separator + "results" + File.separator +ConstantFileName.modelUUID+"_50k.dam",
                    ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneEdit.getNum() + File.separator + ConstantFileName.modelUUID+"_50k.dam", true);
            log.info("文件复制到本地ecs完成——"+sceneEdit.getNum());

            //更新scene.json文件
            if(strsceneInfos!=null)
            {
                scenejson.put("floorEditVer", sceneProEdit.getFloorEditVer() + 1);
                scenejson.put("floorPublishVer", sceneProEdit.getFloorPublishVer());
                FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneEdit.getNum()+File.separator+"scene.json", scenejson.toString());
                log.info("写入scene.json文件完成——"+sceneEdit.getNum());
            }

            //floorEditVer字段增加1
            sceneProEdit.setFloorEditVer(sceneProEdit.getFloorEditVer() + 1);
            sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
            sceneProEditService.updateById(sceneProEdit);
            log.info("修改数据库完成, sceneCode:{}, 花费时间：{}", sceneEdit.getNum(), System.currentTimeMillis() - start);

        }catch (Exception e){
            log.error("画墙重建模型失败...", e);
            throw new BusinessException(ErrorCode.FAILURE_CODE_5039);
        }finally {
            redisLockUtil.unlock(lockKey);
        }

        return ResultData.ok();
    }

    @Override
    public ResultData uploadFloorJsonAjk(FileParamVO param, MultipartFile[] file) throws Exception {

        String sceneNum = param.getNum();
        String floorPlanJson = param.getFloorPlanJson();
        String ajkJson = param.getAjkJson();
        String cameraJson = param.getCameraJson();

        String lockKey = String.format(RedisLockKey.LOCK_UPLOAD_FLOORJSON_REBUILD, sceneNum);
        Boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_2_HOUR);
        if(!lock){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5036);
        }

        try {

            if(StrUtil.isEmpty(sceneNum)){
                throw new BusinessException(ErrorCode.PARAM_REQUIRED);
            }

            ScenePro scenePro = findBySceneNum(sceneNum);
            if(scenePro == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            }

            SceneProEdit sceneProEdit= sceneProEditService.findByProId(scenePro.getId());
            if(sceneProEdit == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            }
            SceneProExt sceneProExt = sceneProExtService.getOne(new LambdaQueryWrapper<SceneProExt>().eq(SceneProExt::getSceneProId, scenePro.getId()));

            //更新scene.json文件
            String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + sceneNum + File.separator + "scene.json");
            JSONObject scenejson = new JSONObject();
            if(strsceneInfos!=null)
            {
                scenejson = JSONObject.parseObject(strsceneInfos);
            }else {
                new File(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + sceneNum + File.separator + "scene.json").createNewFile();
            }

            String path = sceneProExt.getDataSource();//   /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060/
            if(path != null && !"".equals(path) && path.startsWith("http")){
                path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
            }
            String target = path + "_ajk";   // /mnt/data/0662c5389/831989883441512448/4898cab04f8c_202104141602356060_ajk
            File editPath = new File(target);
            if(!editPath.exists()){
                editPath.mkdirs();
            }

            //创建文件夹软连接并且复制data.json和project.json
            if(new File(target + File.separator + "capture").exists()){
                new File(target + File.separator + "capture").delete();
            }
            if(new File(target + File.separator + "caches").exists()){
                //删除link
                new File(target + File.separator + "caches" + File.separator + "images").delete();
                //删除所有文件
                FileUtils.delAllFile(target + File.separator + "caches");
            }
            if(new File(target + File.separator + "results").exists()){
                FileUtils.delAllFile(target + File.separator + "results");
            }
            //创建文件夹,并link文件夹
            new File(target + File.separator + "caches").mkdirs();
            CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture");
            if(new File(path + File.separator + "caches" + File.separator + "images").exists()){
                CreateObjUtil.createSoftConnection(path + File.separator + "caches" + File.separator + "images", target + File.separator + "caches" + File.separator + "images");
            }

            FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
            FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);

            //data.json增加extras为执行重建算法
            String project = FileUtils.readFile(target + File.separator+"project.json");
            if(project != null){
                JSONObject projectJson = JSONObject.parseObject(project);
                projectJson.put("parent", projectJson.get("uuid"));
                projectJson.put("uuid", UUID.randomUUID().toString());
                projectJson.put("time", System.currentTimeMillis());
                FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
            }

            String data = FileUtils.readFile(target + File.separator+"data.json");
            if(data != null){
                JSONObject floorplanJson = new JSONObject();
                floorplanJson.put("has_floor_ajk_json", true);
                floorplanJson.put("has_vision_txt", true);
                floorplanJson.put("has_floorplan_json", true);

                JSONObject dataJson = JSONObject.parseObject(data);
                dataJson.put("extras", floorplanJson);
                //V5表示不需要生成high，low文件
                dataJson.put("skybox_type", "SKYBOX_V8");
                dataJson.put("split_type", "SPLIT_V10");
                FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
            }

            //文件上传的位置可以自定义
            log.info("画墙重建模型开始");
            File targetFile = new File(target + File.separator + "extras" + File.separator + "floor_ajk.json");
            if(!targetFile.getParentFile().exists()){
                targetFile.getParentFile().mkdirs();
            }
            if(targetFile.exists()){
                FileUtils.deleteFile(target + File.separator + "extras" + File.separator + "floor_ajk.json");
            }
            // 保存
            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floorplan.json", new String(floorPlanJson.getBytes(), "UTF-8"));

            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8"));
            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneNum + File.separator + "floor_ajk.json", new String(ajkJson.getBytes(), "UTF-8"));

            FileUtils.writeFile(target + File.separator + "extras" + File.separator + "vision.txt", new String(cameraJson.getBytes(), "UTF-8"));
            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneNum + File.separator + "camera.json", new String(cameraJson.getBytes(), "UTF-8"));

            for(int i = 0; i < file.length; i ++){

                File cadImg = new File(target + File.separator + "extras" + File.separator + "Floorplans/" + file[i].getOriginalFilename());
                if(!cadImg.getParentFile().exists()){
                    cadImg.getParentFile().mkdirs();
                }
                if(cadImg.exists())
                {
                    cadImg.delete();
                }

                file[i].transferTo(cadImg);
            }
            //下载封面图
            FileUtils.downLoadFromUrl(scenePro.getThumb() + "?t=" + System.currentTimeMillis(),
                    "Cover.png", target + File.separator + "extras" + File.separator + "CoverImage");
            //转换成jpg
            FileUtils.pngToJpg(target + File.separator + "extras" + File.separator + "CoverImage/Cover.png",
                    target + File.separator + "extras" + File.separator + "CoverImage/Cover.jpg");

            //安居客算法运行
            log.info("安居客算法：开始建模——"+sceneNum);

            CreateObjUtil.build3dModel(target , "1");
            if(!new File(target + File.separator + "results" + File.separator + "upload.json").exists()){
                return ResultData.error(ErrorCode.FAILURE_CODE_5042);
            }

            String zipPath = target + File.separator + "results/" + sceneNum + ".zip";
            new File(zipPath).delete();

//            FileUtils.zipFile(zipPath, target + File.separator + "results/ajk/");
            String command = "bash /opt/ossutil/gzip.sh " + zipPath.replace(".zip", "") + " " + target + File.separator + "results/ajk/";
            log.info("压缩文件:" + command);
            CreateObjUtil.callshell(command);

            if(!new File(zipPath).exists()){
                return  ResultData.error(ErrorCode.FAILURE_CODE_5043);
            }
            String fileMD5 = FileMd5Util.getFileMD5(new File(zipPath));

            uploadToOssUtil.upload(zipPath, "data_download/" + sceneNum + ".zip");

            SceneDataDownload sceneDataDownload = sceneDataDownloadService.findBySceneNum(sceneNum);
            if(sceneDataDownload == null){
                sceneDataDownload = new SceneDataDownload();
                sceneDataDownload.setNum(sceneNum);
                sceneDataDownload.setDownloadPath(prefixAli + "data_download/" + sceneNum + ".zip");
                sceneDataDownload.setFileMd5(fileMD5);
                sceneDataDownloadService.save(sceneDataDownload);
                return ResultData.ok();
            }

            sceneDataDownload.setFileMd5(fileMD5);
            sceneDataDownload.setUpdateTime(Calendar.getInstance().getTime());
            sceneDataDownloadService.updateById(sceneDataDownload);
        }catch (Exception e){
            log.error("画墙重建模型失败...", e);
            throw new BusinessException(ErrorCode.FAILURE_CODE_5039);
        }finally {
            redisLockUtil.unlock(lockKey);
        }

        return ResultData.ok();
    }

    @Override
    public ResultData addHotMediaInfo(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getType()) ||
                StrUtil.isEmpty(base.getInfo())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String mediaInfoPath = String.format(ConstantFilePath.MEDIAINFO_PATH_FORMAT, scenePro.getNum());
        String infoData = FileUtils.readFile(mediaInfoPath);
        JSONArray medias =  null;
        if(infoData != null){
            medias= JSONArray.parseArray(infoData);
        }

        if(SceneEditType.ADD.code().equals(base.getType())){
            JSONObject jo = JSONObject.parseObject(base.getInfo());
            medias.add(jo);
        }
        else{
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }

        FileUtils.writeFile(mediaInfoPath, medias.toString());

        return ResultData.ok();
    }

    @Override
    public ResultData saveScreencapFile(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getIndex()) ||
                StrUtil.isEmpty(base.getCamerasData())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String sceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String tourlistfolderPath = String.format(ConstantFilePath.TOURLIST_FOLDER_PATH_FORMAT, scenePro.getNum());
        if("1".equals(base.getIndex())){
            File file = new File(tourlistfolderPath);
            if(file.isDirectory()){
                String[] strs = file.list();
                if(strs!=null){
                    for(int i=0;i<strs.length;++i) {

                        if(strs[i].indexOf(ConstantFileName.SCREEN_CRP_DATAFILE)>-1) {
                            FileUtils.deleteFile(tourlistfolderPath + File.separator + strs[i]);
                        }
                    }
                }
            } else {
                file.mkdirs();
            }

            String strsceneInfos = FileUtils.readFile(sceneJsonPath);
            JSONObject scenejson = new JSONObject();
            if(strsceneInfos!=null) {
                scenejson = JSONObject.parseObject(strsceneInfos);
            }
            Map<String, Object> map = new HashMap<>();
            map.put("screencapLen", "0");
            map.put("version", scenejson.getIntValue("version")+1);
            FileUtils.writeJsonFile(sceneJsonPath, map);
        }

        String filePath = tourlistfolderPath+File.separator+ConstantFileName.SCREEN_CRP_DATAFILE+base.getIndex()+"json";
        File file = new File(filePath);
        if(!file.exists())
        {
            file.createNewFile();
        }
        FileUtils.writeFile(filePath, base.getCamerasData());

        return ResultData.ok();
    }

    @Override
    public ResultData saveSceneKey(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getSceneKey())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        sceneProEdit.setSceneKey(base.getSceneKey());
        sceneProEdit.setNeedKey(0);
        sceneProEdit.setVersion(sceneProEdit.getVersion() + 1);
        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditService.updateById(sceneProEdit);

        return ResultData.ok();
    }

    @Override
    public ResultData saveFloorLogo(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getSize()) ||
                StrUtil.isEmpty(base.getLogoType())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String sceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String strsceneInfos = FileUtils.readFile(sceneJsonPath);
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }
        Map map = new HashMap();
        map.put("floorLogo", base.getLogoType());
        map.put("floorLogoSize", base.getSize());
        map.put("version", scenejson.getIntValue("version")+1);

        FileUtils.writeJsonFile(sceneJsonPath, map);
        return ResultData.ok();
    }

    @Override
    public ResultData saveBackgroundMusic(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getMusicName())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String sceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String strsceneInfos = FileUtils.readFile(sceneJsonPath);
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }
        Map map = new HashMap();
        map.put("bgMusic", base.getMusicName());
        map.put("version", scenejson.getIntValue("version")+1);

        FileUtils.writeJsonFile(sceneJsonPath, map);
        return ResultData.ok();
    }

    @Transactional
    @Override
    public ResultData saveInitialPage(FileNameAndDataParamVO param) throws Exception{

        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if(scenePlus == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());

        //更新缩略图url
        String thumbUrl = this.ossUrlPrefix + String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + param.getFileName();
        scenePlusExt.setThumb(thumbUrl);
        scenePlusExtService.updateById(scenePlusExt);

        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        if(sceneEditInfo == null){
            sceneEditInfo = new SceneEditInfo();
            sceneEditInfo.setScenePlusId(scenePlus.getId());
            sceneEditInfo.setEntry(param.getData());
            sceneEditInfoService.save(sceneEditInfo);
        }else{
            sceneEditInfoService.update(
                new LambdaUpdateWrapper<SceneEditInfo>()
                    .set(SceneEditInfo::getEntry, param.getData())
                    .setSql("version = version + 1")
                    .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
        }

        return ResultData.ok();
    }

    @Override
    public ResultData getScreencapVoice(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String sceneInfos = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        JSONObject scenejson = new JSONObject();
        if(sceneInfos!=null)
        {
            scenejson = JSONObject.parseObject(sceneInfos);
        }
        JSONObject result = new JSONObject();
        String screencapVoiceFileName = "";
        if(scenejson.containsKey("screencapVoiceFileName"))
        {
            screencapVoiceFileName = scenejson.getString("screencapVoiceFileName");
        }
        String screencapVoiceSrc = "";
        if(scenejson.containsKey("screencapVoiceSrc"))
        {
            screencapVoiceSrc = scenejson.getString("screencapVoiceSrc");
        }
        if(!screencapVoiceFileName.trim().equals("")&&!screencapVoiceSrc.trim().equals("")&&screencapVoiceFileName.indexOf(".")>-1)
        {
            result.put("screencapVoiceFileName", screencapVoiceFileName);
            result.put("screencapVoiceSrc1", screencapVoiceSrc);
            result.put("screencapVoiceSrc2", "voice/voice"+base.getNum()+"/201810" +screencapVoiceFileName.substring(screencapVoiceFileName.lastIndexOf(".")));
        }

        return ResultData.ok();
    }

    @Override
    public ResultData uploadScreencapVoiceNew(FileParamVO param, MultipartFile file) throws Exception{
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        ScenePro scenePro = findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        if (!file.isEmpty()&& file.getSize() <= 0) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }

        String lockKey = String.format(RedisLockKey.LOCK_UPLOAD_PRO_VOICE, sceneNum);
        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_30_MINUTE);
        if(!lock){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5036);
        }
        String voiceSrc = null;
        try{
            //文件上传的位置可以自定义
            String path = ConstantFilePath.SCENE_PATH+"voice"+File.separator+"voice"+sceneNum;
            File targetFile = new File(path);
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }

            //获取文件名去掉后缀
            String originalFileName = file.getOriginalFilename().substring(0,
                    file.getOriginalFilename().indexOf(".") > 0 ? file.getOriginalFilename().indexOf(".") : file.getOriginalFilename().length());
            log.info("上传的音频文件名：" + file.getOriginalFilename());
            String soundFileName = "sound201810.wav";

            String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json");
            JSONObject scenejson = new JSONObject();
            if(strsceneInfos!=null) {
                scenejson = JSONObject.parseObject(strsceneInfos);
            }
            if("soundsync".equals(type) && !"1".equals(param.getReplace())){
                if(scenejson.containsKey("screencapVoiceSoundsync") && !StrUtil.isEmpty(scenejson.getString("screencapVoiceSoundsync"))){
                    String target = ConstantFilePath.SCENE_PATH + scenejson.getString("screencapVoiceSoundsync").substring(
                            scenejson.getString("screencapVoiceSoundsync").indexOf("voice"));

                    if(new File(target).exists()){
                        targetFile = new File(path + File.separator +soundFileName);
                        if(targetFile.exists())
                        {
                            FileUtils.deleteFile(path + File.separator + soundFileName);
                        }
                        file.transferTo(targetFile);
                        FileUtils.changeVoiceToMp3(path + File.separator + soundFileName, path + File.separator + "newSound201810.mp3");

                        //目标文件改名
                        new File(target).renameTo(new File(path + File.separator + "oldSound201810.mp3"));

                        //判断音频时长，不够拼接空白音效
                        double total = param.getLength();
                        double now = (FileUtils.getAudioPlayTime(new File(path + File.separator + "oldSound201810.mp3")) +
                                FileUtils.getAudioPlayTime(new File(path + File.separator + "newSound201810.mp3"))) / 1000.0;
                        if(total - now > 0.5){
                            CreateObjUtil.createMuteViode(total - now, path + File.separator + "muteSound.mp3");
                            if(new File(path + File.separator + "muteSound.mp3").exists()){
                                //需要将旧的音频改名
                                new File(path + File.separator + "oldSound201810.mp3").renameTo(new File(path + File.separator + "oldMuteSound201810.mp3"));
                                log.info("生成新的静音音频和旧的音频合并");
                                CreateObjUtil.mergeVideo(path + File.separator + "oldMuteSound201810.mp3", path + File.separator + "muteSound.mp3",
                                        path + File.separator + "oldSound201810.mp3");
                            }
                        }

                        //app端和pc端名字不一致，统一文件名字
                        target = path + File.separator + originalFileName + ".mp3";
                        CreateObjUtil.mergeVideo(path + File.separator + "oldSound201810.mp3", path + File.separator + "newSound201810.mp3", target);
                        //删除改名后的文件
    //                    new File(path + File.separator + "oldSound201810.mp3").delete();

                        Map map = new HashMap();
                        map.put("screencapVoiceSoundsyncFileName", originalFileName + ".mp3");
                        String proVideo = "voice/voice"+sceneNum+"/"+originalFileName  + ".mp3";
                        map.put("screencapVoiceSoundsync", proVideo);
                        map.put("uploadVoiceSoundsync", 1);
                        map.put("screencapVoiceType", type);
                        map.put("version", scenejson.getIntValue("version")+1);
                        FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                        return ResultData.ok("voice/voice"+sceneNum+"/"+originalFileName + ".mp3");
                    }

                }else {
                    targetFile = new File(path + File.separator +soundFileName);
                    if(targetFile.exists())
                    {
                        FileUtils.deleteFile(path + File.separator + soundFileName);
                    }
                    file.transferTo(targetFile);
                    //判断音频时长，不够拼接空白音效
                    FileUtils.changeVoiceToMp3(path + File.separator + soundFileName, path + File.separator + "newSound201810.mp3");
                    double total = param.getLength();
                    double now = (FileUtils.getAudioPlayTime(new File(path + File.separator + "newSound201810.mp3"))) / 1000.0;
                    log.info("前端传的时长：" + total);
                    log.info("获取文件的时长：" + now);

                    //同步录音前一段没空白，直接生成文件
                    if(total - now < 0.5){
                        FileUtils.changeVoiceToMp3(path + File.separator + soundFileName, path + File.separator + originalFileName + ".mp3");
                        Map map = new HashMap();
                        map.put("screencapVoiceSoundsyncFileName", originalFileName + ".mp3");
                        String proVideo = "voice/voice"+sceneNum+"/"+originalFileName  + ".mp3";
                        map.put("screencapVoiceSoundsync", proVideo);
                        map.put("uploadVoiceSoundsync", 1);
                        map.put("screencapVoiceType", type);
                        map.put("version", scenejson.getIntValue("version")+1);

                        FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                        return ResultData.ok(proVideo);
                    }

                    ////同步录音前一段有空白，生成一段静音后拼接文件
                    CreateObjUtil.createMuteViode(total - now, path + File.separator + "muteSound.mp3");

                    //app端和pc端名字不一致，统一文件名字
                    String target = path + File.separator + originalFileName + ".mp3";
                    CreateObjUtil.mergeVideo(path + File.separator + "muteSound.mp3", path + File.separator + "newSound201810.mp3", target);

                    Map map = new HashMap();
                    map.put("screencapVoiceSoundsyncFileName", originalFileName + ".mp3");
                    String proVideo = "voice/voice"+sceneNum+"/"+originalFileName  + ".mp3";
                    map.put("screencapVoiceSoundsync", proVideo);
                    map.put("uploadVoiceSoundsync", 1);
                    map.put("screencapVoiceType", type);
                    map.put("version", scenejson.getIntValue("version")+1);
                    FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                    return ResultData.ok("voice/voice"+sceneNum+"/"+originalFileName + ".mp3");

                }
            }

            String name = "201810.wav";
            targetFile = new File(path + File.separator +name);
            // 保存
            if(targetFile.exists())
            {
                FileUtils.deleteFile(path + File.separator + name);
            }
            file.transferTo(targetFile);
            Map map = new HashMap();

            if("soundsync".equals(type)){
                FileUtils.changeVoiceToMp3(path + File.separator + name, path + File.separator + originalFileName + ".mp3");
                map.put("screencapVoiceSoundsyncFileName", originalFileName + ".mp3");
                String proVideo = "voice/voice"+sceneNum+"/"+originalFileName  + ".mp3";
                map.put("screencapVoiceSoundsync", proVideo);
                map.put("uploadVoiceSoundsync", 1);
                map.put("version", scenejson.getIntValue("version")+1);
                map.put("screencapVoiceType", type);
                FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                return ResultData.ok(proVideo);
            }

            if("sound".equals(type)){
                FileUtils.changeVoiceToMp3(path + File.separator + name, path + File.separator + originalFileName + ".mp3");
                map.put("screencapVoiceSoundFileName", originalFileName + ".mp3");
                String proVideo = "voice/voice"+sceneNum+"/"+originalFileName  + ".mp3";
                map.put("screencapVoiceSound", proVideo);
                map.put("uploadVoiceSound", 1);
                map.put("version", scenejson.getIntValue("version")+1);
                map.put("screencapVoiceType", type);
                FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                return ResultData.ok(proVideo);
            }

            FileUtils.changeVoiceToMp3(path + File.separator + name, path + File.separator +"201810.mp3");
            if(StrUtil.isEmpty(fileName)){
                map.put("screencapVoiceFileName", originalFileName + ".mp3");
            }else {
                map.put("screencapVoiceFileName", fileName);
            }
            voiceSrc = "voice/voice"+sceneNum+"/"+"201810.mp3";
            map.put("screencapVoiceSrc", voiceSrc);
            map.put("uploadVoiceSrc", 1);
            map.put("version", scenejson.getIntValue("version")+1);
            map.put("screencapVoiceType", type);
            FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
        }finally {
            redisLockUtil.unlock(lockKey);
        }
        return ResultData.ok(voiceSrc);
    }

    @Override
    public ResultData uploadScreencapVoiceNewV3(FileParamVO param, MultipartFile file) throws Exception{
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        if (!file.isEmpty()&& file.getSize() <= 0) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }
        String lockKey = String.format(RedisLockKey.LOCK_UPLOAD_PRO_VOICE, sceneNum);
        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_30_MINUTE);
        if(!lock){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5036);
        }
        String voiceSrc = null;
        try{
            //文件上传的位置可以自定义
            String path = ConstantFilePath.SCENE_PATH+"voice"+File.separator+"voice"+sceneNum;
            File targetFile = new File(path);
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }

            String originalFileName = "sound201810.mp3";

            String strsceneInfos = FileUtils.readFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json");
            JSONObject scenejson = new JSONObject();
            if(strsceneInfos!=null) {
                scenejson = JSONObject.parseObject(strsceneInfos);
            }
            if("soundsync".equals(type) && !"1".equals(param.getReplace())){
                //判断分房间模块文件夹是否存在
                String partPath = path + File.separator + "part";
                File partFile = new File(partPath);
                if(!partFile.exists()){
                    partFile.mkdirs();
                }

                targetFile = new File(partPath + File.separator + fileName);
                if(targetFile.exists())
                {
                    FileUtils.deleteFile(partPath + File.separator + fileName);
                }
                file.transferTo(targetFile);

                //获取总音频多少段，每段时长
                String[] time = param.getTimes().split(",");
                //遍历判断音频是否存在，不存在生成空白音效
                for(int i = 0, len = time.length; i < len; i++){
                    if(!new File(partPath + File.separator + i + ".mp3").exists()){
                        //某部分文件不存在，直接生成一段静音后拼接文件
                        CreateObjUtil.createMuteViode(Double.valueOf(time[i]), partPath + File.separator + i + ".mp3");
                    }
                }

                //拼接所有音频文件
                if(time.length > 2){
                    //若是多部分，两个两个合并，最后合成最终文件
                    for(int i = 1, len = time.length; i < len; i++){
                        if(i == 1){

                            CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + ".mp3", partPath + File.separator + i + ".mp3",
                                    partPath + File.separator + i + "muteSound.mp3");
                        }else if(i == len - 1){
                            CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + "muteSound.mp3", partPath + File.separator + i + ".mp3",
                                    path + File.separator + originalFileName);
                        }else {
                            CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + "muteSound.mp3", partPath + File.separator + i + ".mp3",
                                    partPath + File.separator + i + "muteSound.mp3");
                        }
                    }
                }else {
                    //若只有两部分，直接合并成最终文件
                    CreateObjUtil.mergeVideo(partPath + File.separator + "0.mp3", partPath + File.separator + "1.mp3", path + File.separator + originalFileName);
                }

                Map map = new HashMap();
                map.put("screencapVoiceSoundsyncFileName", originalFileName);
                String proVideo = "voice/voice"+sceneNum+"/"+originalFileName;
                map.put("screencapVoiceSoundsync", proVideo);
                map.put("uploadVoiceSoundsync", 1);
                map.put("screencapVoiceType", type);
                map.put("version", scenejson.getIntValue("version")+1);
                FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                return ResultData.ok("voice/voice"+sceneNum+"/"+originalFileName);
            }

            String name = "201810.wav";
            targetFile = new File(path + File.separator +name);
            // 保存
            if(targetFile.exists())
            {
                FileUtils.deleteFile(path + File.separator + name);
            }
            file.transferTo(targetFile);
            Map map = new HashMap();

            if("soundsync".equals(type)){
                FileUtils.delAllFile(path + File.separator + "part");
                //判断分房间模块文件夹是否存在
                String partPath = path + File.separator + "part";
                File partFile = new File(partPath);
                if(!partFile.exists()){
                    partFile.mkdirs();
                }

                //保存0.mp3文件到part
                FileUtils.copyFile(path + File.separator +name, partPath + File.separator + fileName, true);

                FileUtils.changeVoiceToMp3(path + File.separator + name, path + File.separator + originalFileName);
                map.put("screencapVoiceSoundsyncFileName", originalFileName);
                String proVideo = "voice/voice"+sceneNum+"/"+originalFileName;
                map.put("screencapVoiceSoundsync", proVideo);
                map.put("uploadVoiceSoundsync", 1);
                map.put("version", scenejson.getIntValue("version")+1);
                map.put("screencapVoiceType", type);
                FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
                return ResultData.ok(proVideo);
            }

            FileUtils.changeVoiceToMp3(path + File.separator + name, path + File.separator +"201810.mp3");
            map.put("screencapVoiceFileName", file.getOriginalFilename());
            voiceSrc = "voice/voice"+sceneNum+"/"+"201810.mp3";
            map.put("screencapVoiceSrc", voiceSrc);
            map.put("uploadVoiceSrc", 1);
            map.put("version", scenejson.getIntValue("version")+1);
            map.put("screencapVoiceType", type);
            FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
        }finally {
            redisLockUtil.unlock(lockKey);
        }
        return ResultData.ok(voiceSrc);
    }

    @Override
    public ResultData deleteScreencapVoicePart(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        String index = param.getIndex();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        //文件上传的位置可以自定义
        String path = ConstantFilePath.SCENE_PATH+"voice"+File.separator+"voice"+sceneNum;
        File targetFile = new File(path);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }

        String originalFileName = "sound201810.mp3";
        log.info("上传的音频文件名：" + originalFileName);

        String scenePath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String strsceneInfos = FileUtils.readFile(scenePath);
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }
        //判断分房间模块文件夹是否存在
        String partPath = path + File.separator + "part";
        File partFile = new File(partPath);
        if(!partFile.exists()){
            partFile.mkdirs();
        }

        //删除指定部分音频文件
        FileUtils.deleteFile(partPath + File.separator + index + ".mp3");

        //获取总音频多少段，每段时长
        String[] time = param.getTimes().split(",");
        //修改删除的部分视频后面部分音频名字，如删除1.MP3，则将2.mp3修改成1.mp3，往后以此类推
        if(Integer.parseInt(index) < time.length) {
            for(int i = 0, len = time.length - Integer.parseInt(index); i < len; i++){
                if(new File(partPath + File.separator + (Integer.parseInt(index) + 1 + i) + ".mp3").exists()){
                    FileUtils.copyFile(partPath + File.separator + (Integer.parseInt(index) + 1 + i) + ".mp3",
                            partPath + File.separator + (Integer.parseInt(index) + i) + ".mp3", true);
                }
            }
        }

        //遍历判断音频是否存在，不存在生成空白音效
        for(int i = 0, len = time.length; i < len; i++){
            if(!new File(partPath + File.separator + i + ".mp3").exists()){
                //某部分文件不存在，直接生成一段静音后拼接文件
                CreateObjUtil.createMuteViode(Double.valueOf(time[i]), partPath + File.separator + i + ".mp3");
            }
        }

        //拼接所有音频文件
        if(time.length > 2){
            //若是多部分，两个两个合并，最后合成最终文件
            for(int i = 1, len = time.length; i < len; i++){
                if(i == 1){
//                    FileUtils.deleteFile(partPath + File.separator + i + "muteSound.mp3");

                    CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + ".mp3", partPath + File.separator + i + ".mp3",
                            partPath + File.separator + i + "muteSound.mp3");
                }else if(i == len - 1){
                    CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + "muteSound.mp3", partPath + File.separator + i + ".mp3",
                            path + File.separator + originalFileName);
                }else {
                    CreateObjUtil.mergeVideo(partPath + File.separator + (i - 1) + "muteSound.mp3", partPath + File.separator + i + ".mp3",
                            partPath + File.separator + i + "muteSound.mp3");
                }
            }
        }else if(time.length == 2){
            //若只有两部分，直接合并成最终文件
            CreateObjUtil.mergeVideo(partPath + File.separator + "0.mp3", partPath + File.separator + "1.mp3", path + File.separator + originalFileName);
        }else {
            FileUtils.copyFile(partPath + File.separator + "0.mp3", path + File.separator + originalFileName, true);
        }

        Map map = new HashMap();
        map.put("screencapVoiceSoundsyncFileName", originalFileName);
        String proVideo = "voice/voice"+sceneNum+"/"+originalFileName;
        map.put("screencapVoiceSoundsync", proVideo);
        map.put("uploadVoiceSoundsync", 1);
        map.put("screencapVoiceType", "soundsync");
        map.put("version", scenejson.getIntValue("version")+1);
        FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneNum + File.separator + "scene.json", map);
        return ResultData.ok("voice/voice"+sceneNum+"/"+originalFileName);
    }

    @Override
    public ResultData deleteScreencapVoice(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String scenePath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String str = FileUtils.readFile(scenePath);
        JSONObject json = new JSONObject();
        if(str!=null){
            json = JSONObject.parseObject(str);
        }
        else{
            File file = new File(scenePath);
            if(!file.getParentFile().exists())
            {
                file.getParentFile().mkdirs();
            }
            if(!file.exists())
            {
                file.createNewFile();
            }
        }
        log.info("type:" + base.getType());
        if("soundsync".equals(base.getType())){
            FileUtils.deleteFile(ConstantFilePath.SCENE_PATH+json.getString("screencapVoiceSoundsync"));
            json.put("screencapVoiceSoundsyncFileName", "");
            json.put("screencapVoiceSoundsync", "");
            json.put("version", json.getIntValue("version")+1);
            FileUtils.deleteFile(scenePath);
            FileUtils.writeFile(scenePath, json.toString());
            return ResultData.ok();
        }

        if("sound".equals(base.getType())){
            FileUtils.deleteFile(ConstantFilePath.SCENE_PATH+json.getString("screencapVoiceSound"));
            json.put("screencapVoiceSoundFileName", "");
            json.put("screencapVoiceSound", "");
            json.put("version", json.getIntValue("version")+1);
            FileUtils.deleteFile(scenePath);
            FileUtils.writeFile(scenePath, json.toString());
            return ResultData.ok();
        }

        String path = ConstantFilePath.SCENE_PATH+json.getString("screencapVoiceSrc");
        log.info("path:" + ConstantFilePath.SCENE_PATH+json.getString("screencapVoiceSrc"));
        FileUtils.deleteFile(path);

        json.put("screencapVoiceFileName", "");
        json.put("screencapVoiceSrc", "");
        json.put("version", json.getIntValue("version")+1);
        log.info("scenePath:" + scenePath);
        FileUtils.deleteFile(scenePath);
        FileUtils.writeFile(scenePath, json.toString());
        return ResultData.ok();
    }

    @Override
    public ResultData deleteScreencap(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        String imagesPath = String.format(ConstantFilePath.IMAGESBUFFER_FORMAT, scenePro.getNum());
        String sceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String tourListPath = String.format(ConstantFilePath.TOURLIST_PATH_FORMAT, scenePro.getNum());
        String capPath = String.format(ConstantFilePath.TOURLIST_FOLDER_PATH_FORMAT, scenePro.getNum());
        String imgPath = imagesPath + ConstantFileName.TOURLIST_FOLDER;
        File file1 = new File(capPath);
        String[] strs = file1.list();
        //删除screenCap对应的json数据
        if(strs!=null) {
            for(int i=0;i<strs.length;++i) {
                if(strs[i].indexOf(ConstantFileName.SCREEN_CRP_DATAFILE)>-1) {
                    FileUtils.deleteFile(capPath+File.separator+strs[i]);
                }
            }
        }
        String tourList = FileUtils.readFile(tourListPath);
        JSONArray tourJsons = new JSONArray();
        if(tourList!=null) {
            tourJsons = JSONArray.parseArray(tourList);
        }
        for(int i=0;i<tourJsons.size();++i) {
            String filePath = imgPath + File.separator +"guide"+i+".jpg";
            FileUtils.deleteFile(filePath);
        }
        FileUtils.deleteFile(tourListPath);

        String strsceneInfos = FileUtils.readFile(sceneJsonPath);
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("screencapLen", 0);
        map.put("uploadTourList", 1);
        map.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeJsonFile(sceneJsonPath, map);

        return ResultData.ok();
    }

    @Override
    public ResultData saveTourList(SceneEditParamVO base) throws Exception{
        if(StrUtil.isEmpty(base.getNum()) || StrUtil.isEmpty(base.getTourList()) ||
                StrUtil.isEmpty(base.getScreencapLen())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        log.info("editScene/saveTourList：生成tourList.json文件");
        String tourListPath = String.format(ConstantFilePath.TOURLIST_PATH_FORMAT, scenePro.getNum());
        FileUtils.writeFile(tourListPath, base.getTourList());

        String sceneJsonPath = String.format(ConstantFilePath.SCENE_PATH_FORMAT, scenePro.getNum());
        String strsceneInfos = FileUtils.readFile(sceneJsonPath);
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("screencapLen", String.valueOf(base.getScreencapLen()));
        map.put("uploadTourList", 1);
        map.put("version", scenejson.getIntValue("version")+1);
        FileUtils.writeJsonFile(sceneJsonPath, map);

        return ResultData.ok();
    }

    @Override
    public ResultData saveSceneInfo(SceneEditParamVO base) throws Exception{

        if(StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = this.findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());



        int type = Integer.valueOf(base.getSceneType());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        //上传七牛
        Map<String,String> map = new HashMap<>();

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());

        //处理漫游数据
        this.dealTour(base, scenejson, map, dataBuffer, imagesBuffer);

        //判断scene.json是否有uploadVoiceSrc上传普通版音频
        if(scenejson.containsKey("uploadVoiceSrc") && scenejson.getIntValue("uploadVoiceSrc") == 1) {
            String screencapVoiceFileName = "";
            if(scenejson.containsKey("screencapVoiceFileName")) {
                screencapVoiceFileName = scenejson.getString("screencapVoiceFileName");
            }
            String screencapVoiceSrc = "";
            if(scenejson.containsKey("screencapVoiceSrc")) {
                screencapVoiceSrc = scenejson.getString("screencapVoiceSrc");
            }

            if(screencapVoiceFileName.indexOf(".")>-1) {
                String fileName = "201810" + screencapVoiceFileName.substring(screencapVoiceFileName.lastIndexOf("."));
                String path = ConstantFilePath.SCENE_PATH + "voice" + File.separator+"voice"+base.getNum()+File.separator+fileName;
                map.put(path, "voice/voice"+base.getNum()+"/201810" +screencapVoiceFileName.substring(screencapVoiceFileName.lastIndexOf(".")));
            }
            sceneProEdit.setScreencapVoiceSrc(screencapVoiceSrc);
        }

        //判断scene.json是否有uploadVoiceSound上传专业版音频
        if(scenejson.containsKey("uploadVoiceSound") && scenejson.getIntValue("uploadVoiceSound") == 1){
            if(!StrUtil.isEmpty(scenejson.getString("screencapVoiceSound"))){
                map.put(ConstantFilePath.SCENE_PATH + scenejson.getString("screencapVoiceSound"), scenejson.getString("screencapVoiceSound"));
            }
            sceneProEdit.setScreencapVoiceSound(scenejson.getString("screencapVoiceSound"));
        }

        if(scenejson.containsKey("uploadVoiceSoundsync") && scenejson.getIntValue("uploadVoiceSoundsync") == 1){
            if(!StrUtil.isEmpty(scenejson.getString("screencapVoiceSoundsync"))){
                map.put(ConstantFilePath.SCENE_PATH + scenejson.getString("screencapVoiceSoundsync"), scenejson.getString("screencapVoiceSoundsync"));
            }
            sceneProEdit.setScreencapVoiceSoundsync(scenejson.getString("screencapVoiceSoundsync"));
        }

        if(base.getScreencapVoiceType() != null){
            scenejson.put("screencapVoiceType", base.getScreencapVoiceType());
            sceneProEdit.setScreencapVoiceType(base.getScreencapVoiceType());
        }

        if(!StrUtil.isEmpty(base.getCapData())){
            FileUtils.writeFile(dataBuffer.toString() + "capData.json", new String(base.getCapData().getBytes(), "UTF-8"));
            scenejson.put("capData", dataBuf.toString() + "capData.json");
        }

        if(!StrUtil.isEmpty(base.getFrameData())){
            FileUtils.writeFile(dataBuffer.toString() + "frameData.json", new String(base.getFrameData().getBytes(), "UTF-8"));
            scenejson.put("frameData", dataBuf.toString() + "frameData.json");
        }

        if(!StrUtil.isEmpty(base.getPlayData())){
            FileUtils.writeFile(dataBuffer.toString() + "playData.json", new String(base.getPlayData().getBytes(), "UTF-8"));
            scenejson.put("playData", dataBuf.toString() + "playData.json");
            sceneProEdit.setPlayData(dataBuf.toString() + "playData.json");
            map.put(dataBuffer.toString() + "playData.json", dataBuf.toString() + "playData.json");
        }

        if(!StrUtil.isEmpty(base.getScreencapThumb())){
            FileUtils.writeFile(dataBuffer.toString() + "screencapThumb.json", new String(base.getScreencapThumb().getBytes(), "UTF-8"));
            scenejson.put("screencapThumb", dataBuf.toString() + "screencapThumb.json");
            sceneProEdit.setScreencapThumb(dataBuf.toString() + "screencapThumb.json");
            map.put(dataBuffer.toString() + "screencapThumb.json", dataBuf.toString() + "screencapThumb.json");
        }

        if(!StrUtil.isEmpty(base.getRecordType())){
            scenejson.put("recordType", base.getRecordType());
        }

        if(!StrUtil.isEmpty(base.getMapVisi())){
            scenejson.put("mapVisi", Integer.parseInt(base.getMapVisi()));
            sceneProEditExt.setMapVisi(Integer.parseInt(base.getMapVisi()));
        }

        if(!StrUtil.isEmpty(base.getTourVisi())){
            scenejson.put("tourVisi", Integer.parseInt(base.getTourVisi()));
            sceneProEditExt.setTourVisi(Integer.parseInt(base.getTourVisi()));
        }
        if(!StrUtil.isEmpty(base.getVrVisi())){
            scenejson.put("vrVisi", Integer.parseInt(base.getVrVisi()));
            sceneProEditExt.setVrVisi(Integer.parseInt(base.getVrVisi()));
        }

        if(!StrUtil.isEmpty(base.getRulerVisi())){
            scenejson.put("rulerVisi", Integer.parseInt(base.getRulerVisi()));
            sceneProEditExt.setRulerVisi(Integer.parseInt(base.getRulerVisi()));
        }
        if(!StrUtil.isEmpty(base.getCadImgVisi())){
            scenejson.put("cadImgVisi", Integer.parseInt(base.getCadImgVisi()));
            sceneProEditExt.setCadImgVisi(Integer.parseInt(base.getCadImgVisi()));
        }

        if(!StrUtil.isEmpty(base.getPanoVisi())){
            scenejson.put("panoVisi", Integer.parseInt(base.getPanoVisi()));
            sceneProEditExt.setPanoVisi(Integer.parseInt(base.getPanoVisi()));
        }

        if(!StrUtil.isEmpty(base.getM2dVisi())){
            scenejson.put("m2dVisi", Integer.parseInt(base.getM2dVisi()));
            sceneProEditExt.setM2dVisi(Integer.parseInt(base.getM2dVisi()));
        }
        if(!StrUtil.isEmpty(base.getM3dVisi())){
            scenejson.put("m3dVisi", Integer.parseInt(base.getM3dVisi()));
            sceneProEditExt.setM3dVisi(Integer.parseInt(base.getM3dVisi()));
        }
        if(!StrUtil.isEmpty(base.getMeasureVisi())){
            scenejson.put("measureVisi", Integer.parseInt(base.getMeasureVisi()));
            sceneProEditExt.setMeasureVisi(Integer.parseInt(base.getMeasureVisi()));
        }

        if(!StrUtil.isEmpty(base.getFloorPlanAngle())){
            scenejson.put("floorPlanAngle", base.getFloorPlanAngle());
            sceneProEditExt.setFloorPlanAngle(base.getFloorPlanAngle());
        }

        if(scenejson.containsKey("uploadFloorPlanPng") && scenejson.getIntValue("uploadFloorPlanPng") == 1){
            JSONArray floorPlanPngStr = new JSONArray();
            JSONArray floorPlanPng = new JSONArray();
            switch (scenePro.getBuildType()){
                case "V2":
                    floorPlanPng.add(scenejson.getString("floorPlanPng"));
                    break;
                case "V3":
                    try {
                        floorPlanPng = scenejson.getJSONArray("floorPlanPng");
                    } catch (Exception e) {
                        // 旧的V3也是String
                        floorPlanPng.add(scenejson.getString("floorPlanPng"));
                    }
                    break;
            }
            scenejson.put("uploadFloorPlanPng", 0);
            for(int i = 0, len = floorPlanPng.size(); i < len; i++){
                map.put(ConstantFilePath.SCENE_PATH+floorPlanPng.getString(i), floorPlanPng.getString(i));
                floorPlanPngStr.add(floorPlanPng.getString(i) + "?t=" + System.currentTimeMillis());
            }
            sceneProEditExt.setFloorPlanPng(floorPlanPngStr.toJSONString());
        }

        if(scenejson.containsKey("uploadFloorJson") && scenejson.getIntValue("uploadFloorJson") == 1){
            map.put(dataBuffer.toString() + "floor.json", dataBuf.toString() + "floor.json");
            scenejson.put("uploadFloorJson", 0);
        }

        if(StrUtil.isNotEmpty(base.getEntry())) {
            //上传七牛
            map.put(imagesBuffer.toString() + "thumbBigImg.jpg", imagesBuf.toString() + "thumbBigImg.jpg");
            map.put(imagesBuffer.toString() + "thumbFishBigImg.jpg",imagesBuf.toString() + "thumbFishBigImg.jpg");
            map.put(imagesBuffer.toString() + "thumbSmallImg.jpg", imagesBuf.toString() + "thumbSmallImg.jpg");
            map.put(imagesBuffer.toString() + "smallPic.jpg", imagesBuf.toString() + "smallPic.jpg");
            sceneProEdit.setEntry(base.getEntry());

            scenejson.put("entry", base.getEntry());

            if(scenejson.containsKey("thumbImg"))
            {
                sceneProEdit.setThumbStatus(scenejson.getIntValue("thumbImg"));
            }

            if(sceneProEdit.getThumbStatus() == 1)
            {
                scenePro.setThumb(prefixAli + imagesBuf.toString() + "thumbSmallImg.jpg");
                if("aws".equals(this.type)){
                    scenePro.setThumb(ConstantUrl.PREFIX_AWS + imagesBuf.toString() + "thumbSmallImg.jpg");
                }
            }

        }

        if(base.getHotFlag() != null && "1".equals(base.getHotFlag())) {
            String str = FileUtils.readFile(dataBuffer.toString() + "hot.json");
            JSONArray jsonhots = new JSONArray();

            if(str != null&&!str.trim().equals("")) {
                jsonhots = JSONArray.parseArray(str);
            }
            String hotsids = "";
            for(int i=0;i<jsonhots.size();++i) {
                JSONObject ele = jsonhots.getJSONObject(i);
                String index = ele.getString("sid");
                hotsids+=index+",";
                if(ele.containsKey("media"))
                {
                    String fileType = ele.getString("media");
                    if(fileType.contains("photo"))
                    {
                        map.put(imagesBuffer.toString() + "hot"+index+".jpg",
                                imagesBuf.toString() + "hot"+index+".jpg");
                    }
                    if(fileType.contains("audio") || fileType.contains("voice"))
                    {
                        map.put(imagesBuffer.toString() + "hot"+index+".mp3",
                                imagesBuf.toString() + "hot"+index+".mp3");
                    }
                    if(fileType.contains("video"))
                    {
                        map.put(imagesBuffer.toString() + "hot"+index+".mp4",
                                imagesBuf.toString() + "hot"+index+".mp4");
                        map.put(imagesBuffer.toString() + "hot"+index+"-cut.jpg",
                                imagesBuf.toString() + "hot"+index+"-cut.jpg");
                    }
                }

            }
            map.put(dataBuffer.toString() + "hot.json",dataBuf.toString() + "hot.json");
            sceneProEdit.setHotsIds(hotsids);
        }

        if(StrUtil.isNotEmpty(base.getFloorLogoType())) {
            sceneProEdit.setFloorLogo(base.getFloorLogoType());
            scenejson.put("floorLogo", base.getFloorLogoType());
            if(base.getFloorLogoType().trim().equals("1")||base.getFloorLogoType().trim().equals("user")) {
                map.put(imagesBuffer.toString() + "floorLogoImg.png", imagesBuf.toString() + "floorLogoImg.png");
            }
        }

        if(StrUtil.isNotEmpty(base.getFloorLogoSize())) {
            sceneProEdit.setFloorLogoSize(Integer.valueOf(base.getFloorLogoSize()));
            scenejson.put("floorLogoSize", base.getFloorLogoSize());
        }

        if(base.getBgMusic() != null) {
            sceneProEdit.setBgMusic(base.getBgMusic());
            scenejson.put("bgMusic", base.getBgMusic());
        }

        if(base.getSceneName() != null) {
            scenePro.setSceneName(base.getSceneName());
            scenejson.put("sceneName", base.getSceneName());
        }

        if(StrUtil.isNotEmpty(base.getSceneType())) {
            if(scenePro.getSceneType() == 99){
                scenejson.put("sceneType", scenePro.getSceneType());
            }else {
                scenePro.setSceneType(type);
                scenejson.put("sceneType", base.getSceneType());
            }
        }

        if(base.getSceneDec() != null) {
            scenePro.setSceneDec(base.getSceneDec());
            scenejson.put("sceneDec", base.getSceneDec());
        }

        if(!StrUtil.isEmpty(base.getSceneKey())) {
            sceneProEdit.setSceneKey(base.getSceneKey());
            sceneProEdit.setNeedKey(1);
            scenejson.put("sceneKey", base.getSceneKey());
            scenejson.put("needKey", 1);
        }else {
            sceneProEdit.setSceneKey("");
            sceneProEdit.setNeedKey(0);
            scenejson.put("sceneKey", "");
            scenejson.put("needKey", 0);
        }

        if(!scenejson.containsKey("version")) {
            scenejson.put("version", 0);
        }
        scenejson.put("version", scenejson.getIntValue("version")+1);
        map.put(dataBuffer.toString() + "scene.json", dataBuf.toString() + "scene.json");

        sceneProEditExt.setCadInfo(scenejson.getString("cadInfo"));
        sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditExtService.updateById(sceneProEditExt);
        sceneProEdit.setVersion(scenejson.getIntValue("version"));
        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditService.updateById(sceneProEdit);

        //重建上传资源到oss
        if(sceneProEdit.getFloorEditVer() != sceneProEdit.getFloorPublishVer()){
            //上传过模型，只更新floor.json
            if(scenejson.containsKey("isUploadObj") && scenejson.getBooleanValue("isUploadObj")){
                map.put(dataBuffer.toString() + "floor.json", dataBuf.toString() + "floor.json");
                //发布重新建模场景，将floorPublishVer设为floorEditVer的值
                sceneProEdit.setFloorPublishVer(sceneProEdit.getFloorEditVer());

                scenejson.put("floorEditVer", sceneProEdit.getFloorEditVer());
                scenejson.put("floorPublishVer", sceneProEdit.getFloorEditVer());
            }else {

                String path = sceneProExt.getDataSource();
                if(path != null && !"".equals(path) && path.startsWith("http")){
                    path = ConstantFilePath.BUILD_MODEL_PATH + path.split("/")[path.split("/").length - 2];
                }
                path = path + "_edit";
                String projectNum = base.getNum();

                //读取upload文件，检验需要上传的文件是否存在
                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");
                }
                if(array != null){
                    JSONObject fileJson = null;
                    String fileName = "";
                    for(int i = 0, len = array.size(); i < len; i++){
                        fileJson = array.getJSONObject(i);
                        fileName = fileJson.getString("file");
                        //文件不存在抛出异常
                        if(!new File(path + File.separator + "results" +File.separator + fileName).exists()){
                            throw new Exception(path + File.separator + "results" +File.separator + fileName+"文件不存在");
                        }

                        //tex文件夹
                        if(fileJson.getIntValue("clazz") == 2 && !fileJson.containsKey("pack-file")){
                            map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
                                    projectNum+"/"+ConstantFileName.modelUUID+"_50k_texture_jpg_high1/"+fileName.replace("tex/", ""));
                        }

                        //2048的模型和贴图
                        if(fileJson.getIntValue("clazz") == 16){
                            map.put(path + File.separator + "results" + File.separator+ fileName,"data/data"+
                                    projectNum+ File.separator + fileName);
                        }
                    }

                    map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam.lzma");
                    map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam");

                    File file = new File(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum);
                    if(!file.exists())
                    {
                        file.mkdir();
                    }
                    log.info("计算大场景：开始上传大场景文件到阿里——"+projectNum);
                    //上传修改后的本地的缩略图
                    map.put(dataBuffer.toString() + "floor.json", dataBuf.toString() + "floor.json");

                    //发布重新建模场景，将floorPublishVer设为floorEditVer的值
                    sceneProEdit.setFloorPublishVer(sceneProEdit.getFloorEditVer());

                    scenejson.put("floorEditVer", sceneProEdit.getFloorEditVer());
                    scenejson.put("floorPublishVer", sceneProEdit.getFloorEditVer());
                }
            }

        }

        //重算全景图并上传oss或oss
        if(scenejson.containsKey("buildImages")){
            String path = sceneProExt.getDataSource();

            if(path != null && !"".equals(path) && path.startsWith("http")){
                path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
            }
            String target = path + "_images";

            File images = new File(target + File.separator + "extras/images");
            File video = new File(target + File.separator + "extras/video");

            if(scenejson.getIntValue("buildImages") == 1){
                log.info("下载vision.modeldata文件");
                if("aws".equals(this.type)){
                    FileUtils.downLoadFromUrl(ConstantUrl.PREFIX_AWS + "images/images" + scenePro.getNum() + "/vision.modeldata" + "?m="+new Date().getTime(),
                            "vision.modeldata", target + File.separator + "extras" + File.separator);
                }
                if("oss".equals(this.type)){
                    FileUtils.downLoadFromUrl(prefixAli + "images/images" + scenePro.getNum() + "/vision.modeldata" + "?m="+new Date().getTime(),
                            "vision.modeldata", target + File.separator + "extras" + File.separator);
                }
                CreateObjUtil.convertVisionmodeldataToTxt(target + File.separator + "extras" + File.separator + "vision.modeldata",
                        target + File.separator + "extras" + File.separator + "vision.txt");

                if(images.exists() && images.listFiles() != null && images.listFiles().length > 0){

                    FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
                    FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);

                    //data.json增加extras为执行重建算法
                    String data = FileUtils.readFile(target + File.separator+"data.json");
                    if(data != null){
                        JSONObject floorplanJson = new JSONObject();
                        floorplanJson.put("has_source_images", true);
                        floorplanJson.put("has_vision_txt", true);

                        JSONObject dataJson = JSONObject.parseObject(data);
                        dataJson.put("extras", floorplanJson);
                        //V5表示不需要生成high，low文件
                        dataJson.put("skybox_type", "SKYBOX_V6");
                        if(scenePro.getSceneScheme() == 11){
                            dataJson.put("skybox_type", "SKYBOX_V7");
                        }
                        dataJson.put("split_type", "SPLIT_V8");
                        //sceneScheme为3切成瓦片图
                        if(scenePro.getSceneScheme() == 3){
                            dataJson.put("skybox_type", "SKYBOX_V4");
                        }
                        FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
                    }

                    //创建文件夹软连接并且复制data.json和project.json
                    if(new File(target + File.separator + "capture").exists()){
                        new File(target + File.separator + "capture").delete();
                    }
                    if(new File(target + File.separator + "results").exists()){
                        FileUtils.delAllFile(target + File.separator + "results");
                    }
                    //下载data.fdage
                    if("aws".equals(this.type)){
                        //亚马逊保持旧方式，超链接capture
                        CreateObjUtil.createSoftConnection(path + File.separator + "capture", target + File.separator + "capture");
                    }
                    CreateObjUtil.ossUtilCp(ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_PATH, "") + "/data.fdage", target + File.separator + "capture/");

                    CreateObjUtil.build3dModel(target , "1");

                    //读取upload文件，检验需要上传的文件是否存在
                    String uploadData = FileUtils.readFile(target + File.separator + "results" +File.separator+"upload.json");
                    JSONObject uploadJson = null;
                    JSONArray array = null;
                    if(uploadData!=null) {
                        uploadJson = JSONObject.parseObject(uploadData);
                        array = uploadJson.getJSONArray("upload");
                    }
                    if(array == null){
                        throw new Exception("upload.json数据出错");
                    }
                    JSONObject fileJson = null;
                    String fileName = "";
                    for(int i = 0, len = array.size(); i < len; i++){
                        fileJson = array.getJSONObject(i);
                        fileName = fileJson.getString("file");
                        //文件不存在抛出异常
                        if(!new File(target + File.separator + "results" +File.separator + fileName).exists()){
                            throw new Exception(target + File.separator + "results" +File.separator + fileName+"文件不存在");
                        }

                        //high文件夹
                        if(fileJson.getIntValue("clazz") == 3){
                            map.put(target + File.separator + "results" +File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+"/pan/high/"+ fileName.replace("high/", ""));
                            continue;
                        }
                        //low文件夹
                        if(fileJson.getIntValue("clazz") == 4){
                            map.put(target + File.separator + "results" +File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+"/pan/low/"+ fileName.replace("low/", ""));
                            continue;
                        }

                        //tiles文件夹,亚马逊没有裁剪图片api，不需要上传4k图
                        if(fileJson.getIntValue("clazz") == 5){
                            map.put(target + File.separator + "results" + File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+ File.separator + fileName);
                            continue;
                        }

                        //tiles文件夹,亚马逊瓦片图
                        if(fileJson.getIntValue("clazz") == 7 ){
                            map.put(target + File.separator + "results" + File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+ File.separator + fileName);
                            continue;
                        }
                    }

                    for(String imagesName : images.list()){
                        //覆盖原始图片资源
                        FileUtils.copyFile(target + File.separator + "extras/images/" + imagesName,
                                path + File.separator + "caches/images/" + imagesName, true);
                        FileUtils.deleteFile(target + File.separator + "extras/images/" + imagesName);
                    }
                }

                if(video.exists() && video.listFiles() != null && video.listFiles().length > 0){
                    for(String videoName : video.list()){
                        uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName,"video/video"+
                                scenePro.getNum()+ File.separator + videoName);

                        CreateObjUtil.mp4ToFlv(target + File.separator + "extras/video/" + videoName,
                                target + File.separator + "extras/video/" + videoName.replace("mp4", "flv"));

                        uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName.replace("mp4", "flv"),"video/video"+
                                scenePro.getNum()+ File.separator + videoName.replace("mp4", "flv"));

                        //覆盖原始视频资源
                        FileUtils.copyFile(target + File.separator + "extras/video/" + videoName,
                                path + File.separator + "caches/videos/" + videoName, true);

                    }
                    FileUtils.deleteDirectory(target + File.separator + "extras/video/");
                }

            }else if(scenejson.getIntValue("buildImages") == 2){
                if(video.exists() && video.listFiles() != null && video.listFiles().length > 0){
                    for(String videoName : video.list()){
                        uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName,"video/video"+
                                scenePro.getNum()+ File.separator + videoName);

                        CreateObjUtil.mp4ToFlv(target + File.separator + "extras/video/" + videoName,
                                target + File.separator + "extras/video/" + videoName.replace("mp4", "flv"));

                        uploadToOssUtil.upload(target + File.separator + "extras/video/" + videoName.replace("mp4", "flv"),"video/video"+
                                scenePro.getNum()+ File.separator + videoName.replace("mp4", "flv"));

                        //覆盖原始视频资源
                        FileUtils.copyFile(target + File.separator + "extras/video/" + videoName,
                                path + File.separator + "caches/videos/" + videoName, true);

                    }
                    FileUtils.deleteDirectory(target + File.separator + "extras/video/");
                }
            }

            scenejson.put("imagesVersion", sceneProEditExt.getImagesVersion() + 1);
            scenejson.put("buildImages", 0);
            sceneProEditExt.setImagesVersion(sceneProEditExt.getImagesVersion() + 1);

        }

        if(scenejson.containsKey("uploadBgMusic") && scenejson.getIntValue("uploadBgMusic") == 1){
            if(StrUtil.isNotEmpty(scenejson.getString("bgMusicName"))){
                map.put(imagesBuffer.toString() + scenejson.getString("bgMusicName"), imagesBuf.toString() + scenejson.getString("bgMusicName"));
            }

            scenejson.put("uploadBgMusic", 0);
            sceneProEditExt.setBgMusicName(scenejson.getString("bgMusicName"));
        }

        if(scenejson.containsKey("uploadPanoramaImg") && scenejson.getIntValue("uploadPanoramaImg") == 1){
            String targetPath = ConstantFilePath.SCENE_PATH + "images/images" + base.getNum() + "/panorama";
            for(File targetFile : new File(targetPath).listFiles()){
                if(targetFile.isDirectory()){
                    String target = targetFile.getAbsolutePath();
                    String sid = target.substring(target.lastIndexOf(File.separator) + 1);
                    //读取upload文件，检验需要上传的文件是否存在
                    String uploadData = FileUtils.readFile(target + File.separator + "results" +File.separator+"upload.json");
                    JSONObject uploadJson = null;
                    JSONArray array = null;
                    if(uploadData!=null) {
                        uploadJson = JSONObject.parseObject(uploadData);
                        array = uploadJson.getJSONArray("upload");
                    }
                    if(array == null){
                        continue;
                    }
                    JSONObject fileJson = null;
                    String fileName = "";
                    for(int i = 0, len = array.size(); i < len; i++){
                        fileJson = array.getJSONObject(i);
                        fileName = fileJson.getString("file");
                        //文件不存在抛出异常
                        if(!new File(target + File.separator + "results" +File.separator + fileName).exists()){
                            throw new Exception(target + File.separator + "results" +File.separator + fileName+"文件不存在");
                        }

                        //high文件夹
                        if(fileJson.getIntValue("clazz") == 3){
                            map.put(target + File.separator + "results" +File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+"/panorama/" + sid + "/pan/high/"+ fileName.replace("high/", ""));
                            continue;
                        }
                        //low文件夹
                        if(fileJson.getIntValue("clazz") == 4){
                            map.put(target + File.separator + "results" +File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+"/panorama/" + sid + "/pan/low/"+ fileName.replace("low/", ""));
                            continue;
                        }

                        //tiles文件夹,亚马逊没有裁剪图片api，不需要上传4k图
                        if(fileJson.getIntValue("clazz") == 5){
                            map.put(target + File.separator + "results" + File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+ "/panorama/" + sid + File.separator + fileName);
                            continue;
                        }

                        //tiles文件夹,亚马逊瓦片图
                        if(fileJson.getIntValue("clazz") == 7 ){
                            map.put(target + File.separator + "results" + File.separator+ fileName,"images/images"+
                                    scenePro.getNum()+ File.separator + fileName);
                            continue;
                        }
                    }
                }
            }

            scenejson.put("uploadPanoramaImg", 0);
        }

        if(scenejson.containsKey("uploadPanoramaJson") && scenejson.getIntValue("uploadPanoramaJson") == 1){
            scenejson.put("uploadPanoramaJson", 0);

            map.put(dataBuffer.toString() + "link-scene.json", dataBuf.toString() + "link-scene.json");
            sceneProEditExt.setJumpScene(scenejson.getBooleanValue("jumpScene"));
        }

        log.info("scene.json路径：" + dataBuffer.toString() + "scene.json");
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        if(map.size()>0) {
            uploadToOssUtil.uploadMulFiles(map);
        }

        scenePro.setUpdateTime(Calendar.getInstance().getTime());
        this.updateById(scenePro);

        sceneProExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProExtService.updateById(sceneProExt);

        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditService.updateById(sceneProEdit);

        sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditExtService.updateById(sceneProEditExt);

        return ResultData.ok();
    }



    @Override
//    @SystemServiceLog(description = "上传场景的热点媒体文件")
    public ResultData uploadHotMedia(FileParamVO param, MultipartFile file) throws Exception {
        String sceneNum = param.getNum();
        String sid = param.getSid();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = this.findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String fileName = "hot" + sid + ".mp4";
        if (file.isEmpty())
            return ResultData.ok(fileName);

        String path = String.format(ConstantFilePath.IMAGESBUFFER_FORMAT, sceneNum);
        File targetFile = new File(path);
        if (!targetFile.exists()){
            targetFile.mkdirs();
        }

        targetFile = new File(path + File.separator + fileName);
        if (targetFile.exists()){
            FileUtils.deleteFile(path + File.separator + fileName);
        }
        file.transferTo(targetFile);

        if(targetFile.exists()){
            //获取指定视频的帧并保存为图片至指定目录
            FileUtils.executeCodecs(path + File.separator + fileName, path, "hot" + sid + "-cut");
        }

        return ResultData.ok(fileName);
    }


    @Override
    public ResultData tagSave(SaveTagsParamVO param) throws Exception {

        ScenePro scenePro = this.findBySceneNum(param.getNum());
        if (scenePro == null)
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);

        List<HotParamVO> hotDataList = param.getHotDataList();
        Map<String, String> addOrUpdateMap = new HashMap<>();
        List<String> deleteSidList = Lists.newArrayList();
        hotDataList.stream().forEach(hotData -> {
            if(hotData.getType().equals(OperationType.DELETE.code()))
                deleteSidList.add(hotData.getSid());
            else
                addOrUpdateMap.put(hotData.getSid(), hotData.getHotData());

        });

        //处理删除状态数据
        this.deleteHotData(param.getNum(), deleteSidList);

        //处理新增和修改数据
        this.addOrUpdateHotDataHandler(param.getNum(), addOrUpdateMap);

        //保存数据库
//        sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), scenePro.getId());

        return ResultData.ok();
    }

    @Override
    public ResultData addOrUpdateTag(SaveTagsParamVO param) throws Exception {

//        ScenePro scenePro = this.findBySceneNum(param.getNum());
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if (scenePlus == null)
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);

        this.addOrUpdateHotData(param.getNum(), param.getHotDataList());

        this.addOrUpdateIcons(param.getNum(), param.getIcons());

        //写入本地文件，作为备份
        this.writeHotJson(param.getNum());

        //保存数据库
        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), sceneEditInfo);
        sceneEditInfoService.updateById(sceneEditInfo);

        return ResultData.ok();
    }

    private void addOrUpdateHotData(String num, List<HotParamVO> hotDataList) throws Exception{
        Map<String, String> addOrUpdateMap = new HashMap<>();
//        hotDataList.stream().forEach(hotData -> {
//            JSONObject jsonObject = JSON.parseObject(hotData.getHotData());
//            jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis());
//            addOrUpdateMap.put(hotData.getSid(), jsonObject.toJSONString());
//        });
        int i = 0;
        for (HotParamVO hotParamVO : hotDataList) {
            JSONObject jsonObject = JSON.parseObject(hotParamVO.getHotData());
            jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
            addOrUpdateMap.put(hotParamVO.getSid(), jsonObject.toJSONString());
        }

        this.syncHotFromFileToRedis(num);

        //处理新增和修改数据
        this.addOrUpdateHotDataHandler(num, addOrUpdateMap);
    }

    private void addOrUpdateIcons(String num, List<String> icons) throws Exception{

        this.syncIconsFromFileToRedis(num);

        String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
        redisUtil.sSet(key, icons.toArray());


//        Map<String, String> addOrUpdateMap = new HashMap<>();
//        hotDataList.stream().forEach(hotData -> {
//            addOrUpdateMap.put(hotData.getSid(), hotData.getHotData());
//        });

        //处理新增和修改数据
//        this.addOrUpdateHotData(num, addOrUpdateMap);
    }

    @Override
    public ResultData deleteTag(DeleteHotParamVO param) throws Exception {

//        ScenePro scenePro = this.findBySceneNum(param.getNum());
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if (scenePlus == null)
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);

        List<String> deleteSidList = param.getSidList();


        //处理删除状态数据
        this.deleteHotData(param.getNum(), deleteSidList);

        //写入本地文件，作为备份
        this.writeHotJson(param.getNum());

        //保存数据库
        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), sceneEditInfo);
        sceneEditInfoService.updateById(sceneEditInfo);

        return ResultData.ok();
    }

    @Override
    public ResultData deleteIcons(DeleteHotIconParamVO param) throws Exception {

        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if (scenePlus == null)
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);

        List<String> fileNameList = param.getFileNameList();

        this.syncIconsFromFileToRedis(param.getNum());

        String key = String.format(RedisKey.SCENE_HOT_ICONS, param.getNum());
        redisUtil.setRemove(key, fileNameList.toArray());

        //写入本地文件，作为备份
        this.writeHotJson(param.getNum());


        return ResultData.ok();
    }

    @Override
    public ResultData listTags(String num) throws Exception{

        //保证热点数据安全性，当redis宕机导致热点数据丢失时，可以从文件中读取，恢复到redis
        this.syncHotFromFileToRedis(num);

        //保证icons数据安全性，当redis宕机导致icons数据丢失时，可以从文件中读取，恢复到redis
        this.syncIconsFromFileToRedis(num);

        JSONObject result = new JSONObject();

        //查询缓存是否包含热点数据
        String key = String.format(RedisKey.SCENE_HOT_DATA, num);
        Map<String, String> allTagsMap = redisUtil.hmget(key);
        List<JSONObject> tags = Lists.newArrayList();
        List<TagBean> tagBeanList = new ArrayList<>();
        if(CollUtil.isNotEmpty(allTagsMap)){
            allTagsMap.entrySet().stream().forEach(entry -> {
                JSONObject jsonObject = JSON.parseObject(entry.getValue());
                tagBeanList.add(
                    TagBean.builder()
                        .createTime(jsonObject.getLong("createTime"))
                        .tag(jsonObject).build());
            });
            //按创建时间倒叙排序
            tagBeanList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());

            //移除createTime字段
            tags = tagBeanList.stream().map(tagBean -> {
                JSONObject tag = tagBean.getTag();
                tag.remove("createTime");
                return tag;
            }).collect(Collectors.toList());
        }
        result.put("tags", tags);

        //查询缓存是否包含icons
        key = String.format(RedisKey.SCENE_HOT_ICONS, num);
        Set<String> icons = redisUtil.sGet(key);
        if(icons == null){
            icons = Sets.newHashSet();
        }
        List<String> iconList = this.sortIcons(tags, icons);
        result.put("icons", iconList);

        return ResultData.ok(result);
    }

    private List<String> sortIcons(List<JSONObject> tags, Set<String> icons){

        //统计使用频次
        List<IconBean> iconBeans = Lists.newArrayList();
        for (String icon : icons) {
            int count = 0;
            for (JSONObject tag : tags) {
                String sid = tag.getString("icon");
                if(StrUtil.isEmpty(sid) || !icon.equals(sid)){
                    continue;
                }
                ++count;
            }
            iconBeans.add(IconBean.builder().icon(icon).count(count).build());
        }

        //排序
        List<String> iconList = iconBeans.stream().sorted(Comparator.comparing(IconBean::getCount).reversed())
            .map(item -> {
                return item.getIcon();
            }).collect(Collectors.toList());

        return iconList;
    }

    /**
     * <p>
            保证热点数据安全性，当redis宕机导致热点数据丢失时，可以从文件中读取，恢复到redis
     * </p>
     * @author dengsixing
     * @date 2022/3/3
     **/
    private void syncHotFromFileToRedis(String num) throws Exception{

        String key = String.format(RedisKey.SCENE_HOT_DATA, num);
        boolean exist = redisUtil.hasKey(key);
        if(exist){
            return;
        }
        String lockKey = String.format(RedisLockKey.LOCK_HOT_DATA_SYNC, num);
        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
        if(!lock){
            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
        }
        try{
            exist = redisUtil.hasKey(key);
            if(exist){
                return;
            }
            String tagsFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num);
            String tagsData = FileUtils.readFile(tagsFilePath + "hot.json");
            if(StrUtil.isEmpty(tagsData)){
                return;
            }
            JSONObject jsonObject = JSON.parseObject(tagsData);
            JSONArray tagsArr = jsonObject.getJSONArray("tags");
            if(CollUtil.isEmpty(tagsArr)){
                return;
            }
            Map<String, String> map = new HashMap<>();
            for (Object o : tagsArr) {
                JSONObject jo = (JSONObject)o;
                map.put(jo.getString("sid"), jo.toJSONString());
            }
            redisUtil.hmset(key, map);
        }finally {
            redisLockUtil.unlockLua(lockKey);
        }
    }

    /**
     * <p>
     保证icons数据安全性，当redis宕机导致icons数据丢失时，可以从文件中读取，恢复到redis
     * </p>
     * @author dengsixing
     * @date 2022/3/3
     **/
    private void syncIconsFromFileToRedis(String num) throws Exception{

        String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
        boolean exist = redisUtil.hasKey(key);
        if(exist){
            return;
        }
        String lockKey = String.format(RedisLockKey.LOCK_HOT_ICONS_SYNC, num);
        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
        if(!lock){
            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
        }
        try{
            exist = redisUtil.hasKey(key);
            if(exist){
                return;
            }
            String tagsFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num);
            String tagsData = FileUtils.readFile(tagsFilePath + "hot.json");
            if(StrUtil.isEmpty(tagsData)){
                return;
            }
            JSONObject jsonObject = JSON.parseObject(tagsData);
            JSONArray iconArr = jsonObject.getJSONArray("icons");
            if(CollUtil.isEmpty(iconArr)){
                return;
            }
            redisUtil.sSet(key,  iconArr.toJavaList(String.class).toArray());
        }finally {
            redisLockUtil.unlockLua(lockKey);
        }

    }

    /**
     * <p>
        热点数据保存

     * </p>
     * @author dengsixing
     * @date 2022/3/3
     **/
    private void writeHotJson(String num) throws Exception{

        String dataKey = String.format(RedisKey.SCENE_HOT_DATA, num);
        Map<String, String> tagMap = redisUtil.hmget(dataKey);
        List<String> tagList = Lists.newArrayList();
        tagMap.entrySet().stream().forEach(entry->{
            if(StrUtil.isNotEmpty(entry.getValue())){
                tagList.add(entry.getValue());
            }
        });
        JSONObject jsonObject = new JSONObject();
        JSONArray tagJsonArr = new JSONArray();
        if(CollUtil.isNotEmpty(tagList)){
            tagList.stream().forEach(hot->{
                tagJsonArr.add(JSONObject.parseObject(hot));
            });
        }
        jsonObject.put("tags", tagJsonArr);

        String iconsKey = String.format(RedisKey.SCENE_HOT_ICONS, num);
        Set<String> iconList = redisUtil.sGet(iconsKey);
        jsonObject.put("icons", iconList);

        String hotJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "hot.json";
        String lockKey = String.format(RedisLockKey.LOCK_HOT_JSON, num);
        boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
        if(!lock){
            return;
        }
        try{
            FileUtils.writeFile(hotJsonPath, jsonObject.toJSONString());
        }finally {
            redisLockUtil.unlockLua(lockKey);
        }
    }


    private void addOrUpdateHotDataHandler(String num, Map<String, String> addOrUpdateMap){
        if(CollUtil.isEmpty(addOrUpdateMap))
            return;

        //数据验证，新增、修改状态，hotdata不能为空
        for (String sid : addOrUpdateMap.keySet()) {
            String hotData = addOrUpdateMap.get(sid);
            if(StrUtil.isEmpty(hotData)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_7004);
            }
        }

        //批量写入缓存
        String key = String.format(RedisKey.SCENE_HOT_DATA, num);
        redisUtil.hmset(key, addOrUpdateMap);
    }


    private void deleteHotData(String num, List<String> deleteSidList) throws Exception {

        this.syncHotFromFileToRedis(num);

        if(CollUtil.isEmpty(deleteSidList)){
            return;
        }

        //从redis中加载热点数据
        String key = String.format(RedisKey.SCENE_HOT_DATA, num);
        List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
        if(CollUtil.isEmpty(deletDataList))
            return;
        String userDataPath = String.format(UploadFilePath.USER_EDIT_PATH, num);

        //删除图片音频视频等资源文件
        for (String data : deletDataList) {
            if(StrUtil.isBlank(data)){
                continue;
            }
            JSONObject jsonObject = JSON.parseObject(data);
            String sid = jsonObject.getString("sid");
            if(jsonObject.containsKey("media")){
                String fileType = jsonObject.getString("media");
                if(fileType.contains("photo"))
                {
                    uploadToOssUtil.delete(userDataPath + "hot"+sid+".jpg");
                }
                if(fileType.contains("audio") || fileType.contains("voice"))
                {
                    uploadToOssUtil.delete(userDataPath + "hot"+sid+".mp3");
                }
                if(fileType.contains("video"))
                {
                    uploadToOssUtil.delete(userDataPath + "hot"+sid+".mp4");
                }
            }
            if(!StorageType.AWS.code().equals(this.type)){
                JSONObject paramData = new JSONObject();
                paramData.put("hotId", sid);
                JSONObject hotListJson = JSONObject.parseObject(OkHttpUtils.httpGet(hotDomainList));
                if(hotListJson != null){
                    JSONArray hotListArray = hotListJson.getJSONArray("data");
                    if(hotListArray != null){
                        for(int l = 0, len = hotListArray.size(); l < len; l++){
                            OkHttpUtils.httpPostJson(hotListArray.getString(l) + hotDelete + "?hotId=" + sid
                                , paramData.toJSONString());
                        }

                    }
                }
            }
        }


        //从redis中移除热点数据
        redisUtil.hdel(key, deleteSidList.toArray());
    }


    @Override
//    @SystemServiceLog(description = "保存场景热点")
    public ResultData saveShopHot(SceneEditParamVO base) throws Exception {
        if(StrUtil.isEmpty(base.getType())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        String fileName = "shopHot.json";

        String sid = base.getSid();

        ScenePro scenePro = findBySceneNum(base.getNum());
        if (scenePro == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }

        JSONObject jsonhot = JSONObject.parseObject(base.getHotData());

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String str = FileUtils.readFile(dataBuffer.toString() + fileName);

        JSONArray jsonhots = null;
        if (StrUtil.isNotEmpty(str)) {
            jsonhots = JSONArray.parseArray(str);
        }else {
            File file = new File(dataBuffer.toString() + fileName);
            if(!file.getParentFile().exists()){
                file.getParentFile().mkdirs();
            }
            if(!file.exists()){
                file.createNewFile();
            }
            jsonhots = new JSONArray();
        }

        //添加或者修改
        if("1".equals(base.getType())){
            sid = jsonhot.getString("sid");
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
            jsonhots.add(jsonhot);
        }
        else if("0".equals(base.getType())){
            sid = jsonhot.getString("sid");
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
        }
        else if("-1".equals(base.getType())){
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
        }

        for(int i=0;i<jsonhots.size();++i){
            JSONObject ele = jsonhots.getJSONObject(i);
            if(ele.getString("sid").equals(sid)){
                if("-1".equals(base.getType())){
                    jsonhots.remove(i);
                    if(ele.containsKey("media")){
                        String fileType = ele.getString("media");
                        if(fileType.contains("photo"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "hot"+sid+".jpg");
                        }
                        if(fileType.contains("audio") || fileType.contains("voice"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "hot"+sid+".mp3");
                        }
                        if(fileType.contains("video"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "hot"+sid+".mp4");
                        }
                    }
                }
                else if("0".equals(base.getType())){
                    jsonhots.set(i, jsonhot);
                }
                break;
            }
        }

        FileUtils.deleteFile(dataBuffer.toString() + fileName);
        File dataPath = new File(dataBuffer.toString());
        if(!dataPath.exists()){
            dataPath.mkdirs();
        }
        FileUtils.writeFile(dataBuffer.toString() + fileName, jsonhots.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null){
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
        return ResultData.ok();
    }

    @Override
    public ResultData saveOverlay(SceneEditParamVO base) throws Exception {
        if(StrUtil.isEmpty(base.getType())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        String sid = base.getSid();

        ScenePro scenePro = findBySceneNum(base.getNum());
        if (scenePro == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        if (sceneProEdit == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());

        //需要操作的数据
        JSONObject jsonOverlay = JSONObject.parseObject(base.getOverlayData());

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String str = sceneProEditExt.getOverlay();
        JSONArray jsonOverlays = null;
        if (StrUtil.isNotEmpty(str)) {
            jsonOverlays = JSONArray.parseArray(str);
        }else {
            jsonOverlays = new JSONArray();
        }

        //添加或者修改
        if("1".equals(base.getType())){
            sid = jsonOverlay.getString("sid");
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
            jsonOverlays.add(jsonOverlay);
        }
        else if("0".equals(base.getType())){
            sid = jsonOverlay.getString("sid");
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
        }
        else if("-1".equals(base.getType())){
            if(StrUtil.isEmpty(sid)){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
            }
        }

        for(int i=0;i<jsonOverlays.size();++i){
            JSONObject ele = jsonOverlays.getJSONObject(i);
            if(ele.getString("sid").equals(sid)){
                if("-1".equals(base.getType())){
                    jsonOverlays.remove(i);
                    if(ele.containsKey("media")){
                        String fileType = ele.getString("media");
                        if(fileType.contains("photo"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "overlay"+sid+".jpg");
                        }
                        if(fileType.contains("audio") || fileType.contains("voice"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "overlay"+sid+".mp3");
                        }
                        if(fileType.contains("video"))
                        {
                            FileUtils.deleteFile(imagesBuffer.toString() + "overlay"+sid+".mp4");
                        }
                    }
                }
                else if("0".equals(base.getType())){
                    jsonOverlays.set(i, jsonOverlay);
                }
                break;
            }
        }

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null){
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        scenejson.put("overlay", jsonOverlays.toString());
        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        sceneProEdit.setVersion(scenejson.getIntValue("version") + 1);
        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditExt.setOverlay(jsonOverlays.toString());
        sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditService.updateById(sceneProEdit);
        sceneProEditExtService.updateById(sceneProEditExt);

        return ResultData.ok();
    }

    @Override
    public ResultData uploadOverlayMedia(FileParamVO param, MultipartFile file) throws Exception {
        String sceneNum = param.getNum();
        String sid = param.getSid();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        String fileName = "overlay" + sid + ".mp4";
        if (!file.isEmpty()){

            String path = ConstantFilePath.SCENE_PATH + "images" + File.separator + "images" + sceneNum;
            File targetFile = new File(path);
            if (!targetFile.exists()){
                targetFile.mkdirs();
            }

            targetFile = new File(path + File.separator + fileName);
            if (targetFile.exists()){
                FileUtils.deleteFile(path + File.separator + fileName);
            }
            file.transferTo(targetFile);

            CreateObjUtil.mp4ToFlv(path + File.separator + fileName, path + File.separator + fileName.replace("mp4", "flv"));

            uploadToOssUtil.upload(path + File.separator + fileName, "images"+File.separator+"images"+sceneNum + File.separator + fileName);
            uploadToOssUtil.upload(path + File.separator + fileName.replace("mp4", "flv"), "images"+File.separator+"images"+sceneNum + File.separator + fileName.replace("mp4", "flv"));
        }

        return ResultData.ok(fileName);
    }

    @Override
//    @SystemServiceLog(description = "保存场景热点")
    public ResultData saveScreencapData(SceneEditParamVO base) throws Exception {
        if(StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        if(base.getScreencapVoiceType() != null){
            scenejson.put("screencapVoiceType", base.getScreencapVoiceType());
        }

        if(!StrUtil.isEmpty(base.getCapData())){
            FileUtils.writeFile(dataBuffer.toString() + "capData.json", new String(base.getCapData().getBytes(), "UTF-8"));
            scenejson.put("capData", dataBuf.toString() + "capData.json");
        }

        if(!StrUtil.isEmpty(base.getFrameData())){
            FileUtils.writeFile(dataBuffer.toString() + "frameData.json", new String(base.getFrameData().getBytes(), "UTF-8"));
            scenejson.put("frameData", dataBuf.toString() + "frameData.json");
        }

        if(!StrUtil.isEmpty(base.getPlayData())){
            FileUtils.writeFile(dataBuffer.toString() + "playData.json", new String(base.getPlayData().getBytes(), "UTF-8"));
            scenejson.put("playData", dataBuf.toString() + "playData.json");
        }

        if(!StrUtil.isEmpty(base.getScreencapThumb())){
            FileUtils.writeFile(dataBuffer.toString() + "screencapThumb.json", new String(base.getScreencapThumb().getBytes(), "UTF-8"));
            scenejson.put("screencapThumb", dataBuf.toString() + "screencapThumb.json");
        }

        if(!StrUtil.isEmpty(base.getRecordType())){
            scenejson.put("recordType", base.getRecordType());
        }

        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
        return ResultData.ok();
    }

    @Override
//    @SystemServiceLog(description = "保存热点可见性的数据")
    public ResultData saveTagsVisible(SaveTagsVisibleParamVO param) throws Exception {

        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if (scenePlus == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }
        JSONArray visiblePanos = JSONArray.parseArray(param.getData());

        //如果redis找不到，就从本地文件中reload
        this.syncHotFromFileToRedis(param.getNum());

        //从缓存中获取热点数据，如果为空，抛出异常
        String key = String.format(RedisKey.SCENE_HOT_DATA, param.getNum());
        Map<String, String> map = redisUtil.hmget(key);
        if (CollUtil.isEmpty(map)) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_7005);
        }
        List<Entry<String, String>> allTags = map.entrySet().stream().filter(item -> {
            if (StrUtil.isBlank(item.getValue())) {
                return false;
            }
            return true;
        }).collect(Collectors.toList());

        if (CollUtil.isEmpty(allTags)) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_7005);
        }

        allTags.stream().forEach(entry->{
            JSONObject hot = JSON.parseObject(entry.getValue());
            visiblePanos.stream().forEach(item->{
                if (hot.getString("sid").equals(((JSONObject) item).getString("sid"))) {
                    hot.put("visiblePanos", ((JSONObject) item).getJSONArray("value"));
                    hot.put("isHidden", ((JSONObject) item).getBoolean("isHidden"));
                    entry.setValue(hot.toJSONString());
                }
            });
        });

        //更新版本号
        SceneEditInfo editInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        sceneEditInfoService.upgradeVersionById(editInfo.getId());

        //放入缓存
        Map<String, String> finalMap = new HashMap<>();
        allTags.stream().forEach(entry->{
            finalMap.put(entry.getKey(), entry.getValue());
        });
        redisUtil.hmset(key, finalMap);

        //写入本地文件，作为备份，以防redis数据丢失
        this.writeHotJson(param.getNum());

        return ResultData.ok();
    }

    @Override
//    @SystemServiceLog(description = "漫游可行")
    public ResultData saveRoam(BaseDataParamVO param) throws Exception {

//        ScenePro scenePro = this.findBySceneNum(param.getNum());
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
        if (scenePlus == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }

        JSONArray inputData = JSONObject.parseArray(param.getData());

        String localDataPath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, param.getNum());
        File directory = new File(localDataPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        String viewImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, param.getNum());
        String modeldataUrl = ossUrlPrefix + viewImagesPath + "vision.modeldata?t=" + System.currentTimeMillis();

        //如果是云存储，将vision.modeldata下载到本地，如果是本地存储，场景计算完就已经将这个文件拷贝到编辑目录了存在这个文件了，不需要再下载
        if(!StorageType.LOCAL.code().equals(this.type)){
            FileUtils.downLoadFromUrl(modeldataUrl, "vision.modeldata", localDataPath);
        }

        //检查vision.modeldata本地是否存在，不存在抛出异常
        File file = new File(localDataPath + "vision.modeldata");
        if(!file.exists()) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5012);
        }
        //将vision.modeldata解压缩至vision.json
        ConvertUtils.convertVisionModelDataToTxt(localDataPath + "vision.modeldata", localDataPath + "vision.json");

        String str = FileUtils.readFile(localDataPath + "vision.json");
        JSONObject json = JSONObject.parseObject(str);
        JSONArray panos = json.getJSONArray("sweepLocations");
        for (int i = 0; i < panos.size(); ++i) {
            JSONObject pano = panos.getJSONObject(i);
            for (int j = 0; j < inputData.size(); ++j) {
                JSONObject jo = inputData.getJSONObject(j);
                String currentPanoId = jo.getString("panoID");
                JSONArray visibles = jo.getJSONArray("visibles");
                JSONArray visibles3 = jo.getJSONArray("visibles3");
                if (pano.getString("uuid").equals(currentPanoId)) {
                    pano.put("visibles", visibles);
                    pano.put("visibles3", visibles3);
                }
            }
        }
        FileUtils.deleteFile(localDataPath + "vision.json");
        FileUtils.deleteFile(localDataPath + "vision.modeldata");
        FileUtils.writeFile(localDataPath + "vision.json", json.toString());
        ConvertUtils.convertTxtToVisionModelData(localDataPath + "vision.json", localDataPath + "vision.modeldata");
        uploadToOssUtil.upload(localDataPath + "vision.modeldata", viewImagesPath + "vision.modeldata");

        //更新版本号
        SceneEditInfo editInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        if(Objects.isNull(editInfo)){
            editInfo = new SceneEditInfo();
            editInfo.setScenePlusId(scenePlus.getId());
            sceneEditInfoService.save(editInfo);
        }else{
            sceneEditInfoService.upgradeVersionById(editInfo.getId());
        }

        //更新scene.json版本号
        sceneEditInfoService.upgradeVersionToSceneJson(param.getNum());


        return ResultData.ok();
    }

    @Override
    public ResultData uploadShareLogo(SceneEditParamVO base, MultipartFile file) throws Exception {
        if(file == null || StrUtil.isEmpty(base.getNum())){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = findBySceneNum(base.getNum());
        if (scenePro == null ) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String fileName = "";
        if (!file.isEmpty()&&file.getSize() > 0) {
            //文件上传的位置可以自定义
            System.out.println("上传分享的logo");
            String path = imagesBuffer.toString();
            File targetFile = new File(path);
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }
            fileName = file.getOriginalFilename();
            targetFile = new File(path + fileName);
            int count = 1;
            // 保存
            synchronized(this)
            {
                file.transferTo(targetFile);
            }

            SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());

//            Map<String, Object> map = new HashMap<>();
//            map.put("shareLogo", imagesBuf.toString() + fileName);
//            map.put("version", sceneProEdit.getVersion()+1);
//            FileUtils.writeJsonFile(dataBuffer.toString() + "scene.json", map);

            sceneProEdit.setShareLogo(imagesBuf.toString() + fileName);
            sceneProEdit.setVersion(sceneProEdit.getVersion()+1);
            sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
            sceneProEditService.updateById(sceneProEdit);
            if("V2".equals(scenePro.getBuildType())){
                MatrixToImageWriterUtil.createQRCode(mainUrl + sceneProUrl + scenePro.getNum(), ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+scenePro.getNum()+".png", true,  path + File.separator + fileName);
                MatrixToImageWriterUtil.createQRCode(mainUrl + sceneProUrl + scenePro.getNum() + "&lang=en", ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+scenePro.getNum()+"_en.png", true, path + File.separator + fileName);
            }
            if("V3".equals(scenePro.getBuildType())){
                MatrixToImageWriterUtil.createQRCode(mainUrl + sceneProNewUrl + scenePro.getNum(), ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+scenePro.getNum()+".png", true, path + File.separator + fileName);
                MatrixToImageWriterUtil.createQRCode(mainUrl + sceneProNewUrl + scenePro.getNum() + "&lang=en", ConstantFilePath.BASE_PATH + File.separator + "sceneQRcode/"+scenePro.getNum()+"_en.png", true, path + File.separator + fileName);
            }
        }
        return ResultData.ok(imagesBuf.toString() + fileName);
    }

    @Override
    public ResultData uploadPic(FileParamVO param, MultipartFile file) throws Exception{
        String sceneNum = param.getNum();
        String folderName = param.getFolderName();
        String toOss = param.getToOss();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        if (file.isEmpty() && file.getSize() <= 0) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }

        //文件上传的位置可以自定义
        String path = ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneNum;
        if(StrUtil.isNotEmpty(folderName)) {
            path = path+File.separator + folderName;
        }
        File targetFile = new File(path);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        targetFile = new File(path + File.separator + fileName);
        // 保存
        synchronized(this)
        {
            if(targetFile.exists())
            {
                FileUtils.deleteFile(path + File.separator + fileName);
            }
            file.transferTo(targetFile);
        }

        if(toOss != null && "1".equals(toOss)){
            uploadToOssUtil.upload(path + File.separator + fileName, "images"+File.separator+"images"+sceneNum + File.separator + fileName);
        }

        return ResultData.ok(targetFile.getName());
    }

    @Override
    public ResultData uploadHotJsonToOss(SceneEditParamVO param) throws Exception {
        String sceneNum = param.getNum();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        String path = ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+sceneNum;
        uploadToOssUtil.upload(path + File.separator + "hot.json", "data"+File.separator+"data"+sceneNum + File.separator + "hot.json");

        return ResultData.ok();
    }

    @Override
    public ResultData deleteOss(FileParamVO param) throws Exception {
        uploadToOssUtil.deleteFile(param.getFilePath());
        return ResultData.ok();
    }

    @Override
    public ResultData uploadFloorplanPng(FileParamVO param, MultipartFile[] file) throws Exception{
        String sceneNum = param.getNum();
        String cadInfo = param.getCadInfo();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        if (file.length <= 0) {
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());


        //文件上传的位置可以自定义
        String path = ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneNum;
        File targetFile = new File(path);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String fileName = "";
        JSONArray floorPlanPngArr = new JSONArray();
        for (MultipartFile multipartFile : file) {
            fileName = multipartFile.getOriginalFilename();
            targetFile = new File(path + File.separator + fileName);
            // 保存
            synchronized(this)
            {
                if(targetFile.exists())
                {
                    FileUtils.deleteFile(path + File.separator + fileName);
                }
                multipartFile.transferTo(targetFile);
            }
            floorPlanPngArr.add("images"+File.separator+"images"+sceneNum + File.separator + fileName);
        }

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("floorPlanPng", floorPlanPngArr);
        map.put("uploadFloorPlanPng", 1);
        map.put("version", scenejson.getIntValue("version")+1);

        if(StrUtil.isNotEmpty(cadInfo)){
            map.put("cadInfo", cadInfo);
        }
        FileUtils.writeJsonFile(dataBuffer.toString() + "scene.json", map);

        return ResultData.ok(floorPlanPngArr);
    }

    @Override
    public void updateTime(String sceneNum, Long space, int payStatus, String videos, long computeTime) {

        List<ScenePro> list = this.list(new LambdaQueryWrapper<ScenePro>().eq(ScenePro::getNum, sceneNum));
        if(CollUtil.isEmpty(list))
            return;

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

        this.update(new LambdaUpdateWrapper<ScenePro>()
                .in(ScenePro::getId, sceneProIds)
                .set(ScenePro::getSceneStatus, SceneStatus.NO_DISPLAY.code())
                .set(ScenePro::getCreateTime, Calendar.getInstance().getTime())
                .set(ScenePro::getUpdateTime, Calendar.getInstance().getTime())
                .set(ScenePro::getPayStatus, payStatus)
                .set(ScenePro::getVideos, videos));

        sceneProExtService.update(new LambdaUpdateWrapper<SceneProExt>()
                .in(SceneProExt::getSceneProId, sceneProIds)
                .set(SceneProExt::getSpace, space)
                .set(SceneProExt::getComputeTime, computeTime));
    }

    @Override
    public void updateTime2(String sceneNum, String videos, long computeTime) {
        List<ScenePro> list = this.list(new LambdaQueryWrapper<ScenePro>().eq(ScenePro::getNum, sceneNum));
        if(CollUtil.isEmpty(list))
            return;

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

        this.update(new LambdaUpdateWrapper<ScenePro>()
                .in(ScenePro::getId, sceneProIds)
                .set(ScenePro::getSceneStatus, SceneStatus.NO_DISPLAY.code())
                .set(ScenePro::getCreateTime, Calendar.getInstance().getTime())
                .set(ScenePro::getUpdateTime, Calendar.getInstance().getTime())
                .set(ScenePro::getVideos, videos));

        sceneProExtService.update(new LambdaUpdateWrapper<SceneProExt>()
                .in(SceneProExt::getSceneProId, sceneProIds)
                .set(SceneProExt::getComputeTime, computeTime));
    }

    @Override
    public SceneVO findLatestOneByUserId(Long userId) {
        return baseMapper.findLatestOneByUserId(userId);
    }

    @Override
    public void updateUserIdByCameraId(Long userId, Long cameraId) {
        this.update(new LambdaUpdateWrapper<ScenePro>()
                .eq(ScenePro::getCameraId, cameraId)
                .set(ScenePro::getUserId, userId));
    }

    @Override
    public List<SceneProPO> findByCameraIdPro(Long cameraId) {
        return baseMapper.findByCameraIdPro(cameraId);
    }

    @Override
    public void updateCameraIdByCameraIdPro(Long oldCameraId, Long cameraId) {
        List<ScenePro> list = this.list(
                new LambdaQueryWrapper<ScenePro>()
                        .select(ScenePro::getId)
                        .eq(ScenePro::getCameraId, oldCameraId));
        if(CollUtil.isEmpty(list))
            return;

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

        this.update(new LambdaUpdateWrapper<ScenePro>()
                .eq(ScenePro::getCameraId, oldCameraId)
                .set(ScenePro::getCameraId, cameraId)
                .set(ScenePro::getPayStatus, PayStatus.NO_CAPACITY.code()));
    }

    @Override
    public void updateRecStatus(String unicode) {

        List<SceneProExt> list = sceneProExtService.list(
                new LambdaQueryWrapper<SceneProExt>()
                        .like(SceneProExt::getDataSource, "%" + unicode + "%"));
        if(CollUtil.isEmpty(list)){
            return ;
        }

        List<Long> sceneProIds = list.stream().map(sceneProExt -> {
            return sceneProExt.getSceneProId();
        }).collect(Collectors.toList());

        this.update(new LambdaUpdateWrapper<ScenePro>()
                .in(ScenePro::getId, sceneProIds)
                .set(ScenePro::getTbStatus, TbStatus.DELETE.code()));
    }

    @Override
    public SceneProPO findByFileId(String fileId) {
        return baseMapper.findByFileId(fileId);
    }

    @Override
    public List<ScenePro> findTempScenes() throws Exception {
        return baseMapper.findTempScenes();
    }

    @Override
    public List<String> findByCameraId(Long cameraId) throws Exception {
        List<ScenePro> list = this.list(new LambdaQueryWrapper<ScenePro>()
                .select(ScenePro::getWebSite)
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .eq(ScenePro::getCameraId, cameraId));
        if(CollUtil.isEmpty(list))
            return null;

        return list.stream().map(scenePro -> {
            return scenePro.getWebSite();
        }).collect(Collectors.toList());
    }

    @Override
    public ResultData uploadLogoBottomStatus(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        String status = param.getStatus();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(status)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        if(sceneProEdit == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());
        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }


        scenejson.put("showLogoBottom", Integer.valueOf(status));
        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        sceneProEdit.setVersion(scenejson.getIntValue("version") + 1);
        sceneProEdit.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditExt.setShowLogoBottom(Integer.valueOf(status));
        sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProEditExtService.updateById(sceneProEditExt);
        sceneProEditService.updateById(sceneProEdit);

        return ResultData.ok();
    }

    @Override
    public ResultData uploadObjAndImg(String num, MultipartFile file) throws Exception{
        if(StrUtil.isEmpty(num)){
            throw new BusinessException(ServerCode.PARAM_REQUIRED, "num");
        }
        if(!file.getOriginalFilename().endsWith(".zip")){
            throw new BusinessException(ErrorCode.FAILURE_CODE_7015);
        }

//        ScenePro scenePro = this.findBySceneNum(num);
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
        if(scenePlus == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
//        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());

        //文件上传的位置可以自定义
        String path = scenePlusExt.getDataSource() + "_obj2txt";
        String zipPath = path + "/zip/";
        String filePath =  path + "/extras/";
        String resultPath = path + "/results/";

//        String path = "F:\\uploadModel" + "_obj2txt";
//        String zipPath = path + "\\zip\\";
//        String filePath =  path + "\\extras\\";
//        String resultPath = path + "\\results\\";

        //压缩文件处理：解压缩，解压缩后复制等操作
        this.objAndImgFileHandler(resultPath, filePath, zipPath, file);

        //创建data.json
        this.writeDataJson(path);

        //调用算法,不同的类型调用不同的算法
        if("V2".equals(scenePlusExt.getBuildType())){
            CreateObjUtil.objToTxt(path , "1");
        }
        if("V3".equals(scenePlusExt.getBuildType())){
            CreateObjUtil.build3dModel(path , "1");
        }

        //算法计算完后，生成压缩文件，上传到oss
        this.uploadFileofterRebuildPanoram(path, num);

        //更新版本信息
        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
        if(Objects.isNull(sceneEditInfo)){
            sceneEditInfo = new SceneEditInfo();
            sceneEditInfo.setScenePlusId(scenePlus.getId());
            sceneEditInfo.setFloorPublishVer(1);
            sceneEditInfo.setFloorEditVer(1);
            sceneEditInfo.setIsUploadObj(CommonStatus.YES.code());
            sceneEditInfoService.save(sceneEditInfo);
        }else{
            sceneEditInfoService.update(
                new LambdaUpdateWrapper<SceneEditInfo>()
                    .setSql("version = version + 1")
                    .setSql("floor_edit_ver = floor_edit_ver + 1")
                    .setSql("floor_publish_ver = floor_publish_ver + 1")
                    .set(SceneEditInfo::getIsUploadObj, CommonStatus.YES.code())
                    .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
        }

        return ResultData.ok();
    }

    private void uploadFileofterRebuildPanoram(String path, String sceneNum) throws Exception {
        //因为共享目录有延迟，这里循环检测算法是否计算完毕3次，每次隔五秒
        String uploadJsonPath = path + File.separator + "results" +File.separator+"upload.json";
        boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, maxCheckTimes, waitTime);
        if(!exist){
            throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
        }
        String uploadData = FileUtils.readFile(uploadJsonPath);
        JSONObject uploadJson = null;
        JSONArray array = null;
        if(uploadData!=null) {
            uploadJson = JSONObject.parseObject(uploadData);
            array = uploadJson.getJSONArray("upload");
        }

        Map<String,String> map = new HashMap<String,String>();
        JSONObject fileJson = null;
        String fileName = "";
        String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
        for(int i = 0, len = array.size(); i < len; i++) {
            fileJson = array.getJSONObject(i);
            fileName = fileJson.getString("file");
            //文件不存在抛出异常
            if (!new File(path + File.separator + "results" + File.separator + fileName).exists()) {
                throw new Exception(path + File.separator + "results" + File.separator + fileName + "文件不存在");
            }

            //tex文件夹
            if (fileJson.getIntValue("clazz") == 15) {
                map.put(path + File.separator + "results" + File.separator + fileName,
                    imgViewPath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/" + fileName.replace("tex/", ""));

                // TODO: 2022/2/17 这里复制一份到本地，不知道需不需要，先注释掉
                //复制一份到images本地
//                FileUtils.copyFile(path + File.separator + "results" +File.separator + fileName,
//                    ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneNum + File.separator +
//                        ConstantFileName.modelUUID + "_50k_texture_jpg_high1/" + fileName.replace("tex/", ""), true);
                continue;
            }
        }

        CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam");
        CreateObjUtil.convertDamToLzma(path + File.separator + "results");
        CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", imgViewPath +ConstantFileName.modelUUID+"_50k.dam.lzma");
        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", imgViewPath+ConstantFileName.modelUUID+"_50k.dam");

        uploadToOssUtil.uploadMulFiles(map);

        // TODO: 2022/2/17 这里复制一份到本地，不知道需不需要，先注释掉
//        FileUtils.copyFile(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam",
//            ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneNum + File.separator + ConstantFileName.modelUUID+"_50k.dam", true);
//        FileUtils.copyFile(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma",
//            ConstantFilePath.SCENE_PATH+"images"+File.separator+"images"+sceneNum + File.separator + ConstantFileName.modelUUID+"_50k.dam.lzma", true);
    }

    private void writeDataJson(String path) throws IOException {
        JSONObject dataJson = new JSONObject();
        dataJson.put("obj2txt", true);
        dataJson.put("split_type", "SPLIT_V6");
        dataJson.put("data_describe", "double spherical");
        dataJson.put("skybox_type", "SKYBOX_V5");
        FileUtils.writeFile(path + "/data.json", dataJson.toString());
    }

    private void objAndImgFileHandler(String resultPath, String filePath, String zipPath, MultipartFile file)
        throws Exception {
        FileUtils.delAllFile(resultPath);
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }else {
            FileUtils.delAllFile(filePath);
        }

        targetFile = new File(zipPath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }else {
            FileUtils.delAllFile(zipPath);
        }

        targetFile = new File(zipPath + file.getOriginalFilename());
        if(!targetFile.getParentFile().exists()){
            targetFile.getParentFile().mkdirs();
        }
        // 保存压缩包到本地
        if(targetFile.exists())
        {
            FileUtils.deleteFile(zipPath + file.getOriginalFilename());
        }
        file.transferTo(targetFile);

        FileUtils.decompress(zipPath + file.getOriginalFilename(), zipPath + "data/");

        //源文件数据，判断是否有多个文件夹，有多个就提示错误，有一个就将文件夹里数据迁移到extras目录，无直接迁移到extras目录
        boolean flag = false;
        //目录名称，如果不为空，则压缩文件第一层是目录
        String targetName = "";
        File dataFile = new File(zipPath + "data/");
        for(File data : dataFile.listFiles()){
            if(data.isDirectory() && flag){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5018);
            }
            if(data.isDirectory() && !flag){
                flag = true;
                targetName = data.getName();
            }
        }

        //是否包含obj文件
        boolean objFlag = false;
        //是否包含mtl文件
        boolean mtlFlag = false;
        File[] files = null;
        String dataPath = null;
        if(StrUtil.isEmpty(targetName)){
            files = dataFile.listFiles();
            dataPath = zipPath + "data/";
        }else{
            files = new File(zipPath + "data/" + targetName).listFiles();
            dataPath = zipPath + "data/" + targetName + File.separator;
        }

        for(File data : files){
            if(data.isDirectory()){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5018);
            }

            if(data.getName().endsWith(".jpg") || data.getName().endsWith(".png")){
                if(!FileUtils.checkFileSizeIsLimit(data.length(), 1.5, "M")){
                    throw new BusinessException(ErrorCode.FAILURE_CODE_5020);
                }
            }
            if(data.getName().endsWith(".obj")){
                if(objFlag){
                    throw new BusinessException(ErrorCode.FAILURE_CODE_5019);
                }
                if(!data.getName().equals("mesh.obj")){
                    throw new BusinessException(ErrorCode.FAILURE_CODE_5060);
                }
                if(!FileUtils.checkFileSizeIsLimit(data.length(), 20, "M")){
                    throw new BusinessException(ErrorCode.FAILURE_CODE_5020);
                }

                objFlag = true;
                FileUtils.copyFile(dataPath + data.getName(), filePath + "mesh.obj", true);
                continue;
            }

            if(data.getName().endsWith(".mtl")){
                mtlFlag = true;
            }

            FileUtils.copyFile(dataPath + data.getName(), filePath + data.getName(), true);
        }

        //压缩文件中必须有且仅有一个obj和mtl文件，否则抛出异常
        if(!mtlFlag || !objFlag){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5059);
        }
    }

    @Override
    public ResultData saveJsonData(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        String jsonData = param.getJsonData();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName) || StrUtil.isEmpty(jsonData)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        FileUtils.writeFile(dataBuffer.toString() + fileName, jsonData.toString());

        return ResultData.ok("scene/" + dataBuf.toString() + fileName);
    }

    @Override
    public ResultData downloadPanoramaOrVideo(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        String planId = param.getPlanId();
        String type = param.getPlanId();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName) || StrUtil.isEmpty(type)|| StrUtil.isEmpty(planId)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        if(fileName.contains("..") || fileName.contains("./\\") || fileName.contains(".//")
                || fileName.contains(".\\\\") || fileName.contains(".\\/")){
            throw new BusinessException(ErrorCode.FAILURE_CODE_3018);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());

        String path = sceneProExt.getDataSource();

        String url = "";

        if("image".equals(type)){
            if(!new File(path + "/caches/images/" + fileName).exists()){
                throw new BusinessException(ErrorCode.FAILURE_CODE_3018);
            }

            //备份原始数据
            if(!new File(imagesBuffer.toString() + "caches/back-" + fileName).exists()){
                FileUtils.copyFile(path + "/caches/images/" + fileName, imagesBuffer.toString() + "caches/back-" + fileName, false);
            }
            //复制打包数据，并且改名
            FileUtils.copyFile(path + "/caches/images/" + fileName, imagesBuffer.toString() + "caches/" + planId + ".jpg", true);

            url = mainUrl + "scene/" + imagesBuf.toString() + "caches/" + planId + ".jpg";
        }

        if("video".equals(type)){
            url = prefixAli + "video/video" + scenePro.getNum() + "/" + planId + ".mp4";
        }

        Map<String, Object> map = new HashMap<>();
        map.put("fileUrl", url + "?t=" + System.currentTimeMillis());
        map.put("fileName", url.substring(url.lastIndexOf("/") + 1));
        return ResultData.ok(map);
    }

    @Override
    public ResultData uploadPanoramaOrVideo(FileParamVO param, MultipartFile file) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        String planId = param.getPlanId();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName) || StrUtil.isEmpty(type) || StrUtil.isEmpty(planId)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

        if(!fileName.endsWith(".jpg") && !fileName.endsWith(".mp4")){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5023);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());


        String path = sceneProExt.getDataSource();

        if(path != null && !"".equals(path) && path.startsWith("http")){
            path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
        }
        String target = path + "_images";

        //文件上传的位置可以自定义
        String filePath = "";
        if("image".equals(type)){
            filePath = target + File.separator + "extras/images" + File.separator + fileName;
        }

        if("video".equals(type)){
            filePath = target + File.separator + "extras/video" + File.separator + fileName;
        }
        File targetFile = new File(filePath);
        if(!targetFile.getParentFile().exists()){
            targetFile.getParentFile().mkdirs();
        }

        //上传文件
        file.transferTo(targetFile);

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }
        if(type.equals("video")){
            scenejson.put("buildImages", 2);
            FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
        }else{
            scenejson.put("buildImages", 1);
            FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());
        }

        return ResultData.ok();
    }

    @Override
    public ResultData uploadROIVideo(FileParamVO param, MultipartFile file) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        String planId = param.getPlanId();
        String rect = param.getRect();
        String dir = param.getDir();
        String hfov = param.getHfov();
        String vfov = param.getVfov();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName) ||
                StrUtil.isEmpty(planId) || StrUtil.isEmpty(rect)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());


        String path = sceneProExt.getDataSource();

        if(path != null && !"".equals(path) && path.startsWith("http")){
            path = ConstantFilePath.BUILD_MODEL_PATH + File.separator + path.split("/")[path.split("/").length - 2];
        }
        String target = path + "_roi";

        FileUtils.deleteDirectory(target);

        //文件上传的位置可以自定义
        String filePath = target + File.separator + "extras" + File.separator + fileName;
        File targetFile = new File(filePath);
        if(!targetFile.getParentFile().exists()){
            targetFile.getParentFile().mkdirs();
        }

        if(file == null){
            FileUtils.copyFile(ConstantFilePath.SCENE_PATH + "video/video"+
                    scenePro.getNum() + File.separator + fileName, filePath, true);
        }else {
            //上传文件
            file.transferTo(targetFile);

            FileUtils.copyFile(filePath, ConstantFilePath.SCENE_PATH + "video/video"+
                    scenePro.getNum() + File.separator + fileName, true);
        }

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();

        JSONObject rectJson = JSON.parseObject(rect);

        boolean noPanoId = true;
        if(scenejson.containsKey("videosUser")){
            jsonArray = scenejson.getJSONArray("videosUser");
            for(int i = 0, len = jsonArray.size(); i < len; i++){
                jsonObject = jsonArray.getJSONObject(i);
                if(planId.equals(jsonObject.getString("panoId"))){
                    jsonObject.put("rect", rectJson);
                    jsonObject.put("name", fileName.substring(0, fileName.lastIndexOf(".")));
                    jsonObject.put("dir", JSON.parseObject(dir));
                    jsonObject.put("hfov", hfov);
                    jsonObject.put("vfov", vfov);
                    noPanoId = false;
                    break;
                }
            }
        }
        if(noPanoId){
            jsonObject = new JSONObject();
            jsonObject.put("name", fileName.substring(0, fileName.lastIndexOf(".")));
            jsonObject.put("panoId", planId);
            jsonObject.put("rect", rectJson);
            jsonObject.put("dir", JSON.parseObject(dir));
            jsonObject.put("hfov", hfov);
            jsonObject.put("vfov", vfov);
            if(!jsonArray.contains(jsonObject)){
                jsonArray.add(jsonObject);
            }
        }
        //保存rect的json数据
        FileUtils.writeFile(target + File.separator + "extras" + File.separator + "video-ROI.json", jsonObject.toJSONString());
        //复制原始图片
        FileUtils.copyFile(path + "/caches/images/" + planId + ".jpg",
                target + File.separator + "extras" + File.separator + planId + ".jpg", true);

        FileUtils.copyFile(path + File.separator + "data.json", target + File.separator+"data.json", true);
        FileUtils.copyFile(path + File.separator + "project.json", target + File.separator+"project.json", true);

        //data.json增加extras为执行重建算法
        String project = FileUtils.readFile(target + File.separator+"project.json");
        if(project != null){
            JSONObject projectJson = JSONObject.parseObject(project);
            projectJson.put("parent", projectJson.get("uuid"));
            projectJson.put("uuid", UUID.randomUUID().toString());
            projectJson.put("time", System.currentTimeMillis());
            FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
        }

        String data = FileUtils.readFile(target + File.separator+"data.json");
        if(data != null){
            JSONObject dataJson = JSONObject.parseObject(data);
            //V5表示不需要生成high，low文件
            dataJson.put("skybox_type", "SKYBOX_V5");
            dataJson.put("split_type", "SPLIT_V11");
            FileUtils.writeFile(target + File.separator+"data.json", new String(dataJson.toString().getBytes(), "UTF-8"));
        }

        //进行计算
        log.info("绿幕抠图视频：开始建模——" + scenePro.getNum());
        CreateObjUtil.build3dModel2(target , "1");

        //读取upload文件，检验需要上传的文件是否存在
        String uploadData = FileUtils.readFile(target + File.separator + "results" +File.separator+"upload.json");
        JSONObject uploadJson = null;
        JSONArray array = null;
        if(uploadData!=null) {
            uploadJson = JSONObject.parseObject(uploadData);
            array = uploadJson.getJSONArray("upload");
        }
        if(array == null){
            throw new Exception("upload.json数据出错");
        }

        Map<String, String> map = new HashMap<>();
        JSONObject fileJson = null;
        for(int i = 0, len = array.size(); i < len; i++){
            fileJson = array.getJSONObject(i);
            fileName = fileJson.getString("file");
            //文件不存在抛出异常
            if(!new File(target + File.separator + "results" +File.separator + fileName).exists()){
                throw new Exception(target + File.separator + "results" +File.separator + fileName+"文件不存在");
            }

            if(fileJson.getIntValue("clazz") == 19 ){
                map.put(target + File.separator + "results" + File.separator+ fileName,"video/video"+
                        scenePro.getNum() + File.separator + fileName.replace("videos/", ""));
            }

        }

        uploadToOssUtil.uploadMulFiles(map);

        scenejson.put("videosUser", jsonArray.toJSONString());
        scenejson.put("imagesVersion", scenejson.getIntValue("imagesVersion") + 1);

        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        if(sceneProEdit != null){
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
            sceneProEditExt.setVideosUser(jsonArray.toJSONString());
            sceneProEditExt.setImagesVersion(sceneProEditExt.getImagesVersion() + 1);
            sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
            sceneProEditExtService.updateById(sceneProEditExt);
        }

        return ResultData.ok();
    }

    @Override
    public ResultData deleteROIVideo(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        String planId = param.getPlanId();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName) || StrUtil.isEmpty(planId)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        JSONArray newArray = new JSONArray();
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();

        if(scenejson.containsKey("videosUser")){
            jsonArray = JSON.parseArray(scenejson.getString("videosUser"));
            for(int i = 0, len = jsonArray.size(); i < len; i++){
                jsonObject = jsonArray.getJSONObject(i);
                if(planId.equals(jsonObject.getString("panoId"))){
                    continue;
                }
                if(!newArray.contains(jsonObject)){
                    newArray.add(jsonObject);
                }
            }
        }

        scenejson.put("videosUser", newArray.toJSONString());
        scenejson.put("imagesVersion", scenejson.getIntValue("imagesVersion") + 1);

        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        if(sceneProEdit != null){
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
            sceneProEditExt.setVideosUser(newArray.toJSONString());
            sceneProEditExt.setImagesVersion(sceneProEditExt.getImagesVersion() + 1);
            sceneProEditExt.setUpdateTime(Calendar.getInstance().getTime());
            sceneProEditExtService.updateById(sceneProEditExt);
        }

        uploadToOssUtil.delete("video/video"+ scenePro.getNum() + File.separator +
                fileName.substring(0, fileName.lastIndexOf(".")) + ".mp4");
        uploadToOssUtil.delete("video/video"+ scenePro.getNum() + File.separator +
                fileName.substring(0, fileName.lastIndexOf(".")) + ".flv");

        FileUtils.deleteFile(ConstantFilePath.SCENE_PATH + "video/video"+ scenePro.getNum() + File.separator + fileName);
        return ResultData.ok();
    }

    @Override
    public ResultData uploadBgMusic(FileParamVO param, MultipartFile file) throws Exception {
        String sceneNum = param.getNum();
        String fileName = param.getFileName();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(fileName)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());

        File buMusicFile = new File(imagesBuffer.toString() + fileName);
        if(!buMusicFile.getParentFile().exists()){
            buMusicFile.getParentFile().mkdirs();
        }

        //上传文件
        file.transferTo(buMusicFile);

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        scenejson.put("bgMusicName", fileName);
        scenejson.put("uploadBgMusic", 1);
        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        return ResultData.ok();
    }

    @Override
    public ResultData deleteUploadBgMusic(FileParamVO param) throws Exception {
        String sceneNum = param.getNum();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = baseMapper.findByNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        scenejson.put("bgMusicName", "");
        scenejson.put("uploadBgMusic", 1);
        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toString());

        return ResultData.ok();
    }

    @Override
    public ResultData copyAndUpdateFloorJson(FileParamVO param) throws Exception{
        String sceneNum = param.getNum();
        String floorJsonData = param.getFloorJsonData();
        if(StrUtil.isEmpty(sceneNum) ){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(sceneNum)
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        if(StrUtil.isEmpty(floorJsonData)){
            ScenePro scenePro = baseMapper.findByNum(sceneNum);
            if(scenePro == null){
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            }
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

            FileUtils.copyFile(sceneProExt.getDataSource() + "/results/floor.json", dataBuffer.toString() + "houst_floor.json", true);
            uploadToOssUtil.upload(dataBuffer.toString() + "houst_floor.json", dataBuf.toString() + "houst_floor.json");

            String result = FileUtils.readFile(dataBuffer.toString() + "houst_floor.json");
            return ResultData.ok((Object) result);
        }

        FileUtils.writeFile(dataBuffer.toString() + "houst_floor.json", floorJsonData);
        uploadToOssUtil.upload(dataBuffer.toString() + "houst_floor.json", dataBuf.toString() + "houst_floor.json");
        return ResultData.ok(floorJsonData);
    }

    @Override
    public ResultData updateFloorJson(FileParamVO param) throws Exception{
        String sceneNum = param.getNum();
        String floorJsonData = param.getFloorJsonData();
        if(StrUtil.isEmpty(sceneNum) || StrUtil.isEmpty(floorJsonData)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(sceneNum)
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());

        String strsceneInfos = FileUtils.readFile(dataBuffer.toString() + "scene.json");
        JSONObject scenejson = new JSONObject();
        if(strsceneInfos!=null) {
            scenejson = JSONObject.parseObject(strsceneInfos);
        }

        scenejson.put("uploadFloorJson", 1);
        scenejson.put("version", scenejson.getIntValue("version") + 1);
        FileUtils.writeFile(dataBuffer.toString() + "floor.json", floorJsonData);
        FileUtils.writeFile(dataBuffer.toString() + "scene.json", scenejson.toJSONString());
        return ResultData.ok((Object) floorJsonData);
    }

    @Override
    public Page<SceneVO> getAppAllSceneByPage(Long cameraId, Long userId, int cameraType, int pageNum, Integer pageSize, String orderBy, Integer sceneType, List<String> sceneCodeList, String sceneName) {

        Page<SceneVO> page = new Page<>(pageNum, pageSize);

        List<SceneVO> list = baseMapper.getAppAllSceneByPage(page, cameraId, userId, cameraType, sceneType, sceneCodeList, sceneName, orderBy);

        page.setRecords(list);

        return page;
    }

    @Override
    public Long findSceneNumByCameraId(Long cameraId) {
        return this.count(new LambdaQueryWrapper<ScenePro>()
            .eq(ScenePro::getCameraId, cameraId));
    }

    @Override
    public SceneProPO findLastSceneByCameraId(Long cameraId) {
        return baseMapper.findLastSceneByCameraId(cameraId);
    }

    @Override
    public Long findTotalSpaceByCameraId(Long cameraId) {
        List<ScenePro> list = this.list(new LambdaQueryWrapper<ScenePro>()
                .select(ScenePro::getId)
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .eq(ScenePro::getCameraId, cameraId)
                .in(ScenePro::getSceneStatus, SceneStatus.SUCCESS.code(), SceneStatus.NO_DISPLAY.code())
                .eq(ScenePro::getPayStatus, PayStatus.PAY.code()));
        if(CollUtil.isEmpty(list)){
            return 0l;
        }

        List<Long> sceneProIds = list.stream().map(scenePro -> {
            return scenePro.getId();
        }).collect(Collectors.toList());

        List<SceneProExt> extList = sceneProExtService.list(new LambdaQueryWrapper<SceneProExt>()
                .in(SceneProExt::getSceneProId, sceneProIds));

        long sum = extList.parallelStream().mapToLong(ext -> ext.getSpace()).sum();

        return sum;
    }

    @Override
    public void updatePayStatusByCameraId(Integer payStatus, Long cameraId) {
        this.update(new LambdaUpdateWrapper<ScenePro>()
                .eq(ScenePro::getTbStatus, TbStatus.VALID.code())
                .eq(ScenePro::getCameraId, cameraId)
                .set(ScenePro::getPayStatus, payStatus));
    }

    @Override
    public ResultData downloadPanoramaData(SceneEditParamVO param) throws Exception {
        String sceneNum = param.getNum();
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }
        ScenePro scenePro = findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());

        String highPath = sceneProExt.getDataSource() + "/results/high";
        if(!new File(highPath).exists()){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5012);
        }

        FileUtils.zipFile(imagesBuffer.toString() + sceneNum + "-high.zip", highPath);
        uploadToOssUtil.upload(imagesBuffer.toString() + sceneNum + "-high.zip", imagesBuf.toString() + sceneNum + "-high.zip");

        return ResultData.ok(prefixAli + imagesBuf.toString() + sceneNum + "-high.zip?t=" + System.currentTimeMillis());

    }

    public ResultData getSceneAndCameras(Long userId,List<String> excludeNums) {
        List<SceneProPO> scenes = findByUserId(userId,excludeNums);
        Map<String,Object> result = new HashMap<>(2);
        if(ObjectUtils.isEmpty(scenes)){
            result.put("scenes",new ArrayList<>());
            result.put("cameras",new ArrayList<>());
            return ResultData.ok(result);
        }
        List<String> ids = scenes.parallelStream().map(scene->String.valueOf(scene.getCameraId()))
                .collect(Collectors.toList());
        // TODO: 2021/12/29 这里需要feign接口 
//        List<CameraEntity> cameras = cameraService.getCamerasByIds(ids);
//        result.put("scenes",scenes);
//        result.put("cameras",cameras);
        return ResultData.ok(result);
    }

    @Override
    public SceneProPO findBySceneNumWithOutCheckRecStatus(String sceneNum) throws Exception {
        return baseMapper.findByNumWithOutCheckRecStatus(sceneNum);
    }


    @Override
    public Integer findFolderIdScence(Long folderId, Long userId) {
        return baseMapper.findFolderIdScence(SceneProVO.builder().folderId(folderId).userId(userId).build());
    }

    @Override
    public ResultData downloadVisionData(SceneEditParamVO param) throws Exception {
        String sceneCode = param.getSceneName();
        if(StrUtil.isEmpty(sceneCode)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }
        List<ScenePro> sceneProList =  this.list(
                new QueryWrapper<ScenePro>()
                        .eq("tb_status", TbStatus.VALID.code())
                        .eq("scene_code",sceneCode));
        if(CollUtil.isEmpty(sceneProList)){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        ScenePro scenePro = sceneProList.get(0);

        StringBuffer dataBuf = new StringBuffer()
                .append("data").append(File.separator)
                .append("data").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer imagesBuf = new StringBuffer()
                .append("images").append(File.separator)
                .append("images").append(scenePro.getNum())
                .append(File.separator);

        StringBuffer dataBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(dataBuf.toString());
        StringBuffer imagesBuffer = new StringBuffer(ConstantFilePath.SCENE_PATH).append(imagesBuf.toString());


        String modeldataUrl = prefixAli + imagesBuf.toString() + "vision.modeldata?t=" + System.currentTimeMillis();
        if("aws".equals(type)){
            modeldataUrl = ConstantUrl.PREFIX_AWS + imagesBuf.toString() + "vision.modeldata?t=" + System.currentTimeMillis();
        }
        FileUtils.downLoadFromUrl(modeldataUrl, "vision.modeldata", dataBuffer.toString());
        File file = new File(dataBuffer.toString() + "vision.modeldata");
        if(!file.exists()) {
            return ResultData.error(ErrorCode.FAILURE_CODE_5012);
        }
        ConvertUtils.convertVisionModelDataToTxt(dataBuffer.toString() + "vision.modeldata", dataBuffer.toString() + "vision.json");

        uploadToOssUtil.upload(dataBuffer.toString() + "vision.json", dataBuf.toString() + "vision.json");
        return ResultData.ok(prefixAli + dataBuf.toString() + "vision.json?t=" + System.currentTimeMillis());
    }

    @Override
    public SceneVO getInfo(String sceneNum) {
        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }


        List<ScenePro> sceneProList =  this.list(
                new QueryWrapper<ScenePro>()
                        .eq("tb_status", TbStatus.VALID.code())
                        .eq("scene_code",sceneNum));
        if(CollUtil.isEmpty(sceneProList)){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        ScenePro scenePro = sceneProList.get(0);

        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        if(scenePro.getTbStatus().equals(TbStatus.DELETE.code())){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5009);
        }

        if(!SceneStatus.SUCCESS.code().equals(scenePro.getSceneStatus())
                && !SceneStatus.NO_DISPLAY.code().equals(scenePro.getSceneStatus())){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5033);
        }
        if(scenePro.getPayStatus() != 1){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5034);
        }

        SceneVO sceneVo = new SceneVO();
        SceneProEdit sceneProEdit =
                sceneProEditService.getOne(
                        new QueryWrapper<SceneProEdit>()
                                .eq("rec_status", RecStatus.VALID.code())
                                .eq("tb_status", RecStatus.VALID.code())
                                .eq("pro_id", scenePro.getId()));// .findByProId(scenePro.getId());
        SceneProEditExt sceneProEditExt
                = sceneProEditExtService.getOne(
                        new QueryWrapper<SceneProEditExt>()
                                .eq("pro_edit_id", sceneProEdit.getId()));

        BeanUtils.copyProperties(sceneProEditExt, sceneVo);
        BeanUtils.copyProperties(sceneProEdit, sceneVo);
        BeanUtils.copyProperties(scenePro, sceneVo);
        if(StrUtil.isNotEmpty(sceneProEdit.getEntry())){
            sceneVo.setEntry(JSONObject.parseObject(sceneProEdit.getEntry()).toJSONString());
        }

        if(StrUtil.isNotEmpty(scenePro.getGps())){
            sceneVo.setGps(JSONObject.parseObject(scenePro.getGps()).toJSONString());
        }

        sceneVo.setCreateTime(new DateTime(scenePro.getCreateTime()).toString("yyyy-MM-dd"));
        sceneVo.setCreateDate(scenePro.getCreateTime().getTime());
        if(StrUtil.isEmpty(sceneProEdit.getSceneKey())){
            sceneVo.setIsPublic(0);

        }else {
            sceneVo.setIsPublic(1);
        }

        //不返回场景访问密码
        sceneVo.setSceneKey("");

        //查询是否有随心装场景
        if(sceneNum.indexOf("vr-")!=-1){
            ScenePro vrScenePro= findLikeSceneNum(sceneNum);
            if(Objects.nonNull(vrScenePro)){
                sceneVo.setVrNum(null);
                sceneVo.setVideosUser(null);
                sceneVo.setBgMusicName(null);
                sceneVo.setBgMusic(null);
            }
        }

        //更新访问数量
        sceneService.updateViewCount(sceneNum);
        return sceneVo;
    }

    @Override
    public ScenePro findLikeSceneNum(String sceneNum) {
        return baseMapper.findLikeNum(sceneNum);
    }

    @Override
    public ResultData rebuildReduceSpaceBySceneNum(String sceneNum) throws Exception{
        ScenePro scenePro = this.findBySceneNum(sceneNum);
        if(scenePro == null){
            log.info("该场景不存在无法扣除容量，场景码为：" + sceneNum);
            return ResultData.error(ErrorCode.FAILURE_CODE_5054);
        }
        if (scenePro.getSceneScheme() < 4){
            log.info("该场景不属于八目相机无法扣除容量，场景码为：" + sceneNum);
            return ResultData.error(ErrorCode.FAILURE_CODE_5055);
        }
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());

        platformGoodsClient.updateCameraDetailByCameraIdAndSpace(scenePro.getCameraId(), -sceneProExt.getSpace());

        sceneProExt.setSpace(Long.parseLong("0"));
        sceneProExt.setUpdateTime(Calendar.getInstance().getTime());
        sceneProExtService.updateById(sceneProExt);

        return ResultData.ok();
    }

    @Override
    public void tempScenes(List<Long> lockedIds) {
        if (lockedIds == null || lockedIds.size() == 0){
            return;
        }
        for (Long id : lockedIds){
            ScenePro scenePro = this.getById(id);
            scenePro.setPayStatus(-2);
            this.updateById(scenePro);

            ScenePro sceneProEntity = this.getById(id);
            try{
                Map<String, Object> map = new HashMap<>();
                map.put("payStatus", -2);
                FileUtils.writeJsonFile(ConstantFilePath.SCENE_PATH + "data/data" + sceneProEntity.getNum() + "/scene.json", map);
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }

    @Override
    public ResultData getRecordAudioFromBrowser(FileParamVO param, MultipartFile file) throws IOException {
        String sceneNum = param.getNum();
        if(StrUtil.isEmpty(sceneNum) || file.isEmpty() || file.getSize() <= 0){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = this.findBySceneNum(sceneNum);
        if(scenePro == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }

        //文件上传的位置可以自定义
        log.info("开始上传文件");
        String path = ConstantFilePath.SCENE_PATH+"voice"+File.separator+"voice"+sceneNum;
        File targetFile = new File(path);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        targetFile = new File(path + File.separator + fileName);
        // 保存
        synchronized(this){
            file.transferTo(targetFile);
        }
        return ResultData.ok();
    }

    @Override
    public ResultData checkVideoUrl(FileParamVO param) {
        String path = param.getPath();
        if(StrUtil.isEmpty(path)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        if(!path.contains("qq.com") && !path.contains("youku.com") && !path.contains("iqiyi.com")){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5016);
        }

        if(path.contains("v.qq.com/txp/iframe/player.html") || path.contains("player.youku.com/embed")
                || path.contains("open.iqiyi.com/developer/player_js/coopPlayerIndex.html")){
            return ResultData.ok(path);
        }

        String html = "";
        try {
            URL url = new URL(path);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setConnectTimeout(60000);
            httpConn.setReadTimeout(60000);

            InputStreamReader input = new InputStreamReader(httpConn
                    .getInputStream(), "utf-8");
            BufferedReader bufReader = new BufferedReader(input);
            String line = "";
            String vid = "";
            if(path.contains("qq.com")){
                while ((line = bufReader.readLine()) != null) {
//                    System.out.println(line);
                    if(line.contains("m.v.qq.com/play.html")){
                        System.out.println(line.substring(line.indexOf("&vid=") + 5, line.indexOf("&ptag")));
                        vid = line.substring(line.indexOf("&vid=") + 5, line.indexOf("&ptag"));
                        break;
                    }
                }
                if(!StrUtil.isEmpty(vid)){
                    html = "https://v.qq.com/txp/iframe/player.html?vid=" + vid;
                }
            }

            if(path.contains("youku.com")){
                vid = path.substring(path.indexOf("/id_") + "/id_".length(), path.indexOf(".html"));
                html = "https://player.youku.com/embed/" + vid;
            }

            if(path.contains("iqiyi.com")){
                String tvid = "";
                while ((line = bufReader.readLine()) != null) {
                    if(line.contains("param['vid']")){
                        vid = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                    }
                    if(line.contains("param['tvid']")){
                        tvid = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                    }
                }
                if(!StrUtil.isEmpty(vid) && !StrUtil.isEmpty(tvid)){
                    html = "https://open.iqiyi.com/developer/player_js/coopPlayerIndex.html?vid=" + vid +
                            "&tvId=" + tvid;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return ResultData.ok(html);
    }

    public ResultData downloadTexData(String num) throws Exception {

        if(StrUtil.isEmpty(num)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }
//        ScenePro scenePro = this.findBySceneNum(num);
        ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
        if(scenePlus == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
//        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
        ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());

        SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());

        String localImagePath = String.format(ConstantFilePath.IMAGESBUFFER_FORMAT, num);
        if(!new File(localImagePath).exists()){
            new File(localImagePath).mkdirs();
        }


        String newData =  scenePlusExt.getDataSource() + "_obj2txt/extras";
        String newResultData = scenePlusExt.getDataSource() + "_obj2txt/results/upload.json";
        String zipName = num + "_extras.zip";
        String zipPath = localImagePath + zipName;
        //如果用户上传过模型，就打包上传到oss，直接返回
        if(CommonStatus.YES.code().equals(sceneEditInfo.getIsUploadObj())
            && new File(newData).exists()
            && new File(newResultData).exists()){
            //打包
            ZipUtil.zip(newData, zipPath);
            //上传压缩包
            uploadToOssUtil.upload(zipPath, "downloads/extras/" + zipName);
            String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
            return ResultData.ok(url);
        }


        String buildType = scenePlusExt.getBuildType();
        if("V3".equals(buildType)){
            String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
            //V3版本去oss下载2048模型
            String meshPath =  String.format(ConstantFilePath.DATABUFFER_FORMAT, num) + "mesh";
            FileUtils.deleteDirectory(meshPath);
            CreateObjUtil.ossUtilCp(dataViewPath + "mesh", meshPath);
            log.info("meshPath="+meshPath);
            if(!new File(meshPath).exists()){
                throw new BusinessException(ErrorCode.FAILURE_CODE_7006);
            }
            log.info(new File(meshPath).listFiles().toString());
            if(new File(meshPath).listFiles().length > 0){
                for(File file : new File(meshPath).listFiles()){
                    if(file.isDirectory()){
                        for (File item : file.listFiles()) {
                            if(item.getName().endsWith(".obj") && !"output.house.obj".equals(item.getName()) &&
                                !"mesh.obj".equals(item.getName())){
                                item.delete();
                            }
                            if(item.getName().endsWith(".mtl") && !"output.house.mtl".equals(item.getName()) &&
                                !"mesh.mtl".equals(item.getName())){
                                item.delete();
                            }
                        }
                        continue;
                    }
                    if(file.getName().endsWith(".obj") && !"output.house.obj".equals(file.getName()) &&
                            !"mesh.obj".equals(file.getName())){
                        file.delete();
                    }
                    if(file.getName().endsWith(".mtl") && !"output.house.mtl".equals(file.getName()) &&
                            !"mesh.mtl".equals(file.getName())){
                        file.delete();
                    }
                }
                //打包
                ZipUtil.zip(meshPath, zipPath);
                //上传压缩包
                uploadToOssUtil.upload(zipPath, "downloads/extras/" + zipName);
                String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
//                FileUtil.del(zipPath);
                return ResultData.ok(url);
            }
        }

        //V2版本在本地获取模型资源
        //修改过的资源
        String editData =  scenePlusExt.getDataSource() + "_edit/caches/tex";
        String results = scenePlusExt.getDataSource() + "_edit/results";
        if (new File(editData).exists() && new File(results).exists()){
            for(File file : new File(editData).listFiles()){
                if(file.getName().endsWith(".obj") && !"output.house.obj".equals(file.getName()) &&
                        !"mesh.obj".equals(file.getName())){
                    file.delete();
                }
                if(file.getName().endsWith(".mtl") && !"output.house.mtl".equals(file.getName()) &&
                        !"mesh.mtl".equals(file.getName())){
                    file.delete();
                }
            }

            ZipUtil.zip(editData, zipPath);
            //上传压缩包
            uploadToOssUtil.upload(zipPath, "downloads/extras/" + zipName);
            String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
            return ResultData.ok(url);
        }

        //没上传过返回源资源
        String dataPath = scenePlusExt.getDataSource() + "/caches/tex";
        File dataFile = new File(dataPath);
        if(!dataFile.exists()){
            throw new BusinessException(ErrorCode.FAILURE_CODE_3018);
        }
        for(File file : dataFile.listFiles()){
            if(file.getName().endsWith(".obj") && !"output.house.obj".equals(file.getName()) &&
                    !"mesh.obj".equals(file.getName())){
                file.delete();
            }
            if(file.getName().endsWith(".mtl") && !"output.house.mtl".equals(file.getName()) &&
                    !"mesh.mtl".equals(file.getName())){
                file.delete();
            }
        }

        ZipUtil.zip(dataPath, zipPath);
        //上传压缩包
        uploadToOssUtil.upload(zipPath, "downloads/extras/" + zipName);
        String url = ossUrlPrefix + "downloads/extras/" + zipName + "?t=" + Calendar.getInstance().getTimeInMillis();
        return ResultData.ok(url);
    }

    private void dealTour(SceneEditParamVO base, JSONObject scenejson, Map<String,String> map,
                          StringBuffer dataBuffer, StringBuffer imagesBuffer) throws IOException {
        if(!StrUtil.isEmpty(base.getTourList())){
            if(scenejson.containsKey("uploadTourList") && scenejson.getIntValue("uploadTourList") == 1){
                int screencapLen = 0;
                File file = new File(dataBuffer.toString() + ConstantFileName.TOURLIST_FOLDER);
                String[] strs = file.list();
                if(strs!=null) {
                    for(int i=0;i<strs.length;++i) {
                        if(strs[i].indexOf(ConstantFileName.SCREEN_CRP_DATAFILE)>-1)
                        {
                            ++screencapLen;
                            map.put(dataBuffer.toString() + ConstantFileName.TOURLIST_FOLDER+File.separator+strs[i],
                                    "data/data"+base.getNum()+"/tour/"+strs[i]);
                        }
                    }
                }
                scenejson.put("screencapLen", screencapLen);

                String path = imagesBuffer.toString() + ConstantFileName.TOURLIST_FOLDER;
                JSONArray tourJsons = JSONArray.parseArray(base.getTourList());
                for(int i=0;i<tourJsons.size();++i) {
                    String fileName = path + File.separator +"guide"+i+".jpg";
                    map.put(fileName,"images/images"+base.getNum()+"/tour/guide"+i+".jpg");
                }

                scenejson.put("uploadTourList", 0);
            }

            String tourListPath = dataBuffer.toString() + ConstantFileName.TOUR_LIST;
            FileUtils.deleteFile(tourListPath);
            FileUtils.writeFile(tourListPath, base.getTourList());
            map.put(tourListPath, dataBuffer.toString() + ConstantFileName.TOUR_LIST);
        }else{
            if(scenejson.containsKey("uploadTourList") && scenejson.getIntValue("uploadTourList") == 1){
                scenejson.put("uploadTourList", 0);
            }
            scenejson.put("screencapLen", 0);
        }
    }

    @Override
    public ResultData downloadCapture(SceneParamVO param) throws Exception {

        log.info("querySceneDataSource：查询模型数据");
        String num = param.getNum();
        if(num==null&&num.trim().equals(""))
            throw new BusinessException(ErrorCode.FAILURE_CODE_7002);
        String data = null;
        ScenePro scenePro= sceneProService.findBySceneNum(num);
        if(scenePro == null)
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());
        data = sceneProExt.getDataSource();
        CreateObjUtil.ossUtilCp(data.replace(ConstantFilePath.BUILD_MODEL_PATH, ConstantFilePath.OSS_PREFIX) + File.separator,
                data + "/capture");
        return ResultData.ok(data);

    }

    public ResultData uploadResultsData(SceneParamVO param) throws Exception{
        String path = param.getPath();
        String projectNum = param.getNum();
        String type = param.getType();
        String oldNum = param.getOldNum();

        if("change".equals(type)){
            ScenePro scenePro = sceneProService.findBySceneNum(projectNum);
            if(scenePro != null){
                sceneProService.updateStatus(projectNum, SceneStatus.wait.code());
                return ResultData.ok("一键换装场景存在，不重复生成");
            }

            //根据旧的场景生成新的vr场景
            scenePro = sceneProService.findBySceneNum(oldNum);
            if(scenePro == null)
                throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
            SceneProExt sceneProExt = sceneProExtService.findBySceneProId(scenePro.getId());


            SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());


            scenePro.setId(null);
            scenePro.setSceneType(99);
            scenePro.setWebSite(scenePro.getWebSite().replace(oldNum, projectNum));
            scenePro.setNum(projectNum);
            scenePro.setSceneStatus(0);
            scenePro.setSceneScheme(11);
            scenePro.setCreateTime(new Date());
            sceneProService.save(scenePro);
            sceneProExt.setSceneSource(11);
            sceneProExt.setSpace(new Long("0"));
            sceneProExt.setId(null);
            sceneProExt.setSceneProId(scenePro.getId());
            sceneProExtService.save(sceneProExt);

            sceneProEdit.setId(null);
            sceneProEdit.setProId(scenePro.getId());
            sceneProEditService.save(sceneProEdit);
            sceneProEditExt.setId(null);
            sceneProEditExt.setProEditId(sceneProEdit.getId());
            sceneProEditExtService.save(sceneProEditExt);

            SceneProPO sceneProPO = new SceneProPO();
            BeanUtil.copyProperties(sceneProExt, sceneProPO);
            BeanUtil.copyProperties(scenePro, sceneProPO);

            JSONObject scenejson = JSONObject.parseObject(JSONObject.toJSONString(sceneProPO));
            FileUtils.writeFile(ConstantFilePath.SCENE_PATH+"data/data"+projectNum+File.separator+"scene.json", scenejson.toString());

            uploadToOssUtil.upload(ConstantFilePath.SCENE_PATH + "images/images" + oldNum + File.separator + "floorplan.png",
                    "images/images" + projectNum + File.separator + "floorplan.png");
            path = sceneProExt.getDataSource();
        }

        Map<String, String> map = new HashMap<>();

        if(StringUtils.isEmpty(path) || StringUtils.isEmpty(projectNum)){
            return ResultData.error(ErrorCode.PARAM_REQUIRED);
        }

        boolean vision2 = false;
        //读取upload文件，检验需要上传的文件是否存在
        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");
        }
        if(array == null){
            throw new Exception("upload.json数据出错");
        }
        JSONObject fileJson = null;
        String fileName = "";
        String meshfix = "";  //双模型时候会有改文件路径
        for(int i = 0, len = array.size(); i < len; i++){
            fileJson = array.getJSONObject(i);
            fileName = fileJson.getString("file");
            //文件不存在抛出异常
            if(!new File(path + File.separator + "results" +File.separator + fileName).exists()){
                throw new Exception(path + File.separator + "results" +File.separator + fileName+"文件不存在");
            }

            //判断是否有vision2.txt
            if("vision2.txt".equals(fileName)){
                vision2 = true;
            }

            //tex文件夹
            if(fileJson.getIntValue("clazz") == 2 && !fileJson.containsKey("pack-file")){
                if(fileName.contains("meshfix.txt")){
                    meshfix = fileName;
                }else {
                    map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
                            projectNum+"/"+ ConstantFileName.modelUUID+"_50k_texture_jpg_high1/"+fileName.replace("tex/", ""));
                }
                continue;
            }

            //high文件夹
            if(fileJson.getIntValue("clazz") == 3){
                map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
                        projectNum+"/pan/high/"+ fileName.replace("high/", ""));
                continue;
            }
            //low文件夹
            if(fileJson.getIntValue("clazz") == 4){
                map.put(path + File.separator + "results" +File.separator+ fileName,"images/images"+
                        projectNum+"/pan/low/"+ fileName.replace("low/", ""));
                continue;
            }

            //tiles文件夹
            if(fileJson.getIntValue("clazz") == 5 ){
                map.put(path + File.separator + "results" + File.separator+ fileName,"images/images"+
                        projectNum+ File.separator + fileName);
                continue;
            }

            //updown文件复制一份到ecs中并去掉换行符
            if(fileJson.getIntValue("clazz") == 10){
                String updown = FileUtils.readFile(path + File.separator + "results" +File.separator+ fileName);
                JSONObject updownJson = JSONObject.parseObject(updown);
                FileUtils.writeFile(ConstantFilePath.SCENE_PATH + "data" + File.separator + "data" + projectNum +
                        File.separator + fileName.replace("updown", "mapping"), updownJson.toString());
                continue;
            }

            //video视频文件或封面图
            if(fileJson.getIntValue("clazz") == 11 || fileJson.getIntValue("clazz") == 12){
                map.put(path + File.separator + "results" + File.separator+ fileName,"video/video"+
                        projectNum+ File.separator + fileName.replace("videos/", ""));
            }

            //2048的模型和贴图
            if(fileJson.getIntValue("clazz") == 16){
                map.put(path + File.separator + "results" + File.separator+ fileName,"data/data"+
                        projectNum+ File.separator + fileName);
            }
        }

        CreateObjUtil.convertTxtToDam( path + File.separator + "results" + File.separator+"tex"+File.separator+"modeldata.txt", path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam");
        CreateObjUtil.convertDamToLzma(path + File.separator + "results");
        CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"tex"+File.separator+"modeldata.txt", path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
        //有meshfix，表示双模型
        if(!"".equals(meshfix)){
            CreateObjUtil.convertTxtToDam( path + File.separator + "results" + File.separator+meshfix, path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k2.dam");
            CreateObjUtil.convertDamToLzma2(path + File.separator + "results");
            CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+meshfix, path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k2.dam");
            map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k2.dam.lzma", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k2.dam.lzma");
            map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k2.dam", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k2.dam");
        }
        CreateObjUtil.convertTxtToVisionmodeldata(path + File.separator + "results" +File.separator+"vision.txt",path + File.separator + "results" +File.separator+"vision.modeldata");
        //8目相机有两个vision.txt因此第二个叫vision2.txt
        if(vision2){
            CreateObjUtil.convertTxtToVisionmodeldata(path + File.separator + "results" +File.separator+"vision2.txt",path + File.separator + "results" +File.separator+"vision2.modeldata");
            map.put(path + File.separator + "results" +File.separator+"vision2.modeldata", "images/images"+projectNum+"/"+"vision2.modeldata");
        }
        log.info("数据转换完成："+projectNum);

        File file = new File(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma");
        while(!file.exists())
        {
            Thread.sleep(60000);
        }

        map.put(path + File.separator + "results" +File.separator+"vision.modeldata", "images/images"+projectNum+"/"+"vision.modeldata");
        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam.lzma");
        map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", "images/images"+projectNum+"/"+ConstantFileName.modelUUID+"_50k.dam");

        file = new File(ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum);
        if(!file.exists())
        {
            file.mkdir();
        }
        FileUtils.copyFile(path + File.separator + "results" +File.separator+"floor.json", ConstantFilePath.SCENE_PATH+"data"+File.separator+"data"+projectNum+File.separator+"floor.json", true);
        log.info("floor.json路径："+ path + File.separator + "results" +File.separator+"floor.json");
        map.put(path + File.separator + "results" +File.separator+"floor.json","data/data"+projectNum+"/floor.json");
        log.info("准备上传文件到oss："+projectNum);
        uploadToOssUtil.uploadMulFiles(map);

        return ResultData.ok("上传完成");
    }

    @Override
    public ResultData updateStatusByScene(SceneParamVO param) throws Exception{
        String sceneNum = param.getNum();
        Integer status = param.getStatus();

        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = sceneProService.findBySceneNum(sceneNum);
        if(scenePro != null){
            scenePro.setSceneStatus(status);
            sceneProService.updateById(scenePro);

            SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
            SceneProEditExt sceneProEditExt = sceneProEditExtService.getByProEditId(sceneProEdit.getId());
            sceneProEdit.setVersion(sceneProEdit.getVersion() + 1);
            sceneProEdit.setFloorEditVer(sceneProEdit.getFloorEditVer() + 1);
            sceneProEdit.setFloorPublishVer(sceneProEdit.getFloorPublishVer() + 1);
            sceneProEditService.updateById(sceneProEdit);
            sceneProEditExt.setImagesVersion(sceneProEditExt.getImagesVersion() + 1);
            sceneProEditExt.setVideosUser(null);
            sceneProEditExtService.updateById(sceneProEditExt);
        }
        return ResultData.ok();
    }

    @Override
    public ResultData getStatusByScene(SceneParamVO param) throws Exception{
        String sceneNum = param.getNum();

        if(StrUtil.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.PARAM_REQUIRED);
        }

        ScenePro scenePro = sceneProService.findBySceneNum(sceneNum);
        if(scenePro != null){
            return ResultData.ok(scenePro.getSceneStatus() == -2? 1 : scenePro.getSceneStatus());
        }
        return ResultData.ok();
    }

    @Override
    public ResultData checkDownLoad(String sceneNum) {
        if(StringUtils.isEmpty(sceneNum)){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        ScenePro scenePro = sceneProService.findBySceneNum(sceneNum);
        if(scenePro == null ){
            throw  new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        SceneProEdit sceneProEdit = sceneProEditService.findByProId(scenePro.getId());
        if(sceneProEdit == null){
            throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
        }
        //downloadStatus,1打包资源下载，2已下载过，3下载过，并且没有修改过，无需打包直接返回下载地址，-1没下载次数不足
        SceneDownloadLog sceneDownloadLogEntity = sceneDownloadLogService.findByStatusAndNum(sceneNum, 0);
        Map<String, Object> result = new HashMap<>();
        if(sceneDownloadLogEntity != null){
            result.put("downloadStatus", 1);
            return ResultData.ok(result);
        }
        sceneDownloadLogEntity = sceneDownloadLogService.findByStatusAndNum(sceneNum, 1);

        //3下载过，并且没有修改过
        if(sceneDownloadLogEntity != null && sceneDownloadLogEntity.getSceneVersion().intValue() ==
                sceneProEdit.getVersion()){

            result.put("downloadStatus", 3);
            result.put("downloadUrl", sceneDownloadLogEntity.getDownloadUrl());
            return ResultData.ok(result);
        }

        //下载过
        if(sceneDownloadLogEntity != null){
            result.put("downloadStatus", 2);
            // 清除旧的下载信息
            redisUtil.del(RedisKey.PREFIX_DOWNLOAD_PROGRESS_V4.concat(sceneNum));
            return ResultData.ok(result);
        }

        //未下载过
        result.put("downloadStatus", 0);
        return ResultData.ok(result);
    }

    @Override
    public List<SceneProPO> findByCameraIds(String cameraIds, String startTime, String endTime) {
        return  this.baseMapper.findByCameraIds(cameraIds, startTime, endTime);
    }

    @Override
    public ResultData getScenesBySnCode(String snCode, String token) {
        if(StringUtils.isEmpty(token)){
            throw new BusinessException(3004, "无token参数");
        }

        SSOUser ssoUser = ssoLoginHelper.loginCheck(token);
        if(ssoUser == null){
            throw new BusinessException(3004, "token参数不正确");
        }

        if(StringUtil.isEmpty(snCode)){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        Camera cameraEntity = platformGoodsClient.getCameraBySnCode(snCode).getData();
        if(cameraEntity == null ){
            throw new BusinessException(CameraConstant.FAILURE_6018);
        }
        CameraDetail cameraDetailEntity = platformGoodsClient.getCameraDetailByCameraId(cameraEntity.getId()).getData();
        if(cameraDetailEntity == null ){
            throw new BusinessException(CameraConstant.FAILURE_6018);
        }
        if(!cameraDetailEntity.getUserId().equals(ssoUser.getId())){
            return ResultData.ok();
        }
        if(cameraDetailEntity.getCameraType() == 10 ){    //激光场景
            List<SceneBySnCodeVo> scenesBySnCode = fdkkLaserService.getScenesBySnCode(snCode, token);
            return ResultData.ok(scenesBySnCode);
        }
        List<SceneBySnCodeVo> sceneVo = sceneProMapper.getNumAndNameByCameraId(cameraEntity.getId(), ssoUser.getId());
        return ResultData.ok(sceneVo);
    }
}
