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

import cn.com.qmth.stmms.biz.common.BaseQueryService;
import cn.com.qmth.stmms.biz.report.dao.ReportSubjectClassGroupDao;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectClassGroup;
import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassGroupService;
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 javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.LinkedList;
import java.util.List;

@Service
public class ReportSubjectClassGroupServiceImpl extends BaseQueryService<ReportSubjectClassGroup>
        implements ReportSubjectClassGroupService {

    @Autowired
    private ReportSubjectClassGroupDao reportSubjectClassGroupDao;

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

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

    @Override
    public ReportSubjectClassGroup save(ReportSubjectClassGroup r) {
        return reportSubjectClassGroupDao.save(r);
    }

    @Override
    public ReportSubjectClassGroup findOne(Integer examId, String subjectCode, String className, boolean objective,
            String paperType, Integer groupNumber) {
        ReportSubjectQuery query = new ReportSubjectQuery();
        query.setExamId(examId);
        query.setSubjectCode(subjectCode);
        query.setClassName(className);
        query.setObjective(objective);
        query.setGroupNumber(groupNumber);
        if (objective) {
            query.setPaperType(paperType);
            if (paperType == null) {
                query.setNullPaperType(true);
            }
        }
        List<ReportSubjectClassGroup> list = findByQuery(query);
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<ReportSubjectClassGroup> findByQuery(final ReportSubjectQuery query) {
        query.setSort(new Sort(Direction.ASC, "groupNumber"));
        Page<ReportSubjectClassGroup> result = reportSubjectClassGroupDao
                .findAll(new Specification<ReportSubjectClassGroup>() {

                    @Override
                    public Predicate toPredicate(Root<ReportSubjectClassGroup> 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 (StringUtils.isNotBlank(query.getClassName())) {
                            predicates.add(cb.equal(root.get("className"), query.getClassName()));
                        }
                        if (query.getGroupNumber() > 0) {
                            predicates.add(cb.equal(root.get("groupNumber"), query.getGroupNumber()));
                        }
                        if (query.getObjective() != null) {
                            predicates.add(cb.equal(root.get("objective"), query.getObjective()));
                        }
                        if (StringUtils.isNotBlank(query.getPaperType())) {
                            predicates.add(cb.equal(root.get("paperType"), query.getPaperType()));
                        } else 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);
        return result.getContent();
    }

    @Override
    public List<ReportSubjectClassGroup> findByExamIdAndSubjectCodeAndObjectiveAndPaperType(Integer examId,
            String subjectCode, boolean objective, String paperType, String className) {
        return reportSubjectClassGroupDao
                .findByExamIdAndSubjectCodeAndObjectiveAndPaperTypeAndClassName(examId, subjectCode, objective,
                        paperType, className, new Sort(Direction.ASC, "groupNumber"));
    }
}
