package com.qmth.themis.business.constant;

import com.qmth.themis.common.contanst.Constants;
import com.qmth.themis.common.enums.Platform;
import com.qmth.themis.common.enums.Source;

import java.io.File;
import java.util.*;

/**
 * @Description: 系统常量
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2019/10/11
 */
public class SystemConstant {
    /**
     * 鉴权
     */
    public static final String ACCESS_TOKEN = "accessToken";
    public static final String SESSION_ID = "sessionId";
    public static final String ORG_INFO = "orgInfo";
    /**
     * 阿里云oss
     */
    public static final String END_POINT = "endpoint";
    public static final String ACCESS_KEY_ID = "accessKeyId";
    public static final String ACCESS_KEY_SECRET = "accessKeySecret";
    public static final String BUCKET = "bucket";
    /**
     * 腾讯云
     */
    public static final String TENCENT_APPID = "appId";
    public static final String TENCENT_KEY = "key";
    public static final long TENCENT_EXPIRE_TIME = 24 * 3600 * 30;
    /**
     * 系统相关
     */
    public static final String IMPORT_INIT = "准备开始处理导入数据";
    public static final String EXPORT_INIT = "准备开始处理导出数据";
    public static final String RECORD_ID = "recordId";
    public static final String MESSAGE = "message";
    public static final String BREACH_STATUS = "breachStatus";
    public static final String USER = "user:";
    public static final String STUDENT = "student:";
    public static final String SESSION = "session:";
    public static final String ORG = "org:cache:";
    public static final String LINK = "LINK";
    public static final String ALL_PATH = "/**";
    public static final String ACCOUNT = "account";
    public static final String STUDENT_ACCOUNT = "student";
    public static final String COUNT = "count";
    public static final String ERROR = "/error";
    public static final String MQ_TOPIC_BUFFER_LIST = "mq:topic:buffer:list";
    public static final String MQ_DELAY_TOPIC_BUFFER_LIST = "mq:delay:topic:buffer:list";
    public static final String TYPE = "type";
    public static final String LOCAL = "local";
    public static final String OSS = "oss";
    public static final String PATH = "path";
    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String TASK_ID = "taskId";
    public static final String MD5 = "md5";
    public static final String ATTACHMENT_TYPE = "attachmentType";
    public static final String UPLOAD_TYPE = "uploadType";
    public static final String DEFAULT_PASSWORD = "1jdzWuniG6UMtoa3T6uNLA==";
    public static final String USER_DIR = "user.dir";
    public static final int MAX_IMPORT_SIZE = 500;
    public static final int MAX_EXPORT_SIZE = 500;
    public static final String EXCEL_PREFIX = ".xlsx";
    public static final String TXT_PREFIX = ".txt";
    public static final String GLOBAL = "global";
    public static final String OK = "ok";
    public static String FILES_DIR;
    public static String TEMP_FILES_DIR;
    public static final String MONITOR_LIVE_URL_ = "monitorLiveUrl_";
    public static final String MONITOR_STATUS_ = "monitorStatus_";
    public static final String MONITOR_CALL_STATUS_ = "monitorCallStatus_";
    public final static String REDIS_MONITOR_SEQUENCE = "redis:seq:monitor";
    public final static String REDIS_ACTIVITY_CODE_SEQUENCE = "redis:seq:activity:code:";

    /**
     * session过期时间
     */
    public static final int WEB_SESSION_EXPIRE = 1;//过期时间1天
    public static final int WIN_SESSION_EXPIRE = 1;//过期时间1天
    public static final int MAC_SESSION_EXPIRE = 1;//过期时间1天
    public static final int WXAPP_SESSION_EXPIRE = 30;//过期时间30天
    public static final int IOS_SESSION_EXPIRE = 30;//过期时间30天
    public static final int ANDROID_SESSION_EXPIRE = 30;//过期时间30天
    //二维码过期时间（秒）
//    private final static int qrExpireTime = 120;
    public final static Long QR_EXPIRE_TIME = 86400L;
    /**
     * redis分布式锁
     */
    public static final String REDIS_LOCK_MQ_PREFIX = "lock:mq:";
    public static final String REDIS_LOCK_WEBSOCKET_PREFIX = "lock:websocket:";
    public static final String REDIS_LOCK_REEXAM_AUDITING = "lock:reexam:";
    public static final long REDIS_LOCK_MQ_TIME_OUT = 60L;
    public static final long REDIS_LOCK_WEBSOCKET_TIME_OUT = 30L;
    public static final long REDIS_LOCK_REEXAM_TIME_OUT = 30L;
    public static final long REDIS_LOCK_REEXAM_EXAM_STUDENT_TIME_OUT = 30L;
    public static final long REDIS_CACHE_TIME_OUT = 30L;
    //学生锁
    public static final String REDIS_LOCK_STUDENT_PREFIX = "lock:student:student_id_";
    //考生锁
    public static final String REDIS_LOCK_EXAM_STUDENT_PREFIX = "lock:student:student_id_";
    //计算客观分总分锁
    public static final String REDIS_LOCK_TOTAL_OBJECTIVE_SCORE_PREFIX = "lock:total_objective_score:record_id_";

