package com.ho.business.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.ho.business.config.BizMergeStrategy;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.*;
import com.ho.business.feignclient.FileCenterFeignClient;
import com.ho.business.mapper.StationSnMapper;
import com.ho.business.service.TabSortService;
import com.ho.business.service.TabSortWebService;
import com.ho.business.util.SendQueueUtil;
import com.ho.business.vo.req.BusinessModelIssue;
import com.ho.business.vo.resp.elecPriceCurve.RowRangeDto;
import com.ho.business.vo.resp.tabSort.TabSortExcel;
import com.ho.common.tools.annotation.TokenIgnore;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.constant.ExcelCommonConstant;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.EasyExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping(ContextConstant.BUSINESS + "tabSort")
@Api(tags = "策略模块配置")
@Slf4j
public class TabSortController {

    public static final Map<String,String> TAG_TYPE_MAP = new HashMap<String,String>(){
        {
            put("输入框","1");
            put("下拉框","2");
            put("单选框","3");
        }
    };

    public static final Map<String,String> TAG_TYPE_MAP_REFLECTION = new HashMap<String,String>(){
        {
            put("1","输入框");
            put("2","下拉框");
            put("3","单选框");
        }
    };

    public static final Map<String,String> TAG_TYPE_MAP_REFLECTION_EN_US = new HashMap<String,String>(){
        {
            put("1","Input Box");
            put("2","Dropdown Box");
            put("3","Radio Button");
        }
    };

    public static final List<String> FILE_SUFFIXS = new ArrayList<String>(){
        {
            add("xls");
            add("xlsx");
        }
    };
    /**
     * 单选框可以有的选项最多数量
     */
    public static final int RADIO_NUM = 3;

    @Autowired
    private TabSortService tabSortService;

    @Autowired
    private TabSortWebService tabSortWebService;

    @Autowired
    FileCenterFeignClient fileCenterFeignClient;

    @Autowired
    private StationSnMapper stationSnMapper;

    @Autowired
    private RedisService redisService;


    /**
     * 保留的版本总量
     */
    public static final int VERSION_FREQUENCY = 5;

    /** start */
    /**
     * todo: 导入导出数据相关代码
     */

    @TokenIgnore
    @PostMapping("/importTabSort")
    @ApiOperation(value = "导入页签内容")
    public DataResult<List<TabSort>> importTabSort(@RequestBody MultipartFile file, @Param("stationId") Integer stationId, HttpServletRequest request) {
        List<TabSort> list = new ArrayList<>(0);
        InputStream inputStream = null;
        boolean flag = false;
        try {
            String name = file.getOriginalFilename();
            if (name != null ) {
                String suffix = name.substring(name.lastIndexOf(".") + 1);
                if( FILE_SUFFIXS.indexOf(suffix) < 0 ){
                    throw new BusinessException(BaseResponseCode.FILE_TYPE_ERROR);
                }
            }
            inputStream = file.getInputStream();
            List<TabSortExcel> excelList = EasyExcel.read(inputStream).head(TabSortExcel.class).sheet().doReadSync();
            if( excelList == null || excelList.size() == 0 ){
                throw new BusinessException(BaseResponseCode.EXCEL_DATA_TABLE_EMPTY);
            }
            String tabName = null;
            String tagName = null;
            String tagNameEn = null;
            String tagType = null;
            String srcId = null;
            String deviceType = null;
            String col = null;
            BigDecimal maxValue = null;
            BigDecimal minValue = null;
            String colName = null;
            String frame = null;
            for (TabSortExcel tabSortExcel : excelList) {
                if (tabSortExcel.getTabName() != null) {
                    tabName = tabSortExcel.getTabName();
                    if( tabName.indexOf("提示") >= 0 ){
                        throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
                    }
                } else {
                    tabSortExcel.setTabName(tabName);
                }
                if (tabSortExcel.getTagName() != null) {
                    tagName = tabSortExcel.getTagName();
                } else {
                    tabSortExcel.setTagName(tagName);
                }
                if (tabSortExcel.getTagNameEn() != null) {
                    tagNameEn = tabSortExcel.getTagNameEn();
                } else {
                    tabSortExcel.setTagNameEn(tagNameEn);
                }
                if (tabSortExcel.getTagType() != null) {
                    tagType = TAG_TYPE_MAP.get(tabSortExcel.getTagType());
                    tabSortExcel.setTagType(tagType);
                } else {
                    tabSortExcel.setTagType(tagType);
                }
                if (tabSortExcel.getSrcId() != null) {
                    srcId = tabSortExcel.getSrcId();
                } else {
                    tabSortExcel.setSrcId(srcId);
                }
                if (tabSortExcel.getDeviceType() != null) {
                    deviceType = tabSortExcel.getDeviceType();
                } else {
                    tabSortExcel.setDeviceType(deviceType);
                }
                if (tabSortExcel.getCol() != null) {
                    col = tabSortExcel.getCol();
                } else {
                    tabSortExcel.setCol(col);
                }
                if (tabSortExcel.getMaxValue() != null) {
                    maxValue = tabSortExcel.getMaxValue();
                } else {
                    tabSortExcel.setMaxValue(maxValue);
                }
                if (tabSortExcel.getMinValue() != null) {
                    minValue = tabSortExcel.getMinValue();
                } else {
                    tabSortExcel.setMinValue(minValue);
                }
                if (tabSortExcel.getFrame() != null) {
                    frame = tabSortExcel.getFrame();
                    if( !checkData(frame,maxValue,minValue) ){
                        throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
                    }
                } else {
                    tabSortExcel.setFrame(frame);
                }
                if ( tabSortExcel.getCol() != null &&  tabSortExcel.getDeviceType() != null) {
                    String colNameByCol = tabSortService.getColNameByCol(tabSortExcel.getCol(), tabSortExcel.getDeviceType());
                    colName = colNameByCol;
                }
                if( colName != null ){
                    tabSortExcel.setColName(colName);
                }
            }
            if (!excelList.isEmpty()) {
                list = processParams(excelList,stationId);
                // 校验数据内容
                flag = this.checkParams(list);
                if( this.checkParams(list) ){
                    throw new BusinessException(BaseResponseCode.RADIO_MSG);
                }
                //入库
                tabSortWebService.exclListToDb(list,stationId);
            }
        } catch (IOException e) {
            throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
        } catch (Exception e) {
            if( flag ){
                throw new BusinessException(BaseResponseCode.RADIO_MSG);
            } else {
                throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
            }
        }
        return DataResult.success(list);
    }

