package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.busi.bu;

import cn.estsh.i3plus.ext.mes.api.base.IProdOrgExtService;
import cn.estsh.i3plus.ext.mes.api.base.IShiftExtService;
import cn.estsh.i3plus.ext.mes.api.busi.bu.ISxStandardWorkReportFormService;
import cn.estsh.i3plus.ext.mes.apiservice.dao.IPartExtDao;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesOutPutStatistics;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesShiftProdCenterRecord;
import cn.estsh.i3plus.ext.mes.pojo.model.bu.SxStandardWorkReportModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOutPutStatisticsRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesShiftProdCenterRecordRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class SxStandardWorkReportFormService implements ISxStandardWorkReportFormService {

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private IProdOrgExtService prodOrgExtService;

    @Autowired
    private IPartExtDao partExtDao;

    @Autowired
    private MesOutPutStatisticsRepository outPutStatisticsRepository;

    @Autowired
    private MesShiftProdCenterRecordRepository shiftProdCenterRecordRepository;

    @Override
    public Map<String, String> querySingleShiftList(String organizeCode) {
        Map<String, String> resultMap = null;
        List<MesShift> shiftList = shiftExtService.queryShiftList(organizeCode);
        if (!CollectionUtils.isEmpty(shiftList)) {
            for (MesShift shift : shiftList) {
                if (null == shift) {
                    continue;
                }
                if (CollectionUtils.isEmpty(resultMap)) {
                    resultMap = new HashMap<>();
                }
                resultMap.put(shift.getShiftCode(), shift.getShiftName());
            }
        }
        return resultMap;
    }

    @Override
    public List<SxStandardWorkReportModel> queryStandardWorkReportForm(SxStandardWorkReportModel model) {
        List<SxStandardWorkReportModel> resultList = null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getPartNo(), MesExtConstWords.PART_NO, packBean);
        DdlPreparedPack.getStringEqualPack(model.getWorkCenterCode(), MesExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(model.getShiftCode(), MesExtConstWords.SHIFT_CODE, packBean);
        if (!StringUtils.isEmpty(model.getWorkTimeStart()) || !StringUtils.isEmpty(model.getWorkTimeEnd())) {
            DdlPreparedPack.timeBuilder(model.getWorkTimeStart(), model.getWorkTimeEnd(), MesExtConstWords.WORK_TIME, packBean, false);
        }
        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = shiftProdCenterRecordRepository.findByHqlWhere(packBean);

        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.WORK_ORDER_TYPE.STANDARD_ORDER.getValue(), MesExtConstWords.WORK_ORDER_TYPE, packBean);
        List<MesOutPutStatistics> outPutStatisticsList = outPutStatisticsRepository.findByHqlWhere(packBean);

        if (CollectionUtils.isEmpty(shiftProdCenterRecordList) && CollectionUtils.isEmpty(outPutStatisticsList)) {
            log.info("机种别工数报表未查询到数据,维度[{}][{}],参数{}",
                    MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            return resultList;
        } else {
            if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
                log.info("机种别工数报表未查询到停开机时间记录数据,维度[{}][{}],参数{}",
                        MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            } else {
                log.info("机种别工数报表查询停开机时间记录数据量[{}],维度[{}][{}],参数{}", shiftProdCenterRecordList.size(),
                        MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            }
            if (CollectionUtils.isEmpty(outPutStatisticsList)) {
                log.info("机种别工数报表未查询到产量数据,维度[{}][{}],参数{}",
                        MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            } else {
                log.info("机种别工数报表查询产量数据量[{}],维度[{}][{}],参数{}", outPutStatisticsList.size(),
                        MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            }
        }

        packWorkTime(shiftProdCenterRecordList, outPutStatisticsList, model);

        Map<String, List<MesShiftProdCenterRecord>> shiftProdCenterRecordMap = packShiftProdCenterRecordMap(shiftProdCenterRecordList, model.getDimension1());
        Map<String, List<MesOutPutStatistics>> outPutStatisticsMap = packOutPutStatisticsMap(outPutStatisticsList, model.getDimension1());

        log.info("机种别工数报表根据维度封装数据成功,维度[{}][{}],参数{}",
                MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));

        List<String> keyList = packKeyList(shiftProdCenterRecordMap, outPutStatisticsMap);

        if (CollectionUtils.isEmpty(keyList)) {
            log.info("机种别工数报表获取行数据唯一键KEY失败,维度[{}][{}],参数{}",
                    MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
            return resultList;
        }

        Map<String, List<MesWorkCenter>> centerMap = getCenterMap(model.getOrganizeCode());
        Map<String, String> shiftMap = querySingleShiftList(model.getOrganizeCode());

        Map<String, Double> partStandardWorkMap = partExtDao.queryPartExtStandardWorkMap(model.getOrganizeCode());

        for (String key : keyList) {
            if (StringUtils.isEmpty(key)) {
                continue;
            }

            List<MesShiftProdCenterRecord> itemList4ShiftProdCenterRecord = CollectionUtils.isEmpty(shiftProdCenterRecordMap) ? null : shiftProdCenterRecordMap.get(key);
            List<MesOutPutStatistics> itemList4OutPutStatistics = CollectionUtils.isEmpty(outPutStatisticsMap) ? null : outPutStatisticsMap.get(key);

            String[] keyArr = key.split(MesExtConstWords.AND);
            SxStandardWorkReportModel result = new SxStandardWorkReportModel();
            packResult(result, keyArr, model.getDimension1(), centerMap, shiftMap,
                    CollectionUtils.isEmpty(itemList4ShiftProdCenterRecord) ? null : itemList4ShiftProdCenterRecord.get(0),
                    CollectionUtils.isEmpty(itemList4OutPutStatistics) ? null : itemList4OutPutStatistics.get(0));
            result.setTotalWorkTime(getTotalWorkTime(itemList4ShiftProdCenterRecord));
            result.setQty(getQty(itemList4OutPutStatistics));
            result.setStandardWork((!CollectionUtils.isEmpty(partStandardWorkMap) && partStandardWorkMap.containsKey(result.getPartNo())) ?
                    partStandardWorkMap.get(result.getPartNo()) : new Double(0));
            result.setRealWork(calcPointTwo(result.getTotalWorkTime(), result.getQty()));
            result.setWorkRate(getWorkRate(result.getStandardWork(), result.getRealWork()));

            if (CollectionUtils.isEmpty(resultList)) {
                resultList = new ArrayList<>();
            }

            resultList.add(result);
        }

        log.info("机种别工数报表数据开始重新排序,维度[{}][{}],参数{}",
                MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
        if (!CollectionUtils.isEmpty(resultList)) {
            resultList = sortResultList(resultList, model.getDimension1());
            log.info("机种别工数报表数据重新排序成功,维度[{}][{}],参数{}",
                    MesExtEnumUtil.REPORT_DIMENSION_DATE.valueOfDescription(model.getDimension()), MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.valueOfDescription(model.getDimension1()), JSONObject.toJSONString(model));
        }
        return resultList;
    }

    private Double getWorkRate(Double standardWork, Double realWork) {
        if (!StringUtils.isEmpty(standardWork) && !StringUtils.isEmpty(realWork)) {
            return MathOperation.sub(standardWork, realWork);
        }
        return null;
    }

    private List<SxStandardWorkReportModel> sortResultList(List<SxStandardWorkReportModel> resultList, Integer dimension) {
        switch (MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.getByValue(dimension)) {
            case CENTER:
                resultList = resultList.stream().sorted(Comparator.comparing(SxStandardWorkReportModel::getWorkTime)
                        .thenComparing(SxStandardWorkReportModel::getPartNo)
                        .thenComparing(SxStandardWorkReportModel::getWorkCenterCode)).collect(Collectors.toList());
                break;
            case SHIFT:
                resultList = resultList.stream().sorted(Comparator.comparing(SxStandardWorkReportModel::getWorkTime)
                        .thenComparing(SxStandardWorkReportModel::getPartNo)
                        .thenComparing(SxStandardWorkReportModel::getWorkCenterCode)
                        .thenComparing(SxStandardWorkReportModel::getShiftCode)).collect(Collectors.toList());
                break;
            case PART:
            default:
                resultList = resultList.stream().sorted(Comparator.comparing(SxStandardWorkReportModel::getWorkTime)
                        .thenComparing(SxStandardWorkReportModel::getPartNo)).collect(Collectors.toList());
                break;
        }
        return resultList;
    }

    private Double calcPointTwo(Double d1, Double d2) {
        if (MathOperation.compareTo(d2, new Double(0)) == 0) {
            return null;
        }
        BigDecimal b = new BigDecimal(MathOperation.div(d1, d2));
        return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    private Double getQty(List<MesOutPutStatistics> outPutStatisticsList) {
        if (CollectionUtils.isEmpty(outPutStatisticsList)) {
            return new Double(0);
        }
        return MathOperation.sub(
                outPutStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getQty()))).mapToDouble(MesOutPutStatistics::getQty).sum(),
                outPutStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getRemakeQty()))).mapToDouble(MesOutPutStatistics::getRemakeQty).sum());
    }

    private Double getTotalWorkTime(List<MesShiftProdCenterRecord> shiftProdCenterRecordList) {
        if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
            return new Double(0);
        }
        List<MesShiftProdCenterRecord> prodList = shiftProdCenterRecordList.stream().filter(o -> (null != o &&
                (MesExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_PROD.getValue() == o.getProdType() || MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_PROD.getValue() == o.getProdType()))).collect(Collectors.toList());
        List<MesShiftProdCenterRecord> stopList = shiftProdCenterRecordList.stream().filter(o -> (null != o &&
                (MesExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_STOP_CENTER.getValue() == o.getProdType() || MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getValue() == o.getProdType()))).collect(Collectors.toList());
        return MathOperation.sub(getWorkTimeTotal(prodList), getWorkTimeTotal(stopList));
    }

    private Double getWorkTimeTotal(List<MesShiftProdCenterRecord> shiftProdCenterRecordList) {
        return CollectionUtils.isEmpty(shiftProdCenterRecordList) ? new Double(0) :
                shiftProdCenterRecordList.stream().filter(o -> (null != o &&
                        !StringUtils.isEmpty(o.getStartTime()) && !StringUtils.isEmpty(o.getEndTime()) && !StringUtils.isEmpty(o.getWorkerQty()))).
                        mapToDouble(o -> (MathOperation.mul(calcMin(o.getStartTime(), o.getEndTime()), o.getWorkerQty()))).sum();
    }

    private Double calcMin(String startTime, String endTime) {
        return MathOperation.div(Double.parseDouble(String.valueOf(TimeTool.stringParseToDate(endTime).getTime() - TimeTool.stringParseToDate(startTime).getTime())), 60000);
    }

    private Map<String, List<MesWorkCenter>> getCenterMap(String organizeCode) {
        List<MesWorkCenter> workCenterList = prodOrgExtService.queryWorkCenterList(organizeCode);
        return CollectionUtils.isEmpty(workCenterList) ? null :
                workCenterList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkCenter::getWorkCenterCode));
    }

    private void packResult(SxStandardWorkReportModel result, String[] keyArr, Integer dimension, Map<String, List<MesWorkCenter>> centerMap,
                            Map<String, String> shiftMap, MesShiftProdCenterRecord shiftProdCenterRecord, MesOutPutStatistics outPutStatistics) {
        result.setWorkTime(keyArr[0]);
        result.setPartNo(keyArr[1]);
        if (null == shiftProdCenterRecord) {
            result.setPartNameRdd(outPutStatistics.getPartNameRdd());
        } else {
            result.setPartNameRdd(shiftProdCenterRecord.getPartNameRdd());
        }

        switch (MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.getByValue(dimension)) {
            case CENTER:
                result.setWorkCenterCode(keyArr[2]);
                break;
            case SHIFT:
                result.setWorkCenterCode(keyArr[2]);
                result.setShiftCode(keyArr[3]);
                break;
            case PART:
            default:
                break;
        }

        result.setWorkCenterName(
                (!StringUtils.isEmpty(result.getWorkCenterCode()) && !CollectionUtils.isEmpty(centerMap) && centerMap.containsKey(result.getWorkCenterCode())) ?
                        centerMap.get(result.getWorkCenterCode()).get(0).getWorkCenterName() : null);
        result.setShiftName(
                (!StringUtils.isEmpty(result.getShiftCode()) && !CollectionUtils.isEmpty(shiftMap) && shiftMap.containsKey(result.getShiftCode())) ?
                        shiftMap.get(result.getShiftCode()) : null);
    }

    private void packWorkTime(List<MesShiftProdCenterRecord> shiftProdCenterRecordList, List<MesOutPutStatistics> outPutStatisticsList, SxStandardWorkReportModel model) {
        if (MesExtEnumUtil.REPORT_DIMENSION_DATE.ONE.getValue() == model.getDimension()) {
            String workTime = new StringJoiner(MesExtConstWords.TO).add(model.getWorkTimeStart()).add(model.getWorkTimeEnd()).toString();
            if (!CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
                shiftProdCenterRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(workTime);
                });
            }
            if (!CollectionUtils.isEmpty(outPutStatisticsList)) {
                outPutStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(workTime);
                });
            }
        } else if (MesExtEnumUtil.REPORT_DIMENSION_DATE.YEAR.getValue() == model.getDimension()) {
            if (!CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
                shiftProdCenterRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(o.getWorkTime().substring(0, 4));
                });
            }
            if (!CollectionUtils.isEmpty(outPutStatisticsList)) {
                outPutStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(o.getWorkTime().substring(0, 4));
                });
            }

        } else if (MesExtEnumUtil.REPORT_DIMENSION_DATE.MONTH.getValue() == model.getDimension()) {
            if (!CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
                shiftProdCenterRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(o.getWorkTime().substring(0, 7));
                });
            }
            if (!CollectionUtils.isEmpty(outPutStatisticsList)) {
                outPutStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()))).forEach(o -> {
                    o.setWorkTime(o.getWorkTime().substring(0, 7));
                });
            }
        }
    }

    private Map<String, List<MesShiftProdCenterRecord>> packShiftProdCenterRecordMap(List<MesShiftProdCenterRecord> shiftProdCenterRecordList, Integer dimension) {
        Map<String, List<MesShiftProdCenterRecord>> shiftProdCenterRecordMap = null;
        if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) {
            return shiftProdCenterRecordMap;
        }
        switch (MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.getByValue(dimension)) {
            case CENTER:
                shiftProdCenterRecordMap = shiftProdCenterRecordList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getWorkCenterCode())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).add(o.getWorkCenterCode()).toString())));
                break;
            case SHIFT:
                shiftProdCenterRecordMap = shiftProdCenterRecordList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getWorkCenterCode()) && !StringUtils.isEmpty(o.getShiftCode())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).add(o.getWorkCenterCode()).add(o.getShiftCode()).toString())));
                break;

            case PART:
            default:
                shiftProdCenterRecordMap = shiftProdCenterRecordList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).toString())));
                break;
        }
        return shiftProdCenterRecordMap;
    }

    private Map<String, List<MesOutPutStatistics>> packOutPutStatisticsMap(List<MesOutPutStatistics> outPutStatisticsList, Integer dimension) {
        Map<String, List<MesOutPutStatistics>> outPutStatisticsMap = null;
        if (CollectionUtils.isEmpty(outPutStatisticsList)) {
            return outPutStatisticsMap;
        }
        switch (MesExtEnumUtil.REPORT_DIMENSION_STANDARD_WORK.getByValue(dimension)) {
            case CENTER:
                outPutStatisticsMap = outPutStatisticsList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getWorkCenterCode())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).add(o.getWorkCenterCode()).toString())));
                break;
            case SHIFT:
                outPutStatisticsMap = outPutStatisticsList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getWorkCenterCode()) && !StringUtils.isEmpty(o.getShiftCode())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).add(o.getWorkCenterCode()).add(o.getShiftCode()).toString())));
                break;
            case PART:
            default:
                outPutStatisticsMap = outPutStatisticsList.stream().filter(
                        o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getPartNo())))
                        .collect(Collectors.groupingBy(o -> (new StringJoiner(MesExtConstWords.AND)
                                .add(o.getWorkTime()).add(o.getPartNo()).toString())));
                break;
        }
        return outPutStatisticsMap;
    }

    private List<String> packKeyList(Map<String, List<MesShiftProdCenterRecord>> shiftProdCenterRecordMap, Map<String, List<MesOutPutStatistics>> outPutStatisticsMap) {
        List<String> keyList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(shiftProdCenterRecordMap)) {
            keyList.addAll(new ArrayList<>(shiftProdCenterRecordMap.keySet()));
        }
        if (!CollectionUtils.isEmpty(outPutStatisticsMap)) {
            keyList.addAll(new ArrayList<>(outPutStatisticsMap.keySet()));
        }

        keyList = CollectionUtils.isEmpty(keyList) ? null : keyList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(keyList)) {
            Collections.sort(keyList);
        }
        return keyList;
    }

}
