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

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

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;

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.distributpaper.dao.FormallyHistoryDao;
import cn.com.qmth.stmms.biz.distributpaper.model.FormallyHistory;
import cn.com.qmth.stmms.biz.distributpaper.query.FormallyHistorySearchQuery;
import cn.com.qmth.stmms.biz.distributpaper.service.FormallyHistoryService;
import cn.com.qmth.stmms.biz.exam.model.Marker;
import cn.com.qmth.stmms.biz.exam.service.MarkerService;

@Service
public class FormallyHistoryServiceImpl implements FormallyHistoryService {

    @Autowired
    private FormallyHistoryDao formallyHistoryDao;

    @Autowired
    private MarkerService markerService;

    @Transactional
    public FormallyHistory save(FormallyHistory formallyHistory) {
        formallyHistoryDao.save(formallyHistory);
        return buildFormallyHistory(formallyHistory);
    }

    public FormallyHistory findById(Integer id) {
        FormallyHistory formallyHistory = formallyHistoryDao.findOne(id);
        return buildFormallyHistory(formallyHistory);
    }

    @Transactional
    public void deleteById(Integer id) {
        formallyHistoryDao.delete(id);
    }

    @Transactional
    public void delete(FormallyHistory formallyHistory) {
        formallyHistoryDao.delete(formallyHistory);
    }

    public List<FormallyHistory> getHistoryByScorer(Integer examId, Integer subjectId, Integer blockId, Integer scorer) {
        /*
         * List<FormallyHistory> list = formallyHistoryDao
         * .findByExamIdAndSubjectIdAndBlockIdAndSchoolIdAndScorer(examId,
         * subjectId, blockId, schoolId, scorer); for (FormallyHistory
         * formallyHistory : list) { buildFormallyHistory(formallyHistory); }
         * return list;
         */
        return null;
    }

    public List<FormallyHistory> getHistoryByScorerAndIsChecked(Integer examId, Integer subjectId, Integer blockId,
            Integer scorer, boolean isChecked) {
        // List<FormallyHistory> list = formallyHistoryDao
        // .findByExamIdAndSubjectIdAndBlockIdAndSchoolIdAndScorerAndIsChecked(examId,
        // subjectId, blockId, schoolId, scorer, isChecked);
        // for (FormallyHistory formallyHistory : list) {
        // buildFormallyHistory(formallyHistory);
        // }
        // return list;
        return null;

    }

    private FormallyHistory buildFormallyHistory(FormallyHistory formallyHistory) {
        Marker marker = markerService.findById(formallyHistory.getScorer());
        formallyHistory.setMarker(marker);
        return formallyHistory;
    }

    public FormallyHistorySearchQuery findByQuery(final FormallyHistorySearchQuery query) {
        Page<FormallyHistory> result = formallyHistoryDao.findAll(new Specification<FormallyHistory>() {

            @Override
            public Predicate toPredicate(Root<FormallyHistory> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = new LinkedList<Predicate>();
                EntityType<FormallyHistory> ci_ = root.getModel();
                if (query.getLibraryId() != null) {
                    predicates.add(cb.equal(root.get("libraryId"), query.getLibraryId()));
                }
                if (query.getStatus() != null) {
                    predicates.add(cb.equal(root.get("status"), query.getStatus()));
                }
                if (query.getPaperNumber() != null) {
                    predicates.add(cb.equal(root.get("paperNumber"), query.getPaperNumber()));
                }
                if (query.getBlockId() != null) {
                    predicates.add(cb.equal(root.get("blockId"), query.getBlockId()));
                }
                if (query.getIsChecked() != null) {
                    predicates.add(cb.equal(root.get("isChecked"), query.getIsChecked()));
                }
                // 发放时间处理
                Predicate issueDate;

                if (query.getStartTime() != null && query.getEndTime() != null) {
                    Expression<Date> start = cb.literal(query.getStartTime());
                    Expression<Date> end = cb.literal(query.getEndTime());
                    issueDate = cb.between(root.get(ci_.getSingularAttribute("scoreTime", Date.class)), start, end);
                    predicates.add(issueDate);
                }

                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                        .size()]));
            }
        }, query);

        query.setResult(result.getContent());
        query.setTotalCount(result.getTotalElements());
        query.setTotalPage(result.getTotalPages());
        List<FormallyHistory> list = query.getResult();
        for (FormallyHistory formallyHistory : list) {
            buildFormallyHistory(formallyHistory);
        }
        return query;
    }

    @Override
    public List<FormallyHistory> findByLibraryId(int libraryId) {
        List<FormallyHistory> list = formallyHistoryDao.findByLibraryId(libraryId,
                new Sort(Direction.DESC, "scoreTime"));
        for (FormallyHistory history : list) {
            buildFormallyHistory(history);
        }
        return list;
    }

    @Override
    public FormallyHistory findLastByLibraryId(int libraryId) {
        FormallyHistorySearchQuery query = new FormallyHistorySearchQuery();
        query.setLibraryId(libraryId);
        query.setSort(new Sort(Direction.DESC, "scoreTime"));
        query.setPageNumber(1);
        query.setPageSize(1);
        query = findByQuery(query);
        if (query.getCurrentCount() > 0) {
            return query.getResult().get(0);
        } else {
            return null;
        }
    }

    @Override
    public List<FormallyHistory> findByScorer(int markerId) {
        List<FormallyHistory> list = formallyHistoryDao.findByScorer(markerId);
        return list;
    }

}