    //考试记录数据持久化锁
    public static final String REDIS_LOCK_EXAM_RECORD_PERSISTED_PREFIX = "lock:exam_record_persisted:record_id_";

    //重新算分锁
    public static final String REDIS_LOCK_CALCULATE_SCORE_PREFIX = "lock:calculate_score:exam_id_";
    /**
     * redis过期时间
     */
    public static final long REDIS_EXPIRE_TIME = 60L * 1440L;//过期时间24小时
    public static final long REDIS_PHONE_EXPIRE_TIME = 60L * 43200L;//过期时间30天
    public static final long REDIS_OAUTH_EXPIRE_TIME = 2 * 60L * 60L;
    public static final long REDIS_DEFAULT_EXPIRE_TIME = 1 * 60L * 60L;
    /**
     * rocket mq
     */
    public static final int CONSUME_MESSAGE_BATCH_MAX_SIZE = 10;
    public static final int MAXRECONSUMETIMES = 3;
    //    public static final String MQDTO_OBJ = "mqDtoObj";
    public static final long MESSAGE_TIMEOUT = 3000L;
    public static List<String> mqDelayLevelList = null;
    public static final String delayLevel = "1s,5s,10s,30s,1m,2m,3m,4m,5m,6m,7m,8m,9m,10m,20m,30m,1h,2h";
    public static Map<String, Integer> mqDelayLevel = null;

    public static final int DELIVERED_ACK_TYPE = 0;//消息"已发出"，但尚未处理结束
    public static final int POSION_ACK_TYPE = 1;//消息"错误",通常表示"抛弃"此消息，比如消息重发多次后，都无法正确处理时，消息将会被删除或者DLQ(死信队列)
    public static final int STANDARD_ACK_TYPE = 2;//"标准"类型,通常表示为消息"处理成功"，broker端可以删除消息了
    public static final int REDELIVERED_ACK_TYPE = 3;//消息需"重发"，比如consumer处理消息时抛出了异常，broker稍后会重新发送此消息
    public static final int INDIVIDUAL_ACK_TYPE = 4;//表示只确认"单条消息",无论在任何ACK_MODE下
    public static final int UNMATCHED_ACK_TYPE = 5;//BROKER间转发消息时,接收端"拒绝"消息
    public static final int UNSEND_ACK_TYPE = 6;//消息未发出
    /**
     * 线程池配置
     */
    public static final String THREAD_POOL_NAME = "arbitrateThreadPool";
    public static final int THREAD_POOL_CORE_POOL_SIZE = 20;
    public static final int THREAD_POOL_MAX_POOL_SIZE = 40;
    public static final int THREAD_POOL_KEEP_ALIVE_SECONDS = 60;
    public static final int THREAD_POOL_QUEUE_CAPACITY = 100;
    /**
     * websocket
     */
    public static final String WEBSOCKET_OE_ONLINE_COUNT = "websocket:oe:online:count";
    public static final String WEBSOCKET_ADMIN_ONLINE_COUNT = "websocket:admin:online:count";
    public static final String GET = "get";
    public static final long WEBSOCKET_MAX_TIME_OUT = 1 * 60 * 1000;
    public static final String ACK_MESSAGE = "ackMessage";
    /**
     * 缓存配置
     */
    public static final String userOauth = "user:oauth:cache";
    public static final String studentOauth = "student:oauth:cache";
    public static final String configCache = "config:cache";
    /**
     * ehcache配置
     */
    public static final String orgCodeCache = "org_code_cache";
    public static final String roleCache = "role_cache";

