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

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import cn.com.qmth.stmms.biz.exam.model.Marker;

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

    private static Map<String, TaskGroup> store = new HashMap<String, TaskGroup>();

    /**
     * 尝试领取某个任务
     * 
     * @param marker
     * @param libraryId
     * @return
     */
    public static boolean add(Marker marker, int libraryId) {
        return getTaskMap(marker.getExamId(), marker.getSubjectCode()).add(libraryId, marker.getId());
    }

    /**
     * 删除某个已完成的任务
     * 
     * @param marker
     * @param libraryId
     */
    public static void remove(Marker marker, int libraryId) {
        getTaskMap(marker.getExamId(), marker.getSubjectCode()).remove(libraryId);
    }

    /**
     * 某个科目已领取未给分的任务总数
     * 
     * @param examId
     * @param subjectCode
     * @return
     */
    public static int count(int examId, String subjectCode) {
        return getTaskMap(examId, subjectCode).count();
    }

    /**
     * 某个评卷员已领取未给分的任务总数
     * 
     * @param marker
     * @return
     */
    public static int count(Marker marker) {
        return getTaskMap(marker.getExamId(), marker.getSubjectCode()).count(marker.getId());
    }

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

    /**
     * 清除某个评卷员已领取未给分的任务
     * 
     * @param examId
     * @param subjectCode
     */
    public static void clear(Marker marker) {
        getTaskMap(marker.getExamId(), marker.getSubjectCode()).clear(marker.getId());
    }

    /**
     * 获取某个科目的任务控制器
     * 
     * @param examId
     * @param subjectCode
     * @return
     */
    private static TaskGroup getTaskMap(int examId, String subjectCode) {
        String key = examId + "_" + subjectCode;
        TaskGroup group = store.get(key);
        if (group == null) {
            synchronized (CurrentTaskUtil2.class) {
                group = store.get(key);
                if (group == null) {
                    group = new TaskGroup();
                    store.put(key, group);
                }
            }
        }
        return group;
    }
}

class TaskGroup {

    // 任务-评卷员对应关系
    private Map<Integer, Integer> taskStore;

    // 评卷员-任务对应关系
    private Map<Integer, Set<Integer>> markerStore;

    private Lock lock;

    public TaskGroup() {
        this.taskStore = new HashMap<Integer, Integer>();
        this.markerStore = new HashMap<Integer, Set<Integer>>();
        this.lock = new ReentrantLock();
    }

    public boolean add(int libraryId, int markerId) {
        if (taskStore.containsKey(libraryId)) {
            return false;
        }
        lock.lock();
        try {
            if (taskStore.containsKey(libraryId)) {
                return false;
            }
            taskStore.put(libraryId, markerId);
            Set<Integer> set = markerStore.get(markerId);
            if (set == null) {
                set = new HashSet<Integer>();
                markerStore.put(markerId, set);
            }
            set.add(libraryId);
            return true;
        } catch (Exception e) {
            return false;
        } finally {
            lock.unlock();
        }
    }

    public void remove(int libraryId) {
        lock.lock();
        try {
            Integer markerId = taskStore.get(libraryId);
            if (markerId != null) {
                markerStore.get(markerId).remove(libraryId);
            }
            taskStore.remove(libraryId);
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }

    public int count() {
        return taskStore.size();
    }

    public int count(int markerId) {
        try {
            return markerStore.get(markerId).size();
        } catch (Exception e) {
            return 0;
        }
    }

    public void clear() {
        lock.lock();
        try {
            taskStore.clear();
            markerStore.clear();
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }

    public void clear(int markerId) {
        lock.lock();
        try {
            Set<Integer> set = markerStore.get(markerId);
            for (Integer id : set) {
                taskStore.remove(id);
            }
            set.clear();
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }
}