    private static boolean checkData(String data,BigDecimal maxValue,BigDecimal minValue){
        if( isNumeric(data) ){
            BigDecimal dataValue = new BigDecimal(data);
            if( maxValue.compareTo(dataValue) < 0 && minValue.compareTo(dataValue) > 0 ){
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    public static boolean isNumeric(String str) {
        return str.matches("\\d+");
    }

    private List<TabSort> processParams(List<TabSortExcel> excelList,Integer stationId) {
        List<TabSort> list = new ArrayList<>(0);
        List<TabTag> tagList = null;
        List<TabTagDefaultValue> defaultValueList = null;
        TabSort tabSort = null;
        TabTag tabTag = null;
        TabTagDefaultValue defaultValue = null;
        for (int i = 0; i < excelList.size(); i++) {
            TabSortExcel tabSortExcel = excelList.get(i);
            TabSortExcel next = null;
            if (i + 1 < excelList.size() && excelList.get(i + 1) != null) {
                next = excelList.get(i + 1);
            }
            if (i == 0) {
                defaultValueList = new ArrayList<>(0);
                tagList = new ArrayList<>(0);
                tabSort = new TabSort();
                tabSort.setTabName(tabSortExcel.getTabName());

                tabTag = new TabTag();
                tabTag.setTagName(tabSortExcel.getTagName() != null ? tabSortExcel.getTagName() : null);
                tabTag.setTagNameEn(tabSortExcel.getTagNameEn() != null ? tabSortExcel.getTagNameEn() : null);
                tabTag.setMaxValue(tabSortExcel.getMaxValue() != null ? tabSortExcel.getMaxValue() : null);
                tabTag.setMinValue(tabSortExcel.getMinValue() != null ? tabSortExcel.getMinValue() : null);
                tabTag.setCol(tabSortExcel.getCol() != null ? tabSortExcel.getCol() : null);
                tabTag.setSrcId(tabSortExcel.getSrcId() != null?tabSortExcel.getSrcId():null);
                tabTag.setDeviceType(tabSortExcel.getDeviceType() != null?tabSortExcel.getDeviceType():null);
                tabTag.setFrame(tabSortExcel.getFrame() != null?tabSortExcel.getFrame():null);
                tabTag.setColName(tabSortExcel.getColName() != null?tabSortExcel.getColName():null);
                tabTag.setTagType(tabSortExcel.getTagType() != null?Integer.parseInt(tabSortExcel.getTagType()):null);
            }

            if (tabSortExcel.getDefVal() != null) {
                defaultValue = new TabTagDefaultValue();
                String defVal = tabSortExcel.getDefVal();
                if ( tabSortExcel.getDefVal().indexOf(":") > 0 ) {
                    if( !checkData(defVal.substring(0,defVal.indexOf(":")),tabSortExcel.getMaxValue(),tabSortExcel.getMinValue()) ){
                        throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
                    }
                    defaultValue.setDefLevel(defVal.substring(defVal.indexOf(":")+1,defVal.length()));
                    defaultValue.setDefVal(defVal.substring(0,defVal.indexOf(":")));
                } else {
                    if( !checkData(defVal,tabSortExcel.getMaxValue(),tabSortExcel.getMinValue()) ){
                        throw new BusinessException(BaseResponseCode.DATA_IS_ERROR);
                    }
                    defaultValue.setDefLevel(defVal);
                }
                defaultValue.setValFlag(1);
                defaultValueList.add(defaultValue);
            }
            if (next == null || !tabSortExcel.getTagName().equals(next.getTagName())) {
                tabTag.setValues(defaultValueList);
                tagList.add(tabTag);
                defaultValueList = new ArrayList<>(0);
                if( next != null ){
                    tabTag = new TabTag();
                    tabTag.setTagName(next.getTagName() != null ? next.getTagName() : null);
                    tabTag.setTagNameEn(next.getTagNameEn() != null ? next.getTagNameEn() : null);
                    tabTag.setMaxValue(next.getMaxValue() != null ? next.getMaxValue() : null);
                    tabTag.setMinValue(next.getMinValue() != null ? next.getMinValue() : null);
                    tabTag.setCol(next.getCol() != null ? next.getCol() : null);
                    tabTag.setSrcId(next.getSrcId() != null ? next.getSrcId() : null);
                    tabTag.setDeviceType(next.getDeviceType() != null ? next.getDeviceType() : null);
                    tabTag.setFrame(next.getFrame() != null ? next.getFrame() : null);
                    tabTag.setColName(next.getColName() != null?next.getColName():null);
                    tabTag.setTagType(next.getTagType() != null?Integer.parseInt(next.getTagType()):null);
//                    tabTag.setTagFlag(1);
                }
            }
            if (next == null || !tabSortExcel.getTabName().equals(next.getTabName())) {
                tabSort.setTabFlag(1);

                /** start */
                /** todo: 为对象去重*/

                Set<TabTag> set = tagList.stream().collect(Collectors.toSet());
                List<TabTag> collect = set.stream().collect(Collectors.toList());

                /** end */

                tabSort.setChilds(collect);
                tabSort.setStationId(stationId);
                tabSort.setTabFlag(1);
                list.add(tabSort);
                tagList = new ArrayList<>(0);
                if ( next != null ) {
                    tabSort = new TabSort();
                    tabSort.setTabName(next.getTabName());
                }
            }
        }
        // 下面代码注释掉,不与数据库数据进行整合
//        if( !list.isEmpty() ){
//            list = processDatas(list,stationId);
//        }
        return list;
    }

    /**
     * 判断数据里默认值数量,如果是单选框,那么最多只能有4个
     * @param list
     */
    private boolean checkParams(List<TabSort> list){
        for (TabSort tabSort : list) {
            List<TabTag> tabTags = tabSort.getChilds();
            if( tabTags != null && tabTags.size() > 0 ){
                for (TabTag tabTag : tabTags) {
                    Integer tagType = tabTag.getTagType();
                    List<TabTagDefaultValue> values = tabTag.getValues();
                    if( tagType != null && tagType == 3 && values != null && values.size() > RADIO_NUM ){
                       return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 处理返回数据,与数据库数据结合
     * @param excelList
     * @return
     */
    private List<TabSort> processDatas(List<TabSort> excelList,Integer stationId){
        // 去数据库查询数据
        TabSort tabSort = new TabSort();
        tabSort.setStationId(stationId);
        List<TabSort> tabSorts = tabSortService.queryIssueDatas(tabSort);
        // 判断一下查询结果,如果查询结果是null,则返回excelList不需要继续进行了
        if (tabSorts == null || tabSorts.isEmpty()) {
            return excelList;
        }
        List<TabSort> list = tabDeWeight(excelList, tabSorts);
        return list;
    }

    /**
     * 页签去重(完全相同的取数据库查询的数据)
     * @param tabSorts1 第一个参数是excel里的数据默认flag全都是1
     * @param tabSorts2 第二个参数是查询到的结果默认flag全都是0
     * @return
     */
    private List<TabSort> tabDeWeight(List<TabSort> tabSorts1, List<TabSort> tabSorts2){
        List<TabSort> list = new ArrayList<>(0);
        // 首先判断两个页签是否相同,如果不同则不需要进行后面的判断,如果相同再调用下一层
        // 创建一个新的集合,如果不相同合并到新的上来,如果相同的部分则直接返回数据库里的数据
        Set<TabSort> set = new HashSet<>(0);
        // 遍历数据库查询到的集合,里面再遍历excel的集合,合并到数据库的集合上来
        for (TabSort tabSort : tabSorts2) {
            for (TabSort sort : tabSorts1) {
                if( tabIsSame(tabSort,sort) ){
                    // 是否相同,如果相同则进入下一轮
                    List<TabTag> childs = tabSort.getChilds();
                    List<TabTag> excelChilds = sort.getChilds();
                    List<TabTag> tabTags = tagDeWeight(childs, excelChilds);
                    tabSort.setTabFlag(1);
                    tabSort.setChilds(tabTags);
                    set.add(tabSort);
                    break;
                } else {
                    set.add(tabSort);
                    set.add(sort);
                }
            }
        }
        if( set.size() > 0 ){
            list = set.stream().collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 页签是否相同 true:相同 false:不同
     * @param tabSort1  数据库查询到的数据
     * @param tabSort2  excel里导入的数据
     * @return
     */
    private boolean tabIsSame(TabSort tabSort1, TabSort tabSort2){
        boolean flag = true;
        // 判断名称是否相同
        if(  !tabSort1.getTabName().equals(tabSort2.getTabName()) ){
            flag = false;
        }
        return flag;
    }

    /**
     * 标签去重
     * @param tabTags1
     * @param tabTags2
     * @return
     */
    private List<TabTag> tagDeWeight(List<TabTag> tabTags1, List<TabTag> tabTags2){
        List<TabTag> list = new ArrayList<>(0);
        Set<TabTag> set = new HashSet<>(0);
        for (TabTag tabTag : tabTags1) {
            for (TabTag tag : tabTags2) {
                if( tagsIsSame(tabTag,tag) ){
                    // 是否相同,如果相同则进入下一轮
                    List<TabTagDefaultValue> values = tabTag.getValues();
                    List<TabTagDefaultValue> values1 = tag.getValues();
                    List<TabTagDefaultValue> defaultValueList = valDeWeight(values, values1);
                    tabTag.setTagFlag(1);
                    tabTag.setValues(defaultValueList);
                    set.add(tabTag);
                    break;
                } else {
                    set.add(tabTag);
                    set.add(tag);
                }
            }
        }
        if( set.size() > 0 ){
            list = set.stream().collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 标签是否相同 true:相同 false:不同
     * @param tabTag1  第一个是数据库查询出来的结果
     * @param tabTag2  第二个是excel导入的结果
     * @return
     */
    private boolean tagsIsSame(TabTag tabTag1, TabTag tabTag2){
        boolean flag = true;
        if( !tabTag1.getTagName().equals(tabTag2.getTagName()) || !tabTag1.getTagNameEn().equals(tabTag2.getTagNameEn()) ){
            flag = false;
        }
        if( !tabTag1.getTagType().equals(tabTag2.getTagType()) ){
            flag = false;
        }
        return flag;
    }


    /**
     * 默认值去重
     * @param values1
     * @param values2
     * @return
     */
    private List<TabTagDefaultValue> valDeWeight(List<TabTagDefaultValue> values1, List<TabTagDefaultValue> values2){
        List<TabTagDefaultValue> list = new ArrayList<>(0);
        Set<TabTagDefaultValue> set = new HashSet<>(0);
        for (TabTagDefaultValue v1 : values1) {
            for (TabTagDefaultValue v2 : values2) {
                if( defValIsSame(v1,v2) ){
                    // 是否相同,如果相同则进入下一轮
                    v1.setValFlag(1);
                    v1.setDefVal(v2.getDefVal());
                    set.add(v1);
                    break;
                } else {
                    set.add(v1);
                    set.add(v2);
                }
            }
        }
        if( set.size() > 0 ){
            list = set.stream().collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 默认值是否相同 true:相同 false:不同
     * @param value1
     * @param value2
     * @return
     */
    private boolean defValIsSame(TabTagDefaultValue value1, TabTagDefaultValue value2){
        boolean flag = true;
        if( !value1.getDefVal().equals(value2.getDefVal()) ){
            flag = false;
        }
        return flag;
    }

    @PostMapping("exportTemplate")
    @ApiOperation(value = "导出模板")
    public void exportTemplate(HttpServletResponse response) {
        ServletOutputStream out = null;
        try {
            String fileName = URLEncoder.encode("planTemplate.xls", "utf-8");
            InputStream fis = getResourcesFileInputStream("template/planTemplate.xls");
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            response.setHeader("Content-disposition", "attachment;fileName=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            out = response.getOutputStream();
            out.write(buffer);
        } catch (Exception ex) {
            log.error("下载失败,{}", ex.getMessage());
        } finally {
            try {
                assert out != null;
                out.flush();
                out.close();
            } catch (Exception e) {
                log.error("下载模板失败,{}", e.getMessage());
                throw new BusinessException(BaseResponseCode.EXCEL_DATA_IMPORT_ERROR);
            }
        }
    }

    private static InputStream getResourcesFileInputStream(String fileName) {
        return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
    }

    @TokenIgnore
    @PostMapping("/exportTabSort")
    @ApiOperation(value = "导出页签内容")
    public void exportTabSort(@RequestBody TabSort tabSort ,HttpServletRequest req, HttpServletResponse response) {
        if( tabSort == null || tabSort.getStationId() == null ) {
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        // 查询结果
        List<TabSortExcel> list = tabSortService.queryExcelDatas(tabSort);
        ServletOutputStream out = null;
        if( list == null || list.size() == 0 ){
            return;
//            throw new BusinessException(BaseResponseCode.DATA_IS_EXISTS);
        }
        for (TabSortExcel tabSortExcel : list) {
            String s = TAG_TYPE_MAP_REFLECTION.get(tabSortExcel.getTagType());
            tabSortExcel.setTagType(s);
        }
        Map<String, List<RowRangeDto>> strategyMap = BizMergeStrategy.addAnnualMerStrategy4TabSort(list);
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String filename = URLEncoder.encode("策略", "utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + filename + ".xlsx");

            EasyExcel.write(response.getOutputStream(), TabSortExcel.class)
                    .excelType(ExcelTypeEnum.XLSX).head(TabSortExcel.class)
                    //设置默认样式及写入头信息开始的行数
                    .registerWriteHandler(new BizMergeStrategy(strategyMap))    // 注册合并策略
                    .sheet("策略")
                    .doWrite(list);
        }catch (Exception e) {
            log.error("下载失败,{}", e.getMessage());
            throw new BusinessException(BaseResponseCode.EXCEL_DATA_IMPORT_ERROR);
        }
    }

    /** end */

    /** start */
    /**
     * todo: 下发命令相关代码
     */

    @TokenIgnore
    @PostMapping("/oneKeySend")
    @ApiOperation(value = "一键下发")
    public DataResult<Map<String,Object>> oneKeySend(@RequestBody TabSort tabSort) {
        Map<String,Object> result = new HashMap<>(0);
        result.put("isEnd",2);
        result.put("bar",0);
        if( tabSort == null ) {
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        List<TabSort> tabSorts = tabSortService.queryIssueDatas(tabSort);
        Integer stationId = null;
        if( tabSort != null && tabSort.getStationId() != null ){
            stationId = tabSort.getStationId();
        }
        // 先查询一下是否有下发进度,如果有进度给进度,没有才走下发逻辑
//        SendResultVo sendResultVo = SendQueueUtil.getOneKeyProgress(stationId);
        Object obj = redisService.hget(SendQueueUtil.REDIS_PROGRESS_KEY, String.valueOf(stationId));
        List<OrderIssuedReqVO> list = null;
        if ( obj == null  && tabSort.getQueryType() != null &&tabSort.getQueryType().equals(1) ) {
            list = processIssueDatas(tabSorts);
        }
//        sendResultVo = SendQueueUtil.getOneKeyProgress(stationId);
        SendResultVo sendResultVo =  (SendResultVo)redisService.hget(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId));
        if ( sendResultVo != null && sendResultVo.getType().equals(1)) {
            result.put("isEnd",sendResultVo.getIsEnd());
            result.put("bar",sendResultVo.getBar());
            result.put("failDatas","");
            result.put("failTimes","");
            result.put("sussessDatas","");
            result.put("sussessTimes","");
            if ( sendResultVo.getIsEnd().equals(1) ) {
                result.put("failDatas",sendResultVo.getFailDatas());
                result.put("failTimes",sendResultVo.getFailTimes());
                result.put("sussessDatas",sendResultVo.getSussessDatas());
                result.put("sussessTimes",sendResultVo.getSussessTimes());
//                SendQueueUtil.removeOneKeyProgress(stationId);
                redisService.hdel(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId));
            }
        } else if( tabSort.getQueryType().equals(1) ) {
            if( list != null && list.size() > 0 ){
                result.put("isEnd",0);
                result.put("bar",0);
                result.put("failDatas","");
                result.put("failTimes","");
                result.put("sussessDatas","");
                result.put("sussessTimes","");
                sendResultVo.setType(1);
//                SendQueueUtil.setOneKeyProgress(stationId,sendResultVo);
                redisService.hset(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId),sendResultVo);
                redisService.expire(SendQueueUtil.REDIS_PROGRESS_KEY,4, TimeUnit.HOURS);
                SendQueueUtil.setSendMap(list,stationId);
            } else {
                throw new BusinessException(BaseResponseCode.SEND_DATA_IS_EXISTS);
            }
        } else {
            result.put("isEnd",-1);
            result.put("bar",-1);
            result.put("failDatas","");
            result.put("failTimes","");
            result.put("sussessDatas","");
            result.put("sussessTimes","");
        }
        return DataResult.success(result);
    }

    @TokenIgnore
    @PostMapping("/oneTabSend")
    @ApiOperation(value = "单页面下发")
    public DataResult<Map<String, Object>> oneTabSend(@RequestBody List<TabTag> tabTags) {
        Map<String,Object> result = new HashMap<>(0);
        if( tabTags == null || tabTags.size() == 0) {
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        Integer tabId = tabTags.get(0).getTabId();
        TabSort tabSort = tabSortService.queryTabSortById(tabId);
        if( tabSort == null ){
            throw new BusinessException(BaseResponseCode.DATA_NOT_SAVE);
        }
        List<TabSort> tabSorts = new ArrayList<>(0);
        tabSort.setChilds(tabTags);
        tabSorts.add(tabSort);
        List<OrderIssuedReqVO> list = null;
        // 先查询一下是否有下发进度,如果有进度给进度,没有才走下发逻辑
        Integer stationId = null;
        if( tabSort != null && tabSort.getStationId() != null ){
            stationId = tabSort.getStationId();
        }
//        SendResultVo sendResultVo = SendQueueUtil.getOneKeyProgress(stationId);
        Object obj = redisService.hget(SendQueueUtil.REDIS_PROGRESS_KEY, String.valueOf(stationId));
        if ( obj == null ) {
            list = processIssueDatas(tabSorts);
        }
        result.put("isEnd",2);
        result.put("bar",0);
//        sendResultVo = SendQueueUtil.getOneKeyProgress(stationId);
        SendResultVo sendResultVo =  (SendResultVo)redisService.hget(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId));
        if ( sendResultVo != null && sendResultVo.getType().equals(1)) {
            result.put("isEnd",sendResultVo.getIsEnd());
            result.put("bar",sendResultVo.getBar());
            result.put("failDatas","");
            result.put("failTimes","");
            result.put("sussessDatas","");
            result.put("sussessTimes","");
            if ( sendResultVo.getIsEnd().equals(1) ) {
                result.put("failDatas",sendResultVo.getFailDatas());
                result.put("failTimes",sendResultVo.getFailTimes());
                result.put("sussessDatas",sendResultVo.getSussessDatas());
                result.put("sussessTimes",sendResultVo.getSussessTimes());
//                SendQueueUtil.removeOneKeyProgress(stationId);
                redisService.hdel(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId));
            }
        } else {
            if( list != null && list.size() > 0 ){
                result.put("isEnd",0);
                result.put("bar",0);
                result.put("failDatas","");
                result.put("failTimes","");
                result.put("sussessDatas","");
                result.put("sussessTimes","");
                sendResultVo.setType(1);
                redisService.hset(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId),sendResultVo);
                redisService.expire(SendQueueUtil.REDIS_PROGRESS_KEY,4, TimeUnit.HOURS);
//                SendQueueUtil.setOneKeyProgress(stationId,sendResultVo);
                SendQueueUtil.setSendMap(list,stationId);
            }
        }
        return DataResult.success(result);
    }

    @PostMapping("/oneKeyControl")
    @ApiOperation(value = "一键顺控")
    public DataResult<Map<String, Object>> oneKeySend(@RequestBody List<OneClickSequentialControl> list) {
        Map<String,Object> result = new HashMap<>(0);
        result.put("isEnd","");
        result.put("bar","");
        if(list!=null&&list.size()>0){
            Integer stationId = list.get(0).getStationId();
            List<StationSn> stationSns = stationSnMapper.selectByStationId(stationId);
            if(stationSns!=null&&stationSns.size()>0){
                StationSn stationSn = stationSns.get(0);
                String sn = stationSn.getSn();
                for(OneClickSequentialControl oneClick:list){
                    // 先查询一下是否有下发进度,如果有进度给进度,没有才走下发逻辑
//                    Integer oneControlProgress = SendQueueUtil.getOneControlProgress(oneClick.getId() + "" + stationId);
                    String redisKey = SendQueueUtil.REDIS_PROGRESS_KEY_4_CONTROL+stationId+":"+oneClick.getId();
                    Integer oneControlProgress = (Integer) redisService.get(redisKey);
//                    Integer oneControlProgress = (Integer) redisService.hget(SendQueueUtil.REDIS_PROGRESS_KEY,oneClick.getId()+""+stationId);
                    if ( oneControlProgress != null ) {
                        result.put("isEnd",oneControlProgress);
                        result.put("bar",100.00);

                        String key = SendQueueUtil.REDIS_KEYS + stationId;

                        // 删除逻辑-----> 0表示正在下发   1表示成功  正在下发中不删除redis缓存,下发成功时需要知道是最后一条下发成功才会删除
                        if ( (!oneControlProgress.equals(0) && !oneControlProgress.equals(1)) || (!oneControlProgress.equals(0) && oneClick.getIsLast() == 1) ) {
//                            SendQueueUtil.removeOneControlProgress(oneClick.getId()+""+stationId);
//                            redisService.hdel(SendQueueUtil.REDIS_PROGRESS_KEY,oneClick.getId()+""+stationId);
                            List<String> keys = (List<String>)redisService.get(key);
                            redisService.delete(key);
                            redisService.delete(keys);
                        }
//                        Integer oneControlProgress1 = SendQueueUtil.getOneControlProgress(oneClick.getId() + "" + stationId);
//                        System.err.println("一键顺控>>>>"+oneControlProgress1);
//                        System.err.println("一键顺控  !oneControlProgress.equals(0) >>>>"+!oneControlProgress.equals(0));
                    } else {
//                        redisService.hset(SendQueueUtil.REDIS_PROGRESS_KEY,oneClick.getId()+""+stationId,0);
                        redisService.set(redisKey,0);
                        redisService.expire(redisKey,4, TimeUnit.HOURS);
                        result.put("isEnd",0);
                        result.put("bar",0);
                        OrderIssuedVO orderIssuedVO = new OrderIssuedVO();
                        orderIssuedVO.setSn(sn);
                        orderIssuedVO.setStationId(stationId);
                        orderIssuedVO.setCol(oneClick.getCol());
                        orderIssuedVO.setMinValue(oneClick.getMinValue());
                        orderIssuedVO.setMaxValue(oneClick.getMaxValue());
                        orderIssuedVO.setSrcId(oneClick.getSrcId());
                        orderIssuedVO.setModifyValue(oneClick.getSetValue());
                        List<OrderIssuedReqVO> orderIssuedReqVOS = new ArrayList<>();
                        OrderIssuedReqVO orderIssuedReqVO = new OrderIssuedReqVO();
                        orderIssuedReqVO.setSn(sn);
                        ArrayList<OrderIssuedVO> OrderIssuedList = new ArrayList<OrderIssuedVO>();
                        OrderIssuedList.add(orderIssuedVO);
                        orderIssuedReqVO.setList(OrderIssuedList);
                        orderIssuedReqVO.setSrcId(oneClick.getSrcId());
                        orderIssuedReqVO.setStationId(stationId);
                        orderIssuedReqVOS.add(orderIssuedReqVO);
                        SendQueueUtil.setControlMap(orderIssuedReqVOS,stationId+":"+oneClick.getId());
                        checkRedisKey(stationId,redisKey);
                    }
                }
            }
        }
        return DataResult.success(result);
    }

    /**
     * 先判断这个电站下有没有key,如果有则返回true,如果没有则false
     * @param stationId
     * @param redisKey
     * @return
     */
    private boolean checkRedisKey(Integer stationId,String redisKey){
        String key = SendQueueUtil.REDIS_KEYS + stationId;
        Boolean b = redisService.hasKey(key);
        List<String> keys = null;
        if( b ){
            keys= (List<String>)redisService.get(key);
        }
        if( keys != null && keys.contains(redisKey) ){
            return true;
        } else if( keys != null ){
            keys.add(redisKey);
            redisService.set(key,keys);
            return false;
        } else {
            keys = new ArrayList<>();
            keys.add(redisKey);
            redisService.set(key,keys);
            return false;
        }
    }

    /**
     * 组装下发指令
     * @param tabSorts
     * @return
     */
    private List<OrderIssuedReqVO> processIssueDatas( List<TabSort> tabSorts ){
        // 失败数据直接放进队列
        SendResultVo sendVo = new SendResultVo();
        List<ResutData> failDatas = new ArrayList<>(0);
        ResutData fail = null;

        List<OrderIssuedReqVO> issueList = new ArrayList<>(0);
        OrderIssuedVO vo = null;
        // 如果集合不为空,那么直接取第一个sn赋值
        String sn = null;
        Integer stationId = null;
        if( tabSorts != null && tabSorts.size() > 0 ){
            stationId = tabSorts.get(0).getStationId();
            if (stationId == null) {
                throw new BusinessException(BaseResponseCode.STATION_SN_IS_NOT_EXISTS);
            }else{
                sn = tabSortService.getStationSn(stationId);
                if( sn == null ){
                    throw new BusinessException(BaseResponseCode.STATION_SN_IS_NOT_EXISTS);
                }
            }
        } else {
            throw new BusinessException(BaseResponseCode.SEND_DATA_IS_EXISTS);
        }
        OrderIssuedReqVO orderIssuedReqVO = null;
        List<OrderIssuedVO> list = null;

        for (TabSort tabSort : tabSorts) {
            int index = 0;
            list = new ArrayList<>(0);
            if ( tabSort.getChilds() != null && tabSort.getChilds().size() > 0 ) {
                List<TabTag> tags = tabSort.getChilds();
                if( tags == null || tags.size() <= 0 ){
                    continue;
                }
                for (int i = index; i < tags.size(); i++) {
                    fail = new ResutData();
                    boolean flag = true;
                    TabTag tag = tags.get(i);
                    if ( tag == null || tag.getSrcId() == null ){
                        continue;
                    }
                    vo = new OrderIssuedVO();
                    vo.setStationId(tabSort.getStationId());
                    if ( tag.getCol() != null && !tag.getCol().equals("")) {
                        vo.setCol(tag.getCol());
                    } else {
                        flag = false;
                    }
                    vo.setMaxValue(tag.getMaxValue()==null?new BigDecimal(65535):tag.getMaxValue());
                    vo.setMinValue(tag.getMinValue()==null?new BigDecimal(-65535):tag.getMinValue());
                    if ( tag.getSrcId() != null && !tag.getSrcId().equals("") ) {
                        vo.setSrcId(Integer.parseInt(tag.getSrcId()));
                    } else {
                        flag = false;
                    }
                    vo.setSn(sn);
                    if ( tag.getFrame() != null && !tag.getFrame().equals("")) {
                        vo.setModifyValue(new BigDecimal(tag.getFrame()));
                    } else {
                        flag = false;
                    }
                    vo.setTabName(tabSort.getTabName());
                    vo.setTagName(tag.getTagName());
                    if (flag) {
                        list.add(vo);
                    } else {
                        fail.setTabName(tabSort.getTabName());
                        fail.setTagName(tag.getTagName());
                        failDatas.add(fail);
                    }
                    if( list.size() == 5 || i+1 == tags.size() ){
                        orderIssuedReqVO = new OrderIssuedReqVO();
                        orderIssuedReqVO.setSn(sn);
                        orderIssuedReqVO.setList(list);
                        orderIssuedReqVO.setSrcId(Integer.parseInt(tag.getSrcId()));
                        orderIssuedReqVO.setStationId(stationId);
                        issueList.add(orderIssuedReqVO);
                        index = i;
                        list = new ArrayList<>(0);
                    }
                }
            }
        }
        sendVo.setBar("0");
        sendVo.setIsEnd(0);
        sendVo.setType(0);
        sendVo.setFailDatas(failDatas);
        sendVo.setFailTimes(failDatas.size());
        sendVo.setSussessDatas(new ArrayList<>(0));
        sendVo.setSussessTimes(0);
//        SendQueueUtil.setOneKeyProgress(stationId,sendVo);
        redisService.hset(SendQueueUtil.REDIS_PROGRESS_KEY,String.valueOf(stationId),sendVo);
        redisService.expire(SendQueueUtil.REDIS_PROGRESS_KEY,4, TimeUnit.HOURS);
        return issueList;
    }
    /** end */

    @TokenIgnore
    @PostMapping("/sendPlanControl")
    @ApiOperation(value = "下发控制")
    public DataResult<OrderIssuedReqVO> sendPlanControl(@RequestBody BusinessModelIssue issue) {
        if( issue == null || issue.getStationId() == null ){
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        String deviceType = DeviceTypeConstant.PLAN_CURVE.PALN_CONTROL_DEVICE_TYPE+issue.getStationId();
        List<PlanningIssueComm> planningIssueComm = tabSortService.queryPlanControlIssueData(deviceType);
        OrderIssuedReqVO orderIssuedReqVO = buildOrderIssuedReqVO(planningIssueComm,issue);
        sendData(orderIssuedReqVO);
        return DataResult.success(orderIssuedReqVO);
    }

    private OrderIssuedReqVO buildOrderIssuedReqVO( List<PlanningIssueComm> issueComms,BusinessModelIssue issue ){
        OrderIssuedReqVO result = new OrderIssuedReqVO();
        // 0 计划曲线，1 实时
        Integer value = issue.getValue();
        Integer stationId = issue.getStationId();
        if( value.equals(1) && ( issue.getQ() == null || issue.getP() == null ) ){
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }

        List<OrderIssuedVO> list = new ArrayList<>(0);
        OrderIssuedVO vo = null;

        // 获取电站sn
        String sn = tabSortService.getStationSn(stationId);

        // 如果是计划曲线的流程
        if( value.equals(0) ){
            for (PlanningIssueComm issueComm : issueComms) {
                if ( DeviceTypeConstant.PLAN_CURVE.PLAN_CONTROL_MODEL.equals(issueComm.getModelCol()) ) {
                    vo = new OrderIssuedVO();
                    vo.setStationId(stationId);
                    vo.setCol(issueComm.getTypeCol());
                    vo.setMaxValue(new BigDecimal(issueComm.getMaxValue()));
                    vo.setMinValue(new BigDecimal(issueComm.getMinValue()));
                    vo.setSrcId(Integer.parseInt(issueComm.getSrcId()));
                    vo.setSn(sn);
                    vo.setModifyValue(new BigDecimal(value));
                    list.add(vo);
                    result.setStationId(stationId);
                    result.setSrcId(Integer.parseInt(issueComm.getSrcId()));
                }
            }
            result.setSn(sn);
            result.setList(list);

        }

        // 进入实时流程
        if( value.equals(1) ){
            for (PlanningIssueComm issueComm : issueComms) {
                vo = new OrderIssuedVO();
                vo.setStationId(stationId);
                vo.setCol(issueComm.getTypeCol());
                vo.setMaxValue(new BigDecimal(issueComm.getMaxValue()));
                vo.setMinValue(new BigDecimal(issueComm.getMinValue()));
                vo.setSrcId(Integer.parseInt(issueComm.getSrcId()));
                vo.setSn(sn);
                vo.setModifyValue(new BigDecimal(value));
                list.add(vo);
            }
            result.setSn(sn);
            result.setList(list);
        }
        return result;
    }


    private void sendData( OrderIssuedReqVO vo ){
        DataResult<HeartbeatResp> heartbeatRespDataResult = fileCenterFeignClient.orderIssued(vo);
        HeartbeatResp data = heartbeatRespDataResult.getData();
    }

    @PostMapping("/getTabModel")
    @ApiOperation(value = "策略模块-总览页面-工作模式")
    public DataResult<JSONObject> getTabModel(@RequestBody BusinessModelIssue issue) {
        JSONObject jsonObject = tabSortService.getTabModel(issue);
        return DataResult.success(jsonObject);
    }

}
