package com.engine.common.util;

import com.engine.attendance.enums.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.company.DepartmentComInfo;
import weaver.hrm.company.SubCompanyComInfo;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.time.ZoneOffset;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

@Slf4j
public class Utils<T> {
    public static Gson gson = new Gson();
    public static Type list_map_type = new TypeToken<List<Map<String,String>>>(){}.getType();
    public static Type map_type = new TypeToken<Map<String,Object>>(){}.getType();
    public static BaseBean baseBean = new BaseBean();
    /**
     * 解析格式为[{a:b,c:d}]格式的json
     * @param json
     * @return
     */
    public static List<Map<String,String>> resolveList_Map(String json){
        List<Map<String,String>> list= gson.fromJson(json,list_map_type);
        return list;
    }
    /**
     * 解析格式为{a:b,c:d}格式的json
     * @param json
     * @return
     */
    public static Map<String,Object> resolveMap(String json){
        Map<String,Object> list= gson.fromJson(json,map_type);
        return list;
    }

    /**
     * 通过接口名取得某个接口下所有实现这个接口的类
     */
    public  List<T> getAllClassByInterface(Class<?> c) {
        List<T> returnClassList = null;
        if (c.isInterface()) {
            try {
                // 获取当前的包名
                String packageName = c.getPackage().getName();
                // 获取当前包下以及子包下所以的类
                List<Class<?>> allClass = getClasses(packageName);
                if (allClass != null) {
                    returnClassList = new ArrayList();
                    for (Class<?> cls : allClass) {
                        // 判断是否是同一个接口
                        if (c.isAssignableFrom(cls)) {
                            // 本身不加入进去
                            if (!c.equals(cls)) {
                                returnClassList.add((T)cls.newInstance());
                            }
                        }
                    }
                }
            }catch (Exception e){
                baseBean.writeLog(e);
            }
        }

        return returnClassList;
    }




    /**
     * 从包package中获取所有的Class
     *
     * @param packageName
     * @return
     */
    @NotNull
    public static List<Class<?>> getClasses(String packageName) {
        // 第一个class类的集合
        List<Class<?>> classes = new ArrayList<Class<?>>();
        // 是否循环迭代
        boolean recursive = true;
        // 获取包的名字 并进行替换
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;
        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            // 循环迭代下去
            while (dirs.hasMoreElements()) {
                // 获取下一个元素
                URL url = dirs.nextElement();
                // 得到协议的名称
                String protocol = url.getProtocol();
                // 如果是以文件的形式保存在服务器上
                if ("file".equals(protocol)) {
                    // 获取包的物理路径
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    // 以文件的方式扫描整个包下的文件 并添加到集合中
                    findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
                } else if ("jar".equals(protocol)) {
                    // 如果是jar包文件
                    // 定义一个JarFile
                    JarFile jar;
                    try {
                        // 获取jar
                        jar = ((JarURLConnection) url.openConnection()).getJarFile();
                        // 从此jar包 得到一个枚举类
                        Enumeration<JarEntry> entries = jar.entries();
                        // 同样的进行循环迭代
                        while (entries.hasMoreElements()) {
                            // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
                            JarEntry entry = entries.nextElement();
                            String name = entry.getName();
                            // 如果是以/开头的
                            if (name.charAt(0) == '/') {
                                // 获取后面的字符串
                                name = name.substring(1);
                            }
                            // 如果前半部分和定义的包名相同
                            if (name.startsWith(packageDirName)) {
                                int idx = name.lastIndexOf('/');
                                // 如果以"/"结尾 是一个包
                                if (idx != -1) {
                                    // 获取包名 把"/"替换成"."
                                    packageName = name.substring(0, idx).replace('/', '.');
                                }
                                // 如果可以迭代下去 并且是一个包
                                if ((idx != -1) || recursive) {
                                    // 如果是一个.class文件 而且不是目录
                                    if (name.endsWith(".class") && !entry.isDirectory()) {
                                        // 去掉后面的".class" 获取真正的类名
                                        String className = name.substring(packageName.length() + 1, name.length() - 6);
                                        try {
                                            // 添加到classes
                                            classes.add(Class.forName(packageName + '.' + className));
                                        } catch (ClassNotFoundException e) {
                                            baseBean.writeLog(e);
                                        }
                                    }
                                }
                            }
                        }
                    } catch (IOException e) {
                        baseBean.writeLog(e);
                    }
                }

            }
        } catch (IOException e) {
            baseBean.writeLog(e);
        }

