package cn.com.qmth.stmms.biz.report.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.qmth.stmms.biz.common.BaseQueryService;
import cn.com.qmth.stmms.biz.report.dao.ReportSubjectQuestionDao;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectQuestionService;

/**
 * 客、主观题分析 service 实现
 *
 * @author xuwenjin
 * @Date 2019-04-17
 */
@Service
public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSubjectQuestion> implements
        ReportSubjectQuestionService {

    @Autowired
    private ReportSubjectQuestionDao reportSubjectQuestionDao;

    @Override
    public ReportSubjectQuestion save(ReportSubjectQuestion reportSubjectQuestion) {
        return reportSubjectQuestionDao.save(reportSubjectQuestion);
    }

    @Transactional
    @Override
    public void deleteByExamId(Integer examId) {
        reportSubjectQuestionDao.deleteByExamId(examId);
    }

    @Transactional
    @Override
    public void deleteByExamIdAndSubjectCode(Integer examId, String subjectCode) {
        reportSubjectQuestionDao.deleteByExamIdAndSubjectCode(examId, subjectCode);
    }

    @Override
    public List<ReportSubjectQuestion> findByQuery(final ReportSubjectQuery query) {
        query.setSort(new Sort(Direction.ASC, "paperType", "mainNumber", "subNumber"));
        Page<ReportSubjectQuestion> result = reportSubjectQuestionDao.findAll(
                new Specification<ReportSubjectQuestion>() {

                    @Override
                    public Predicate toPredicate(Root<ReportSubjectQuestion> root, CriteriaQuery<?> cQuery,
                            CriteriaBuilder cb) {
                        List<Predicate> predicates = new LinkedList<Predicate>();
                        if (query.getExamId() != null) {
                            predicates.add(cb.equal(root.get("examId"), query.getExamId()));
                        }
                        if (StringUtils.isNotBlank(query.getSubjectCode())) {
                            predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
                        }
                        if (query.getMainNumber() != null) {
                            predicates.add(cb.equal(root.get("mainNumber"), query.getMainNumber()));
                        }
                        if (StringUtils.isNotBlank(query.getSubNumber())) {
                            predicates.add(cb.equal(root.get("subNumber"), query.getSubNumber()));
                        }
                        if (query.getObjective() != null) {
                            predicates.add(cb.equal(root.get("objective"), query.getObjective()));
                        }
                        if (query.getObjective() != null && query.getObjective()
                                && StringUtils.isNotBlank(query.getPaperType())) {
                            predicates.add(cb.equal(root.get("paperType"), query.getPaperType()));
                        }
                        if (query.getNullPaperType() != null && query.getNullPaperType().booleanValue()) {
                            predicates.add(cb.isNull(root.get("paperType")));
                        }
                        return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates
                                .toArray(new Predicate[predicates.size()]));
                    }
                }, query);
        List<ReportSubjectQuestion> list = new ArrayList<ReportSubjectQuestion>();
        list.addAll(result.getContent());
        questionSort(list);
        return list;
    }

    @Override
    public ReportSubjectQuestion findOne(Integer examId, String subjectCode, boolean objective, String paperType,
            Integer mainNumber, String subNumber) {
        ReportSubjectQuery query = new ReportSubjectQuery();
        query.setExamId(examId);
        query.setSubjectCode(subjectCode);
        query.setObjective(objective);
        query.setPaperType(paperType);
        query.setMainNumber(mainNumber);
        query.setSubNumber(subNumber);
        List<ReportSubjectQuestion> list = findByQuery(query);
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<ReportSubjectQuestion> findByExamIdAndSubjectCodeAndObjectiveAndPaperType(Integer examId,
            String subjectCode, boolean objective, String paperType) {
        List<ReportSubjectQuestion> list = reportSubjectQuestionDao.findByExamIdAndSubjectCodeAndObjectiveAndPaperType(
                examId, subjectCode, objective, paperType, new Sort(Direction.ASC, "mainNumber", "subNumber"));
        questionSort(list);
        return list;
    }

    private List<ReportSubjectQuestion> questionSort(List<ReportSubjectQuestion> list) {
        Collections.sort(list, new Comparator<ReportSubjectQuestion>() {

            @Override
            public int compare(ReportSubjectQuestion o1, ReportSubjectQuestion o2) {
                int i = o1.getMainNumber() - o2.getMainNumber();
                if (i == 0) {
                    if (o1.getSubNumber().contains("-")) {
                        String[] o1s = o1.getSubNumber().split("-");
                        String[] o2s = o2.getSubNumber().split("-");
                        int j = Integer.parseUnsignedInt(o1s[0]) - Integer.parseUnsignedInt(o2s[0]);
                        if (j == 0) {
                            return Integer.parseUnsignedInt(o1s[1]) - Integer.parseUnsignedInt(o2s[1]);
                        } else {
                            return j;
                        }
                    } else {
                        return Integer.parseUnsignedInt(o1.getSubNumber())
                                - Integer.parseUnsignedInt(o2.getSubNumber());
                    }
                }
                return i;
            }
        });
        return list;
    }

}
