package cn.com.qmth.stmms.mark;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.model.Marker;
import cn.com.qmth.stmms.biz.exam.model.Tag;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.exam.service.MarkerService;
import cn.com.qmth.stmms.biz.exam.service.TagService;
import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.biz.mark.model.Task;
import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
import cn.com.qmth.stmms.biz.mark.service.TaskService;
import cn.com.qmth.stmms.common.controller.BaseController;
import cn.com.qmth.stmms.common.enums.ExamSubjectStatus;
import cn.com.qmth.stmms.common.enums.LibraryStatus;
import cn.com.qmth.stmms.common.session.model.StmmsSession;
import cn.com.qmth.stmms.common.utils.RequestUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Controller
@RequestMapping("/mark")
public class MarkController extends BaseController {

    private static Logger log = LoggerFactory.getLogger(MarkController.class);

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private MarkerService markerService;

    @Autowired
    private MarkLibraryService libraryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private TagService tagService;

    @Value("${slice.image.server}")
    private String sliceServer;

    @Value("${sheet.image.server}")
    private String sheetServer;

    @Value("${card.server}")
    private String cardServer;

    @Value("${app.index}")
    private String appIndex;

    @RequestMapping(value = "/reset", method = RequestMethod.GET)
    public ModelAndView reset(HttpServletRequest request) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        ModelAndView modelAndView = new ModelAndView("modules/mark/reset");
        modelAndView.addObject("marker", marker);
        return modelAndView;
    }

    @RequestMapping(value = "/reset", method = RequestMethod.POST)
    public ModelAndView reset(HttpServletRequest request, Marker marker) {
        Marker current = RequestUtils.getWebUser(request).getMarker();
        current.setName(marker.getName());
        current.setPassword(marker.getPassword());
        current.setLastLoginIp(request.getRemoteAddr());
        current.setLastLoginTime(new Date());
        markerService.save(current);
        return new ModelAndView("redirect:/mark/index");
    }

    @RequestMapping(value = "/subject-select", method = RequestMethod.GET)
    public ModelAndView select(HttpServletRequest request) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        ModelAndView modelAndView = new ModelAndView();
        if ("aopeng".equals(appIndex)) {
            modelAndView.setViewName("modules/mark/subjectSelectAp");
        } else {
            modelAndView.setViewName("modules/mark/subjectSelect");
        }
        modelAndView.addObject("marker", marker);
        modelAndView.addObject("subjectList",
                subjectService.list(marker.getExamId(), ExamSubjectStatus.MARKING, 0, 0, 0));

        if (StringUtils.isNotBlank(marker.getSubjectCode())) {
            clearCurrentTask(marker);
        }
        return modelAndView;
    }

    @RequestMapping(value = "/subject-select", method = RequestMethod.POST)
    public ModelAndView select(HttpServletRequest request, @RequestParam String subjectCode) {
        Marker current = RequestUtils.getWebUser(request).getMarker();
        current.setSubjectCode(subjectCode);
        markerService.save(current);
        return new ModelAndView("redirect:/mark/index");
    }

    @RequestMapping("/index")
    public ModelAndView index(HttpServletRequest request, @RequestParam(value = "mode", required = false) String mode) {
        StmmsSession session = RequestUtils.getSession(request);
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        ModelAndView modelAndView = getMarkModeView(marker, mode);
        preProcess(marker, session, modelAndView);
        return modelAndView;
    }

    private ModelAndView getMarkModeView(Marker marker, String mode) {
        if (StringUtils.isNotBlank(mode)) {
            marker.setMode(mode);
        }
        String view = null;
        if ("track".equals(marker.getMode())) {
            view = "modules/mark/markTrack";
        } else {
            marker.setMode("common");
            view = "modules/mark/markNew";
        }
        markerService.save(marker);
        return new ModelAndView(view);
    }

    @RequestMapping("/logout")
    public ModelAndView logout(HttpServletRequest request) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        clearCurrentTask(marker);
        return new ModelAndView("redirect:/mark-logout");
    }

    /**
     * 进入评卷界面后的通用预处理
     * 
     * @param marker
     * @param session
     * @param modelAndView
     * @param modelAndView
     */
    private void preProcess(Marker marker, StmmsSession session, ModelAndView modelAndView) {
        modelAndView.addObject("sliceServer", sliceServer);
        modelAndView.addObject("sheetServer", sheetServer);
        modelAndView.addObject("cardServer", cardServer);
        modelAndView.addObject("marker", marker);
        modelAndView.addObject("subject", subjectService.find(marker.getExamId(), marker.getSubjectCode()));
        clearCurrentTask(marker);
    }

    @RequestMapping("/clear")
    @ResponseBody
    public void clear(HttpServletRequest request) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        if (marker != null) {
            // 清除该评卷员当前正在评卷的指定任务
            clearCurrentTask(marker);
        }
    }

    @RequestMapping("/status")
    @ResponseBody
    public JSONObject status(HttpServletRequest request) {
        JSONObject status = new JSONObject();
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        ExamSubject subject = subjectService.find(marker.getExamId(), marker.getSubjectCode());
        if (subject == null || subject.getStatus() != ExamSubjectStatus.MARKING) {
            status.accumulate("valid", false);
            return status;
        }

        MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
        query.setExamId(marker.getExamId());
        query.setSubjectCode(marker.getSubjectCode());
        long totalCount = libraryService.countByQuery(query);

        query.setStatus(LibraryStatus.MARKED);
        long markedCount = libraryService.countByQuery(query);

        query.setMarkerId(marker.getId());
        long personCount = libraryService.countByQuery(query);

        status.accumulate("personCount", personCount);
        status.accumulate("totalCount", totalCount);
        status.accumulate("topCount", marker.getTopCount() == null ? 0 : marker.getTopCount());
        status.accumulate("markedCount", markedCount);
        status.accumulate("exceptionCount", 0);
        status.accumulate("valid", totalCount > 0);

        return status;
    }

    @RequestMapping("/gettask")
    @ResponseBody
    public Task getTask(HttpServletRequest request) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        Task task = getTask(marker);
        if (task == null) {
            task = new Task();
            task.setExist(false);
            task.setMessage("当前无评卷任务");
        }
        return task;
    }

    /**
     * 设置任务通用属性
     * 
     * @param task
     * @param marker
     * @param stage
     * @param count
     * @param bmList
     */
    private void setTaskParameter(Task task, Marker marker) {
        task.setMarkId(marker.getId());
        task.setSpent(new Date().getTime());
    }

    private Task getTask(Marker marker) {
        int retry = 1;
        Task task = null;
        while (retry <= 5 && task == null) {
            List<MarkLibrary> list = libraryService.findByStatus(marker.getExamId(), marker.getSubjectCode(),
                    LibraryStatus.WAITING, retry, 20);
            for (MarkLibrary library : list) {
                if (setCurrentTask(marker, library.getId())) {
                    task = taskService.build(library);
                    setTaskParameter(task, marker);
                    break;
                }
            }

            if (task == null) {
                retry++;
            }
        }
        return task;
    }

    @RequestMapping(value = "/savetask", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject saveTask(HttpServletRequest request, @RequestBody Task task) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        JSONObject result = new JSONObject();
        try {
            if (taskService.submit(task)) {
                releaseCurrentTask(marker, task);
                result.accumulate("success", true);
                result.accumulate("status", status(request));
            } else {
                result.accumulate("success", false);
            }
        } catch (Exception e) {
            log.error("MarkController-保存任务出错", e);
            result.accumulate("success", false);
        }
        return result;
    }

    @RequestMapping("/gethistory")
    @ResponseBody
    public Object history(HttpServletRequest request, @RequestParam int pageNumber, @RequestParam int pageSize)
            throws Exception {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        // 查找给分任务历史
        MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
        query.setExamId(marker.getExamId());
        query.setSubjectCode(marker.getSubjectCode());
        query.setMarkerId(marker.getId());
        query.setStatus(LibraryStatus.MARKED);
        query.setPageNumber(pageNumber);
        query.setPageSize(pageSize);
        query.orderByMarkerTimeDesc();
        List<Task> list = taskService.findByQuery(query);
        for (Task task : list) {
            task.setPrevious(true);
            setTaskParameter(task, marker);
        }
        return list;
    }

    @RequestMapping("/change-name")
    @ResponseBody
    public JSONObject changeName(HttpServletRequest request, @RequestParam String name,
            @RequestParam(required = false) String password) {
        Marker marker = RequestUtils.getWebUser(request).getMarker();
        JSONObject result = new JSONObject();
        marker.setName(name);
        if (StringUtils.isNotEmpty(password)) {
            marker.setPassword(password);
        }
        marker = markerService.save(marker);
        result.accumulate("success", marker != null);
        if (marker != null) {
            result.accumulate("name", marker.getName());
        }
        return result;
    }

    @RequestMapping("/tags")
    @ResponseBody
    public JSONArray getTags(HttpServletRequest request) {
        JSONArray array = new JSONArray();
        List<Tag> list = tagService.findAll();
        for (Tag tag : list) {
            JSONObject obj = new JSONObject();
            obj.accumulate("value", tag.getId());
            obj.accumulate("name", tag.getName());
            array.add(obj);
        }
        return array;
    }

    /**
     * 清除当前评卷员正在评卷的所有任务记录
     * 
     * @param marker
     * @param task
     * @param session
     */
    private void clearCurrentTask(Marker marker) {
        taskService.clearCurrent(marker);
    }

    /**
     * 清除当前评卷员已给分的评卷任务
     * 
     * @param marker
     * @param task
     * @param session
     */
    private void releaseCurrentTask(Marker marker, Task task) {
        taskService.removeCurrent(marker, task.getLibraryId());
    }

    /**
     * 尝试设置当前任务
     * 
     * @param marker
     * @param libraryId
     * @return
     */
    private boolean setCurrentTask(Marker marker, int libraryId) {
        return taskService.setCurrent(marker, libraryId);
    }
}