        return classes;
    }

    /**
     * 以文件的形式来获取包下的所有Class
     *
     * @param packageName
     * @param packagePath
     * @param recursive
     * @param classes
     */
    public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, List<Class<?>> classes) {
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 如果存在 就获取包下的所有文件 包括目录
        File[] dirfiles = dir.listFiles(new FileFilter() {
            // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
            @Override
            public boolean accept(File file) {
                return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
            }
        });
        // 循环所有文件
        for (File file : dirfiles) {
            // 如果是目录 则继续扫描
            if (file.isDirectory()) {
                findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
            } else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    // 添加到集合中去
                    classes.add(Class.forName(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    baseBean.writeLog(e);
                }
            }
        }
    }


    /**
     * 获得time时间内最近的前后打卡时间数据
     * @param time
     * @param clockInTimeList 打卡数据
     * @return
     */
    public static Map<ClockPointEnum,Map<String,Object>> getNearestClcokInTimeCmd(String time,List<Map<String, Object>> clockInTimeList){
        Map<ClockPointEnum,Map<String,Object>> resultMap = Maps.newHashMap();
        for (int i=0;i<clockInTimeList.size();i++){
            String signDateTime = clockInTimeList.get(i).get("signdate") +" "+clockInTimeList.get(i).get("signtime");
            int j=i+1;
            if (j > clockInTimeList.size()-1){
                j = clockInTimeList.size()-1;
            }
            String afterSignDateTime = clockInTimeList.get(j).get("signdate") +" "+clockInTimeList.get(j).get("signtime");
            if (i==0 && DateUtil.getTime(time).compareTo(DateUtil.getTime(signDateTime)) <0){
                resultMap.put(ClockPointEnum.AFTER,clockInTimeList.get(i));
            }else if (i == clockInTimeList.size()-1 && DateUtil.getTime(time).compareTo(DateUtil.getTime(signDateTime)) >0){
                resultMap.put(ClockPointEnum.BEFORE,clockInTimeList.get(i));
            }else if (DateUtil.getTime(time).compareTo(DateUtil.getTime(signDateTime)) >0 && DateUtil.getTime(time).compareTo(DateUtil.getTime(afterSignDateTime)) <0){
                resultMap.put(ClockPointEnum.BEFORE,clockInTimeList.get(i));
                resultMap.put(ClockPointEnum.AFTER,clockInTimeList.get(j));
            }else if (DateUtil.getTime(time).compareTo(DateUtil.getTime(signDateTime)) == 0){
                resultMap.put(ClockPointEnum.EQUAL,clockInTimeList.get(i));
            }
        }
        return resultMap;
    }

    /**
     * 根据核算量、核算单位，计算出具体项目时长，向上核算
     * @param hsl 核算量
     * @param hsdw 核算单位
     * @param duration 时间值
     * @param unit 时间值单位
     * @return
     */
    public static double getItemduration(double hsl, String hsdw,int duration, AccountingUnitEnum unit){
        double itemDuration = 0.0;
        BigDecimal durationBig = new BigDecimal(duration);
        BigDecimal hslBig = new BigDecimal(hsl);
        if (AccountingUnitEnum.DAY.getKey().equals(hsdw) || AccountingUnitEnum.ONCE.getKey().equals(hsdw)){
            itemDuration = hsl;
        }else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)){
            if (unit.equals(AccountingUnitEnum.MINUTES)){
                double durationHour = duration/60.0;
//                if (duration%60 > 0){
//                    durationHour = durationHour +1;
//                }
                durationBig = new BigDecimal(durationHour);
                if ((durationHour/hsl) > Math.floor(durationHour/hsl)){
                    // (durationHour/hsl)*hsl+hsl
                    durationBig = new BigDecimal(Math.floor(durationHour/hsl));
                    itemDuration = durationBig.multiply(hslBig).add(hslBig,new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }else if (unit.equals(AccountingUnitEnum.HOUR)){
                if ((duration/hsl) > Math.floor(duration/hsl)){
                    durationBig = new BigDecimal(Math.floor(duration/hsl));
                    itemDuration=durationBig.multiply(hslBig).add(hslBig,new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }

        }else if (AccountingUnitEnum.MINUTES.getKey().equals(hsdw)){
            if (unit.equals(AccountingUnitEnum.MINUTES)){
                if ((duration/hsl) > Math.floor(duration/hsl)){
                    durationBig = new BigDecimal(Math.floor(duration/hsl));
                    itemDuration=durationBig.multiply(hslBig).add(hslBig,new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }else if (unit.equals(AccountingUnitEnum.HOUR)){
                int durationMinute = duration*60;
                durationBig = new BigDecimal(durationMinute);
                if ((durationMinute/hsl) > Math.floor(durationMinute/hsl)){
                    durationBig = new BigDecimal(Math.floor(durationMinute/hsl));
                    itemDuration=durationBig.multiply(hslBig).add(hslBig,new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }
            }
        }
        return itemDuration;
    }



    /**
     * 根据核算量、核算单位，计算出具体项目时长，向下核算
     * @param hsl 核算量
     * @param hsdw 核算单位
     * @param duration 时间值
     * @param unit 时间值单位
     * @return
     */
    public static double getItemdurationDown(double hsl, String hsdw,int duration, AccountingUnitEnum unit){
        double itemDuration = 0.0;
        BigDecimal durationBig = new BigDecimal(duration);
        BigDecimal hslBig = new BigDecimal(hsl);
        if (AccountingUnitEnum.DAY.getKey().equals(hsdw) || AccountingUnitEnum.ONCE.getKey().equals(hsdw)){
            itemDuration = hsl;
        }else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)){
            if (unit.equals(AccountingUnitEnum.MINUTES)){
                double durationHour = duration/60.0;
//                if (duration%60 > 0){
//                    durationHour = durationHour +1;
//                }
                durationBig = new BigDecimal(durationHour);
                if ((durationHour/hsl) > Math.floor(durationHour/hsl)){
                    // (durationHour/hsl)*hsl+hsl
                    durationBig = new BigDecimal(Math.floor(durationHour/hsl));
                    itemDuration = durationBig.multiply(hslBig).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }else if (unit.equals(AccountingUnitEnum.HOUR)){
                if ((duration/hsl) > Math.floor(duration/hsl)){
                    durationBig = new BigDecimal(Math.floor(duration/hsl));
                    itemDuration=durationBig.multiply(hslBig).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }

        }else if (AccountingUnitEnum.MINUTES.getKey().equals(hsdw)){
            if (unit.equals(AccountingUnitEnum.MINUTES)){
                if ((duration/hsl) > Math.floor(duration/hsl)){
                    durationBig = new BigDecimal(Math.floor(duration/hsl));
                    itemDuration=durationBig.multiply(hslBig).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }

            }else if (unit.equals(AccountingUnitEnum.HOUR)){
                int durationMinute = duration*60;
                durationBig = new BigDecimal(durationMinute);
                if ((durationMinute/hsl) > Math.floor(durationMinute/hsl)){
                    durationBig = new BigDecimal(Math.floor(durationMinute/hsl));
                    itemDuration=durationBig.multiply(hslBig).doubleValue();
                }else {
                    itemDuration = durationBig.multiply(hslBig).divide(hslBig,BigDecimal.ROUND_DOWN).doubleValue();
                }
            }
        }
        return itemDuration;
    }

    /**
     * 请假、外出时间扣出休息时间
     * @param kssj 开始时间
     * @param jssj 结束时间
     * @param scheduleResult 班次
     * @return
     */
    public static int removeRestTime(String kssj,String jssj,List<Map<String, Object>> scheduleResult,String analysisDate){
        scheduleResult = scheduleResult.stream().filter(e -> ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(e.get("bdlx")) ||
                ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
        int betweenMinutes = DateUtil.getBetWeenMinutes(kssj,jssj)-removeTime(kssj,jssj,scheduleResult,analysisDate);
        return betweenMinutes;
    }

    /**
     * 开始时间和结束时间在所给班次中的占比时间
     * @param kssj
     * @param jssj
     * @param scheduleResult
     * @param analysisDate
     * @return
     */
    public static int removeTime(String kssj,String jssj,List<Map<String, Object>> scheduleResult,String analysisDate){
        int betweenMinutes = 0;
        log.info("removeRestTime  scheduleResult : {}",scheduleResult);
        for (Map<String, Object> restSchedule :scheduleResult){
            String dtkssj = Utils.getkssjTime(restSchedule,analysisDate);
            String dtjssj = Utils.getjssjTime(restSchedule,analysisDate);

            if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(dtkssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(dtjssj)) >=0){
                //休息时间在请假时间中间
                betweenMinutes = DateUtil.getBetWeenMinutes(dtkssj,dtjssj);
                log.info("休息时间在请假时间中间");
            }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(dtkssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(dtjssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(dtkssj)) >=0){
                //休息时间在请假时间 右边
                betweenMinutes = DateUtil.getBetWeenMinutes(dtkssj,jssj);
                log.info("休息时间在请假时间 右边");
            }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(dtkssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(dtjssj)) >=0 && DateUtil.getTime(kssj).compareTo(DateUtil.getTime(dtjssj)) <=0){
                //休息时间在请假时间 左边
                betweenMinutes = DateUtil.getBetWeenMinutes(kssj,dtjssj);
                log.info("休息时间在请假时间 左边");
            }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(dtkssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(dtjssj)) <=0){
                //请假时间在休息时间中间
                betweenMinutes = 0;
                log.info("请假时间在休息时间中间");
            }
        }
        return betweenMinutes;
    }

    /**
     * 扣除就餐时间
     * @param kssj 开始时间
     * @param jssj 结束时间
     * @param scheduleResult 班次
     * @return
     */
    public static int dinnerTime(String kssj,String jssj,List<Map<String, Object>> scheduleResult,String analysisDate){
        scheduleResult = scheduleResult.stream().filter(e ->ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
        int dinnerTime = removeTime(kssj,jssj,scheduleResult,analysisDate);
        return dinnerTime;
    }

    /**
     * 请假外出在加班中所占时间
     * @return
     */
    public static int getStartAndEndTime(String kssj,String jssj,Map<String, Object> leaveMap){
        String leavekssj = leaveMap.get("ksrq") + " "+leaveMap.get("kssj");
        String leavejssj = leaveMap.get("jsrq")+ " "+leaveMap.get("jssj");
        int betweenMinutes=0;
        if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) >=0){
            //请假外出时间在中间
            betweenMinutes =  DateUtil.getBetWeenMinutes(leavekssj,leavejssj);
            log.info("请假外出时间在中间");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavekssj)) >=0){
            //请假外出时间 右边
            betweenMinutes =  DateUtil.getBetWeenMinutes(leavekssj,jssj);
            log.info("请假外出时间 右边");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) >=0 && DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavejssj)) <=0){
            //休请假外出时间 左边
            betweenMinutes = DateUtil.getBetWeenMinutes(kssj,leavejssj);
            log.info("请假外出时间 左边");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) <=0){
            //请假外出时间中间
            betweenMinutes = DateUtil.getBetWeenMinutes(kssj,jssj);
            log.info("加班实际在请假外出时间中间");
        }
        return betweenMinutes;
    }

    /**
     * map中的开始时间和结束时间，在kssj和jssj中占据的分钟数
     * @return
     */
    public static int getIntersectionTime(String kssj,String jssj,Map<String, Object> map,List<Map<String, Object>> scheduleResult,String analysisDate){
        String leavekssj = map.get("kssj").toString();
        String leavejssj = map.get("jssj").toString();
        int betweenMinutes=0;
        if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) >=0){
            //时间在中间
            betweenMinutes =  removeRestTime(leavekssj,leavejssj,scheduleResult,analysisDate);
            log.info("时间在中间,被包含");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) <=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavekssj)) >=0){
            //时间 右边
            betweenMinutes =  removeRestTime(leavekssj,jssj,scheduleResult,analysisDate);
            log.info("时间 右边");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) >=0 && DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavejssj)) <=0){
            //时间 左边
            betweenMinutes = removeRestTime(kssj,leavejssj,scheduleResult,analysisDate);
            log.info("时间 左边");
        }else if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(leavekssj)) >=0 && DateUtil.getTime(jssj).compareTo(DateUtil.getTime(leavejssj)) <=0){
            //请假外出时间中间
            betweenMinutes = removeRestTime(kssj,jssj,scheduleResult,analysisDate);
            log.info("时间在中间,包含");
        }
        return betweenMinutes;
    }

    /**
     * 获得建模表对应的模块ID
     * @return
     */
    public static Map<String,String> getFormmodeIdMap(){
        String sql = "select c.id,b.tablename  from uf_jcl_form_table a left join workflow_bill b on a.tablename=b.tablename left join modeinfo c on b.id=c.formid where  (c.isDelete is null or  c.isDelete <> '1')";
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql);
        return dataList.stream().collect(Collectors.toMap(e->e.get("tablename").toString(),e->e.get("id").toString()));

    }

    /**
     * 插入
     * @param tableName
     * @param dataMap
     * @param formmodeIdMap
     */
    public static void InsertFormTable(String tableName,Map<String,Object> dataMap,Map<String,String> formmodeIdMap){
        String formmodeId = formmodeIdMap.get(tableName);
        dataMap.put("formmodeid",formmodeId);
        dataMap.put("modeuuid", UUID.randomUUID().toString());
        dataMap.put("modedatacreater","1");
        dataMap.put("modedatacreatertype","0");
        dataMap.put("modedatacreatedate",DateUtil.getCurrentTime().split(" ")[0]);
        dataMap.put("modedatacreatetime",DateUtil.getCurrentTime().split(" ")[1]);
        CommonUtil.makeInsertSql(tableName,dataMap);
    }

    /**
     * 根据班段类型获得作用时段
     * @param bdlx
     * @return
     */
    public static String getWorkFor(String bdlx){
        String workFor="";
        if (ClassSegmentTypeEnum.WORK_TIME.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.WORK_TIME.getKey();
        }else if (ClassSegmentTypeEnum.EXTENDED_OVERTIME.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.DELAY_TO_WORK_OVERTIME.getKey();
        }else if (ClassSegmentTypeEnum.EARLY_OVERTIME.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.EARLY_TO_WORK_OVERTIME.getKey();
        }else if (ClassSegmentTypeEnum.OVERTIME_PLAN.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.PLAN_WORK_OVERTIME.getKey();
        }else if (ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.LEAVE_TIME.getKey();
        }else if (ClassSegmentTypeEnum.EVECTION.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.EVECTION.getKey();
        }else if (ClassSegmentTypeEnum.OVERTIME_IN_CLASS.getKey().equals(bdlx)){
            workFor = WorkForTimeEnum.OVERTIME_IN_CLASS.getKey();
        }
        return workFor;
    }

    /**
     * 获得半天时间
     * @param scheduleResult
     * @return
     */
    public double getHalfDay(List<Map<String, Object>> scheduleResult){
        scheduleResult = scheduleResult.stream().filter(e -> !ClassSegmentTypeEnum.OVERTIME_PLAN.getKey().equals(e.get("bdlx")) &&
                !ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(e.get("bdlx")) && !ClassSegmentTypeEnum.EVECTION.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
        if (scheduleResult.size() > 0){
            String btgz = Util.null2String(scheduleResult.get(0).get("btgz"));
            String fgsjd = Util.null2String(scheduleResult.get(0).get("fgsjd"));
            if (HalfDayRuleREnum.BY_CLASS_SET.getKey().equals(btgz)){

            }else if (HalfDayRuleREnum.FIXED_DURATION.getKey().equals(btgz)){

            }else if (HalfDayRuleREnum.HALF_TOTAL_DURATION.getKey().equals(btgz)){

            }else if (HalfDayRuleREnum.HALF_RATED_DURATION.getKey().equals(btgz)){

            }
        }
        return 0;
    }

    /**
     * 重新获得排班
     * @param dataList
     * @return
     */
    public static List<Map<String, Object>> getSchedulingList(List<Map<String, Object>> dataList){
        Map<String,List<Map<String, Object>>> dataMaps = dataList.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("bcrq"))));
        List<Map<String, Object>> resultList = Lists.newArrayList();
        for (Map.Entry<String,List<Map<String, Object>>> entry:dataMaps.entrySet()){
            String bcrq = entry.getKey();
            List<Map<String, Object>> classList = entry.getValue();
            if (classList.size() > 1){
                classList = classList.stream().filter(e->!e.get("pbtj").equals(RegularScheduleTypeEnum.REGULAR.getKey())).collect(Collectors.toList());
                classList = classList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(e.get("pbrq")+" "+e.get("pbsj")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
                resultList.add(classList.get(classList.size()-1));
            }else {
                resultList.addAll(classList);
            }
        }
        return resultList;
    }

    /**
     * 相减
     * @param value1
     * @param value2
     * @return
     */
    public static double subtract(double value1,double value2){

        return new BigDecimal(value1).subtract(new BigDecimal(value2),new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
    }

    /**
     * 相加
     * @param value1
     * @param value2
     * @return
     */
    public static double add(double value1,double value2){

        return new BigDecimal(value1).add(new BigDecimal(value2),new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
    }

    /**
     *  相乘
     * @param value1
     * @param value2
     * @return
     */
    public static double multiply(double value1,double value2){

        return new BigDecimal(value1).multiply(new BigDecimal(value2),new MathContext(BigDecimal.ROUND_HALF_UP)).doubleValue();
    }

    /**
     * 根据日期和时间组装日期时间
     * @param date
     * @param time
     * @return
     */
    public static String installTime(String date ,String time){
        return date+" "+time;
    }

    /**
     * 开始时间大于结束时间
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean dateGreaterThan(String beginTime,String endTime){
        return DateUtil.getTime(beginTime).compareTo(DateUtil.getTime(endTime)) >0;
    }

    /**
     * 根据日期，日历名称id，获得当前日期类型
     * @param date
     * @param rlmc
     * @return
     */
    public static String getDateType(String date,String rlmc){
        String sql = "select rqlx from uf_jcl_kq_rlxx where rlmc=? and rq=?";
        Map<String,Object> data = DbTools.getSqlToMap(sql,rlmc,date.split(" ")[0]);
        return Util.null2String(data.get("rqlx"));
    }
    /**
     * 根据日期，分部，获得该分部下的默认日历的当前日期类型
     * @param userId
     * @param date
     * @return
     */
    public static String getDefaultDateType(String userId,String date){
        String rqlx = "";
        String sql = "select subcompanyid1 from hrmresource where id =?";
        Map<String,Object> departMentMap = DbTools.getSqlToMap(sql,userId);
        String subcompanyid1 = departMentMap.get("subcompanyid1").toString();
        String parentSubcompanyids = "";
        try {

            parentSubcompanyids = new SubCompanyComInfo().getAllParentSubcompanyId(subcompanyid1,parentSubcompanyids);
        }catch (Exception e){
            log.error("getDefaultDateType error:[{}]",e);
        }
        parentSubcompanyids = subcompanyid1+parentSubcompanyids;
        sql = "select b.szjg,a.rqlx from uf_jcl_kq_rlxx a left join uf_jcl_kq_rlmc b on a.rlmc=b.id where b.mrrl=1 and b.szjg in ("+parentSubcompanyids+") and a.rq=?";
        List<Map<String,Object>> dataList = DbTools.getSqlToList(sql,date);
        Map<String,Object> dataMap = dataList.stream().collect(Collectors.toMap(e->e.get("szjg").toString(),e->e.get("rqlx")));
        for (int i=0;i<parentSubcompanyids.split(",").length;i++){
            String subId = parentSubcompanyids.split(",")[i];
            rqlx = Util.null2String(dataMap.get(subId));
            if (!"".equals(rqlx)){
                break;
            }
        }
        return rqlx;
    }

    /**
     * 根据核算单位、时间转换成分钟
     * @param time 时间
     * @param hsdw 核算单位
     * @return
     */
    public static double converTimeToMinute(double time,String hsdw){
        if (AccountingUnitEnum.DAY.getKey().equals(hsdw)){
            time = time*24*60;
        }else if (AccountingUnitEnum.HOUR.getKey().equals(hsdw)){
            time = time*60;
        }

        return time;
    }

    /**
     * 获得班次的开始时间的提前时间
     * @param schedulingMap
     * @param date
     * @return
     */
    public static String getkssjEarliestTime(Map<String,Object> schedulingMap,String date){
        String tqdkfzs = Util.null2String(schedulingMap.get("tqdkfzs"));
        if ("".equals(tqdkfzs)){
            tqdkfzs = "60";
        }
        return DateUtil.beforeMinutes(getkssjTime(schedulingMap,date),Integer.valueOf(tqdkfzs));
    }

    /**
     * 获得班次的开始时间
     * @param schedulingMap 班次信息
     * @param date 分析日期
     * @return
     */
    public static String getkssjTime(Map<String,Object> schedulingMap,String date){
        String gsrq = Util.null2String(schedulingMap.get("gsrq"));
        String kssj = Util.null2String(schedulingMap.get("dtkssj"));
        if (gsrq.equals(ClassBelongToEnum.YESTERDAY.getKey())){
            date = DateUtil.beforeDay(date,1);
        }else if (gsrq.equals(ClassBelongToEnum.NEXTDAY.getKey())){
            date = DateUtil.AfterDay(date,1);
        }
        kssj = date+" "+kssj;

        return kssj;
    }
    /**
     * 获得班次的结束时间的退后时间
     * @param schedulingMap
     * @param date
     * @return
     */
    public static String getjssjLastestTime(Map<String,Object> schedulingMap,String date){

        String thdkfzs = Util.null2String(schedulingMap.get("thdkfzs"));
        if ("".equals(thdkfzs)){
            thdkfzs = "60";
        }

        return DateUtil.AfterMinutes(getjssjTime(schedulingMap,date),Integer.valueOf(thdkfzs));
    }
    /**
     * 获得班次的结束时间
     * @param schedulingMap 班次信息
     * @param date 分析日期
     * @return
     */
    public static String getjssjTime(Map<String,Object> schedulingMap,String date){
        String gsrq = Util.null2String(schedulingMap.get("gsrq"));
        String jssj = Util.null2String(schedulingMap.get("dtjssj"));
        String kssj = Util.null2String(schedulingMap.get("dtkssj"));
        if (gsrq.equals(ClassBelongToEnum.YESTERDAY.getKey())){
            date = DateUtil.beforeDay(date,1);
        }else if (gsrq.equals(ClassBelongToEnum.NEXTDAY.getKey())){
            date = DateUtil.AfterDay(date,1);
        }
        jssj = date+" "+jssj;
        kssj = date+" "+kssj;
        if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(jssj)) > 0) {
            jssj = DateUtil.AfterDay(date, 1) + " " + Util.null2String(schedulingMap.get("dtjssj"));
        }

        return jssj;
    }
    /**
     * 判断是否是加班类型时段
     * @param classSegmentType
     * @return
     */
    public static boolean ifOverTimeClassSegment(String classSegmentType){
        if (classSegmentType.equals(ClassSegmentTypeEnum.EXTENDED_OVERTIME.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.EARLY_OVERTIME.getKey())
                || classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_IN_CLASS.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 判断是否是休息类型时段
     * @param classSegmentType
     * @return
     */
    public static boolean ifRestClassSegment(String classSegmentType){
        if (classSegmentType.equals(ClassSegmentTypeEnum.REST_AND_DINE.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.REST_PERIOD.getKey())
                || classSegmentType.equals(ClassSegmentTypeEnum.DINING_PERIOD.getKey())){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 转换成double
     * @param num
     * @return
     */
    public static double convertDouble(Object num){
        return Util.null2String(num).equals("")?0:Double.valueOf(Util.null2String(num));
    }
}
