package cn.com.qmth.stmms.biz.utils;

import cn.com.qmth.stmms.biz.exam.model.Marker;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.SetMultimap;

import java.text.ParseException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Redis zset替代方案，单JVM内部针对已领取未给分正评任务的管理工具
 *
 * @author luoshi
 */
public class FormalTaskUtil {

    private static SetMultimap<String, TaskEntry> taskMap = HashMultimap.create();

    /**
     * 尝试领取某个任务
     *
     * @param marker
     * @param taskId
     * @return
     */
    public static boolean add(Marker marker, String taskId) {
        String key = getKey(marker);
        TaskEntry obj = new TaskEntry(marker.getId(), taskId);

        synchronized (FormalTaskUtil.class) {
            if (taskMap.containsEntry(key, obj)) {
                return false;
            } else {
                taskMap.put(key, obj);
                return true;
            }
        }
    }

    /**
     * 是否已领取某个任务
     *
     * @param marker
     * @param taskId
     * @return
     */
    public static boolean exists(Marker marker, String taskId) {
        String key = getKey(marker);
        Set<TaskEntry> set = taskMap.get(key);
        if (set != null) {
            boolean success = false;
            Set<TaskEntry> loopSet = new HashSet<>(set);
            for (TaskEntry entry : loopSet) {
                if (entry.getTaskId().equals(taskId) && entry.getMarkerId() == marker.getId()) {
                    success = true;
                    break;
                }
            }
            loopSet.clear();
            return success;
        }
        return false;
    }

    /**
     * 删除某个已完成的任务
     *
     * @param marker
     * @param taskId
     */
    public static void remove(Marker marker, String taskId) {
        TaskEntry obj = new TaskEntry(marker.getId(), taskId);
        synchronized (FormalTaskUtil.class) {
            taskMap.remove(getKey(marker), obj);
        }
    }

    /**
     * 某个科目已领取未给分的任务总数
     *
     * @param examId
     * @param subjectCode
     * @return
     */
    public static int count(int examId, String subjectCode, int number) {
        Set<TaskEntry> set = taskMap.get(getKey(examId, subjectCode, number));
        return set != null ? set.size() : 0;
    }

    /**
     * 某个评卷员已领取未给分的任务总数
     *
     * @param marker
     * @return
     */
    public static int count(Marker marker) {
        Set<TaskEntry> set = taskMap.get(getKey(marker));
        int count = 0;
        if (set != null) {
            Set<TaskEntry> loopSet = new HashSet<>(set);
            for (TaskEntry obj : loopSet) {
                if (obj.getMarkerId() == marker.getId()) {
                    count++;
                }
            }
            loopSet.clear();
        }
        return count;
    }

    /**
     * 清除某个科目已领取未给分的任务
     *
     * @param examId
     * @param subjectCode
     */
    public static void clear(int examId, String subjectCode, int number) {
        synchronized (FormalTaskUtil.class) {
            taskMap.removeAll(getKey(examId, subjectCode, number));
        }
    }

    /**
     * 清除某个评卷员已领取未给分的任务
     *
     * @param marker
     */
    public static void clear(Marker marker) {
        String key = getKey(marker);
        Set<TaskEntry> set = new HashSet<TaskEntry>();
        synchronized (FormalTaskUtil.class) {
            set.addAll(taskMap.get(key));
            for (TaskEntry obj : set) {
                if (obj.getMarkerId() == marker.getId()) {
                    taskMap.remove(key, obj);
                }
            }
        }
    }

    /**
     * 获取当前已领取的任务快照
     *
     * @param examId
     * @param subjectCode
     * @param groupNumber
     */
    public static Set<TaskEntry> list(Integer examId, String subjectCode, Integer groupNumber) {
        return taskMap.get(getKey(examId, subjectCode, groupNumber));
    }

    private static String getKey(int examId, String subjectCode, int number) {
        return examId + "_" + subjectCode + "_" + number;
    }

    private static String getKey(Marker marker) {
        return getKey(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
    }

    public static void clearTimeoutTask(long timeoutMinute) {
        synchronized (FormalTaskUtil.class) {
            SetMultimap<String, TaskEntry> taskMap1 = HashMultimap.create();
            // System.out.println("任务池大小："+taskMap.size());
            // System.out.println("间隔时间："+cleanMapinterval);
            if (taskMap.size() > 0) {
                Multiset<String> keysTemp = taskMap.keys();
                Set<String> setKey = new HashSet<String>();
                for (String key : keysTemp) {
                    setKey.add(key);
                }
                for (String key : setKey) {
                    Set<TaskEntry> set = taskMap.get(key);
                    if (set != null) {
                        for (TaskEntry obj : set) {
                            if (getDateDifference(obj.getTimestamp()) >= timeoutMinute) {// 如果相隔时间超过阀值，则该试卷的放入清空池中
                                taskMap1.put(key, obj);
                            }
                        }
                    }
                }
            }
            for (Map.Entry<String, TaskEntry> taskEntry : taskMap1.entries()) {
                taskMap.remove(taskEntry.getKey(), taskEntry.getValue());
            }
            taskMap1.clear();
        }
    }

    /**
     * 获取当前时间戳
     *
     * @return
     * @throws ParseException
     */
    public static Long getDateString() {
        return System.currentTimeMillis();
    }

    /**
     * 时间戳相隔分钟
     *
     * @return
     * @throws ParseException
     */
    public static Long getDateDifference(Long oldTime) {
        return (getDateString() - oldTime) / (1000 * 60);
    }
}