    static {
        String[] strs = delayLevel.split(",");
        mqDelayLevel = new LinkedHashMap();
        for (int i = 0; i < strs.length; i++) {
            mqDelayLevel.put(strs[i], i + 1);
        }
        mqDelayLevelList = Arrays.asList(strs);
    }

    /**
     * 获取过期时间
     *
     * @param platform
     * @return
     */
    public static Map<String, Object> getExpireTime(Platform platform) {
        Map<String, Object> map = new HashMap<>();
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        Long redisExpire = REDIS_EXPIRE_TIME;
        if (platform.getSource().contains(Source.ADMIN_WEB.name())) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.WEB_SESSION_EXPIRE);
        } else if (Objects.equals(platform.name(), Platform.WIN.name()) &&
                (platform.getSource().contains(Source.ADMIN_CLIENT.name()) || platform.getSource().contains(Source.OE_CLIENT.name()))) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.WIN_SESSION_EXPIRE);
        } else if (Objects.equals(platform.name(), Platform.MAC.name()) &&
                (platform.getSource().contains(Source.ADMIN_CLIENT.name()) || platform.getSource().contains(Source.OE_CLIENT.name()))) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.MAC_SESSION_EXPIRE);
        } else if (platform.getSource().contains(Source.OE_ANSWER.name())) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.WXAPP_SESSION_EXPIRE);
            redisExpire = REDIS_PHONE_EXPIRE_TIME;
        } else if (Objects.equals(platform.name(), Platform.IOS.name()) &&
                (platform.getSource().contains(Source.OE_ANSWER.name()) || platform.getSource().contains(Source.MOBILE_FIRST.name()) || platform.getSource().contains(Source.MOBILE_SECOND.name()))) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.IOS_SESSION_EXPIRE);
            redisExpire = REDIS_PHONE_EXPIRE_TIME;
        } else if (Objects.equals(platform.name(), Platform.ANDROID.name()) &&
                (platform.getSource().contains(Source.OE_ANSWER.name()) || platform.getSource().contains(Source.MOBILE_FIRST.name()) || platform.getSource().contains(Source.MOBILE_SECOND.name()))) {
            calendar.add(Calendar.DAY_OF_YEAR, SystemConstant.ANDROID_SESSION_EXPIRE);
            redisExpire = REDIS_PHONE_EXPIRE_TIME;
        }
        map.put("date", calendar.getTime());
        map.put("redisExpire", redisExpire);
        return map;
    }

    /**
     * 比较过期
     *
     * @param timestamp
     * @return
     */
    public static boolean expire(long timestamp) {
        long diff = (System.currentTimeMillis() - timestamp) / 1000;
        return diff < -1 * Constants.SIGNATURE_AHEAD_SECONDS || diff > Constants.SIGNATURE_EXPIRE_SECONDS;
    }

//    /**
//     * 毫秒时间转换
//     *
//     * @param map
//     * @return
//     */
//    public static Map timeTransform(Map map) {
//        if (Objects.nonNull(map) && Objects.nonNull(map.get("createTime")) && map.get("createTime") instanceof Long) {
//            map.put("createTime", new Date((Long) map.get("createTime")));
//        }
//        if (Objects.nonNull(map) && Objects.nonNull(map.get("startTime")) && map.get("startTime") instanceof Long) {
//            map.put("startTime", new Date((Long) map.get("startTime")));
//        }
//        if (Objects.nonNull(map) && Objects.nonNull(map.get("finishTime")) && map.get("finishTime") instanceof Long) {
//            map.put("finishTime", new Date((Long) map.get("finishTime")));
//        }
//        if (Objects.nonNull(map) && Objects.nonNull(map.get("updateTime")) && map.get("updateTime") instanceof Long) {
//            map.put("updateTime", new Date((Long) map.get("updateTime")));
//        }
//        return map;
//    }

    /**
     * 初始化附件文件路径
     */
    public static void initTempFiles() {
        StringJoiner localPath = new StringJoiner("").add(
                System.getProperty(SystemConstant.USER_DIR));
        String mkdir = localPath.toString().substring(0, localPath.toString().lastIndexOf(File.separator));
        File dir = new File(mkdir + File.separator + "themis-files");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File tempdir = new File(mkdir + File.separator + "themis-temp");
        if (!tempdir.exists()) {
            tempdir.mkdirs();
        }
        FILES_DIR = dir.getPath();
        TEMP_FILES_DIR = tempdir.getPath();
    }
}