package com.x.cms.assemble.control.factory;

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

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

import com.x.base.core.utils.annotation.MethodDescribe;
import com.x.cms.assemble.control.AbstractFactory;
import com.x.cms.assemble.control.Business;
import com.x.cms.core.entity.DocumentViewRecord;
import com.x.cms.core.entity.DocumentViewRecord_;

/**
 * 文档权限基础功能服务类
 * @author liyi
 */
public class DocumentViewRecordFactory extends AbstractFactory {

	public DocumentViewRecordFactory(Business business) throws Exception {
		super(business);
	}
	
	@MethodDescribe("列示指定Id的DocumentViewRecord信息列表")
	public List<DocumentViewRecord> list( List<String> ids ) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<DocumentViewRecord> cq = cb.createQuery( DocumentViewRecord.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = root.get( DocumentViewRecord_.id).in( ids );
		return em.createQuery(cq.where(p)).getResultList();
	}

	@MethodDescribe("根据文档ID列示指定Id的DocumentViewRecord信息列表")
	public List<String> listByDocument( String docId ) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<String> cq = cb.createQuery( String.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.documentId ), docId );
		cq.orderBy( cb.desc( root.get( DocumentViewRecord_.createTime ) ) );
		cq.select( root.get( DocumentViewRecord_.id ));
		return em.createQuery( cq.where(p) ).setMaxResults(50).getResultList();
	}
	
	@MethodDescribe("根据访问者姓名列示指定Id的DocumentViewRecord信息列表")
	public List<String> listByPerson( String personName ) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<String> cq = cb.createQuery( String.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.viewerName ), personName );
		cq.orderBy( cb.desc( root.get( DocumentViewRecord_.createTime ) ) );
		cq.select( root.get( DocumentViewRecord_.id ));
		return em.createQuery( cq.where(p) ).setMaxResults(50).getResultList();
	}
	
	@MethodDescribe("根据访问者姓名和文档ID列示指定Id的DocumentViewRecord信息列表")
	public List<String> listByDocAndPerson( String documentId, String personName ) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<String> cq = cb.createQuery( String.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.viewerName ), personName );
		p = cb.and( p, cb.equal( root.get( DocumentViewRecord_.documentId ), documentId ) );
		cq.select( root.get( DocumentViewRecord_.id ));
		return em.createQuery( cq.where(p) ).getResultList();
	}
	
	@MethodDescribe( "根据文档ID查询文档被访问次数" )
	public Long countWithDocmentId(String id) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery( Long.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.documentId ), id );
		cq.select( cb.sumAsLong(root.get( DocumentViewRecord_.viewCount )) ).where(p);
		return em.createQuery( cq.where(p) ).getSingleResult();
	}
	
	public List<DocumentViewRecord> listNextWithDocIds( String docId, Integer count, Object sequenceFieldValue, String order ) throws Exception {
		if( order == null || order.isEmpty() ){
			order = "DESC";
		}
		if( count == null ){
			count = 12;
		}
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<DocumentViewRecord> cq = cb.createQuery( DocumentViewRecord.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.documentId ), docId );
		p = cb.and( p, cb.isNotNull( root.get( DocumentViewRecord_.lastViewTime ) ));
		if( sequenceFieldValue != null ){
			if( "DESC".equalsIgnoreCase( order )){
				p = cb.and( p, cb.lessThan( root.get( DocumentViewRecord_.lastViewTime ), (Date)sequenceFieldValue ));
			}else{
				p = cb.and( p, cb.greaterThan( root.get( DocumentViewRecord_.lastViewTime ), (Date)sequenceFieldValue ));
			}
		}
		if( "DESC".equalsIgnoreCase( order )){
			cq.orderBy( cb.desc( root.get( DocumentViewRecord_.lastViewTime ) ) );
		}
		return em.createQuery(cq.where(p)).setMaxResults( count ).getResultList();
	}

	public Long countWithDocIds(String docId) throws Exception {
		EntityManager em = this.entityManagerContainer().get( DocumentViewRecord.class );
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery( Long.class );
		Root<DocumentViewRecord> root = cq.from( DocumentViewRecord.class );
		Predicate p = cb.equal( root.get( DocumentViewRecord_.documentId ), docId );
		if( docId != null && docId.isEmpty() ){
			p = cb.and( p, cb.equal( root.get( DocumentViewRecord_.documentId ), docId ));
		}
		cq.select( cb.count( root ));
		return em.createQuery(cq.where(p)).getSingleResult();
	}
	
}