package com.lerx.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.search.Query;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.exception.EmptyQueryException;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.lerx.dao.iface.IArticleDao;
import com.lerx.entities.Article;
import com.lerx.entities.ArticleGroup;
import com.lerx.entities.CommentBridge;
import com.lerx.entities.HtmlFileStatic;
import com.lerx.entities.Poll;
import com.lerx.entities.SearchTotalModel;
import com.lerx.entities.VisitorsBook;
import com.lerx.hql.entities.Rs;
import com.lerx.hql.util.HibernateCallbackUtil;
import com.lerx.hql.util.HibernateUtil;
import com.lerx.hql.util.RsUtil;
import com.lerx.portal.obj.PortalStatInfo;
import com.lerx.v6.util.ArticleUtil;

public class ArticleDaoImpl extends HibernateDaoSupport implements IArticleDao {

	@Override
	public Article add(Article art) {
		
		VisitorsBook vbook = art.getVbook();
		Poll poll=art.getPoll();
		CommentBridge cb=art.getCb();
		HtmlFileStatic hfs=art.getHfs();
		if (hfs==null) {
			hfs=new HtmlFileStatic();
			art.setHfs(hfs);
		}
		this.getHibernateTemplate().save(vbook);
		this.getHibernateTemplate().save(cb);
		this.getHibernateTemplate().save(poll);
		this.getHibernateTemplate().save(hfs);
		if (art.getSrt()==null) {
			SearchTotalModel srt = new SearchTotalModel();
			art.setSrt(srt);	
		}
		if (art.getSrt()!=null) {
			this.getHibernateTemplate().save(art.getSrt());
		}
		this.getHibernateTemplate().save(art);
		cb.setObjID(art.getId());
		this.getHibernateTemplate().update(cb);
		return art;
	}
	
	@Override
	public void modify(Article art) {
		HibernateTemplate ht=this.getHibernateTemplate();
		VisitorsBook vbook = art.getVbook();
		vbook.setObjTitle(art.getSubject());
		Poll poll = art.getPoll();
		CommentBridge cb=art.getCb();
		HtmlFileStatic hfs=art.getHfs();
		if (hfs==null) {
			
			hfs=new HtmlFileStatic();
			this.getHibernateTemplate().save(hfs);
			art.setHfs(hfs);
		}
		
		if (cb.getObjTitle()==null || cb.getObjTitle().trim().equals("")) {
			cb.setObjTitle(art.getSubject());
		}
		cb.setObjID(art.getId());
		ht.saveOrUpdate(cb);
		ht.saveOrUpdate(poll);
		ht.saveOrUpdate(vbook);
		ht.saveOrUpdate(hfs);
		SearchTotalModel srt=art.getSrt();
		if (srt==null) {
			srt = new SearchTotalModel();
			srt=ArticleUtil.srtUpdate(srt, art);
		}
		if (srt.getId()==0) {
			ht.save(srt);
			art.setSrt(srt);
		}else {
			ht.update(srt);
		}
		
		ht.saveOrUpdate(art);
		ht.flush();
		ht.clear();
	
	}

	@Override
	public Article findByID(long id) {
		Article art=this.getHibernateTemplate().get(Article.class, id);
		if (art==null || art.isDeled()) {
			return null;
		}
		return art;
	}
	
	@Override
	public Article findByUuid(String uuid) {
		DetachedCriteria criteria=DetachedCriteria.forClass(Article.class);
		criteria.add(Restrictions.eq("deled", false ) );
		criteria.add(Restrictions.eq("uuid", uuid ) );
		@SuppressWarnings("unchecked")
		List<Article> lu = (List<Article>) this.getHibernateTemplate().findByCriteria(criteria);
		if (lu.size() > 0) { 
			return lu.get(0);
		}else{
			return null;
		}
	}

	@Override
	public boolean delByID(long id) {
		Article art=this.getHibernateTemplate().get(Article.class, id);
		art.setDeled(true);
		System.out.println("删除用户过程中");
		this.getHibernateTemplate().update(art);
		this.getHibernateTemplate().flush();
		this.getHibernateTemplate().clear();
		art=this.getHibernateTemplate().get(Article.class, id);
		if (art.isDeled()) {
			System.out.println("删除成功");
			return true;
		}else {
			System.out.println("删除失败");
			return false;
		}
		
		/*
		 * this.getHibernateTemplate().delete(findByID(id));
		 * 
		 * if (findByID(id) == null) { return true; } else { return false; }
		 */
	}

	@Override
	public Rs queryByGid(long gid,long startT,long endT,int firstResult, int page, int pagesize,boolean asc,int status,int img,int soul,int orderby) {
		
		DetachedCriteria criteria=DetachedCriteria.forClass(Article.class);
		criteria.add(Restrictions.eq("deled", false ) );
		switch (status) {
		case -1:
			criteria.add(Restrictions.eq("status", false ) );
			break;
		case 0:
			break;
		default:
			criteria.add(Restrictions.eq("status", true ) );
		}
		
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				criteria.createAlias("agroup", "g"); 
				
				criteria.add(Restrictions.ge("g.footLeft", g.getFootLeft() ) );
				criteria.add(Restrictions.le("g.footLeft", g.getFootRight() ) );
				
			}
			
		}
		
		if (img==1) {
			criteria.add(Restrictions.and(Restrictions.or(Restrictions.and(Restrictions.ne("thumbnail",""),Restrictions.isNotNull("thumbnail")),Restrictions.and(Restrictions.ne("titleImg",""),Restrictions.isNotNull("titleImg")) )));
//			criteria.add(Restrictions.and(Restrictions.ne("thumbnail",""),Restrictions.ne("titleImg",""),Restrictions.isNotNull("thumbnail"),Restrictions.isNotNull("titleImg"))); 
			
		}
		
		if (soul==1) {
			criteria.add(Restrictions.eq("soul", true ) );
		}
		
		if (startT>0L ) {
			criteria.add(Restrictions.ge("creationTime", startT ) );
		}
		
		if (endT>0L ) {
			criteria.add(Restrictions.le("creationTime", endT ) );
		}
		
		criteria.createAlias("vbook", "v"); 
		criteria.createAlias("cb", "c"); 
		criteria.createAlias("poll", "p");
		
		
		String ocol;
		switch (orderby) {
		case 1:			//按发布时间
			ocol="creationTime";
			break;
		case 2:			//按修改时间
			ocol="lastModifyTime";
			break;
		case 3:			//按浏览次数
			ocol="v.viewsOwn";
			break;
		case 4:			//按浏览IP次数
			ocol="v.ipOwn";
			break;
		case 5:			//按评论数
			ocol = "(c.total + p.agrees/3 + v.ipTotal/13)";
			break;
		case 6:			//按点赞数
			ocol = "(c.total/3 + p.agrees + v.ipTotal/13)";
//			ocol = "((c.total * 4 + p.agrees*3 + v.ipOwn*2) *(TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1)))/(( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1))/3+1)";
			break;
		case 7:			//按平均热度
			ocol = "((c.total * 2 + p.agrees*3 + v.ipTotal*3) *( TO_DAYS(NOW()) - ( TO_DAYS(a.creationTime)-1 ) )   /  ( ( TO_DAYS(NOW()) - ( TO_DAYS(creationTime)-1 ) ) /3 ))";
			break;
		case 8:
			ocol = "soul";
			break;
		case 9:
			ocol = "rand()";
			break;
		default:		//默认排序，按id
			ocol="id";
		}
		
		if (orderby<9) {
			if (asc) {
				criteria.addOrder( Order.asc(ocol) );
			}else {
				criteria.addOrder( Order.desc(ocol) );
			}
		}else {
			criteria.add(Restrictions.sqlRestriction("1=1 order by rand()"));
		}
		
		
		
		Rs rs=HibernateCallbackUtil.getRs(this.getHibernateTemplate(), criteria, firstResult, page, pagesize);
		return rs;
		
		
		
		/*String ascCmd;
		if (asc) {
			ascCmd=" asc ";
		}else {
			ascCmd=" desc ";
		}
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		
		if (gCmd.equals("") && gid!=0){
			//gCmd=" where 1<>1 ";
			return RsUtil.init(1, 1, 0);
		}
		
		String statusSql;
		switch (status) {
		case -1:
			statusSql=" and a.status is false ";
			break;
		case 0:
			statusSql="";
			break;
		default:
			statusSql=" and a.status is true ";
		}
		if (!statusSql.trim().equals("")) {
			if (gCmd.trim().equals("")){
				gCmd = statusSql;
			}else {
				gCmd = gCmd + statusSql;
			}
		}
		
		if (img==1) {
			gCmd+=" and ((a.thumbnail is not null and trim(a.thumbnail)<>'') or (a.titleImg is not null and trim(a.titleImg)<>'')) ";
		}
		
		if (soul==1) {
			gCmd+=" and a.soul is true ";
		}
		String orderbySQLAdd="";
		switch (orderby) {
		case 1:			//按发布时间
			orderbySQLAdd = " a.creationTime ";
			break;
		case 2:			//按修改时间
			orderbySQLAdd = " a.lastModifyTime ";
			break;
		case 3:			//按浏览次数
			orderbySQLAdd = " a.vbook.viewsOwn ";
			break;
		case 4:			//按浏览IP次数
			orderbySQLAdd = " a.vbook.ipOwn ";
			break;
		case 5:			//按评论数
			orderbySQLAdd = " a.cb.total ";
			break;
		case 6:			//按平均热度
			orderbySQLAdd = " (a.poll.agrees/( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1) )) desc,(a.vbook.ipOwn/( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1) )) ";
			break;
		case 7:			//按精华
			orderbySQLAdd = " a.soul ";
			break;
		default:		//默认排序，按id
			orderbySQLAdd = " a.id ";
		}
		
		String hql = "from Article a where a.agroup.deled is false " + gCmd + " order by a.topOne desc, "+orderbySQLAdd + ascCmd;
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);*/
	}
	
	@Override
	public Rs queryByUid(long uid,long gid,int firstResult, int page, int pagesize,boolean asc,int status) {
		String ascCmd;
		if (asc) {
			ascCmd=" asc ";
		}else {
			ascCmd=" desc ";
		}
		String gCmd="";
		
		
		if (uid==0){
			
			return RsUtil.init(1, 1, 0);
		}
		
		gCmd = " and a.user.id = " + uid;
		
		
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = gCmd + " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		
		String statusSql;
		switch (status) {
		case -1:
			statusSql=" a.status is false ";
			break;
		case 0:
			statusSql="";
			break;
		default:
			statusSql=" a.status is true ";
		}
		if (!statusSql.trim().equals("")) {
			gCmd = gCmd+ " and " + statusSql;
			/*
			 * if (gCmd.trim().equals("")){ gCmd = " where " + statusSql; }else { gCmd =
			 * gCmd+ " and " + statusSql; }
			 */
		}
		
		String hql = "from Article a where a.deled is false " + gCmd + " order by a.creationTime "+ascCmd+",a.id " + ascCmd;
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);
	}

	@Override
	public Rs hotByGid(long gid,int firstResult, int page, int pagesize) {
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		String hql = "from Article a  where a.deled is false and a.status is true "+gCmd+" order by (a.poll.agrees/( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1) )) desc,(a.vbook.ipOwn/( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1) )) desc, a.id desc";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);
	}
	
	//点击量
	@Override
	public Rs clicksByGid(long gid,int firstResult, int page, int pagesize) {
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		String hql = "from Article a  where a.deled is false and a.status is true "+gCmd+" order by a.vbook.ipOwn desc";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);
	}
	
	@Override
	public Rs randByGid(long gid, int page, int pagesize) {
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		String hql = "from Article a  where a.deled is false and a.status is true "+gCmd+" order by rand()";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, 0, page, pagesize);
	}
	
	@Override
	public Rs hotByUid(long uid,long gid,int firstResult, int page, int pagesize) {
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		String hql = "from Article a  where a.deled is false and a.status is true and a.user.id="+uid+gCmd+" order by (a.hotn/( TO_DAYS(NOW()) - (TO_DAYS(a.creationTime)-1) )) desc, a.id desc";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);
	}
	
	
	@Override
	public Rs clicksByUid(long uid,long gid,int firstResult, int page, int pagesize) {
		String gCmd="";
		if (gid>0L) {
			ArticleGroup g = (ArticleGroup) this.getHibernateTemplate().get(
					ArticleGroup.class, gid);
			if (g!=null){
				gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			}
			
		}
		String hql = "from Article a  where a.deled is false and a.status is true and a.user.id="+uid+gCmd+" order by a.vbook.ipOwn desc";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, firstResult, page, pagesize);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Rs search(long gid,String key,boolean fulltext,int firstResult, int page, int pagesize) {
		
		FullTextSession fts = Search.getFullTextSession(this.getSessionFactory().getCurrentSession());
	    QueryBuilder qb = fts.getSearchFactory().buildQueryBuilder().forEntity(Article.class).get();
	    
	    Query luceneQuery;
	    List<Article> data;
	    Rs rs=null;
	    try {
			luceneQuery = qb.keyword().onFields("content","subject","titleImgTxt","author","authorDept").matching(key).createQuery();
			
			FullTextQuery query = fts.createFullTextQuery(luceneQuery, Article.class);
			query.addQueryHint("status is true");
			query.addQueryHint("deled is false");
		    query.setFirstResult((page - 1) * pagesize);
		    query.setMaxResults(pagesize);
		    data = query.list();
		    rs=RsUtil.init(page, pagesize, query.getResultSize());
		    List<Article> la=ArticleUtil.hightLight(luceneQuery, data, "content","subject","titleImgTxt","author","authorDept");
		    rs.setList(la);
		} catch (EmptyQueryException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
		}
	    
		if (rs!=null) {
			/*for (Object art:rs.getList()) {
		    	Article a=(Article) art;
		    	System.out.println("a.getSubject():"+a.getSubject());
		    }*/
		}else {
			rs=new Rs();
			rs.setList(new ArrayList<Article>());
		}
	    
		
	    
		return rs;
	}

	@Override
	//本函数未用
	public Rs statByUser(long gid, int page, int pagesize) {
		String hql="select u from User u,Article a where a.deled is false and a.user.id=u.id and a.status is true order by count(a) desc";
		return HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, 0, page, pagesize);
	}

	@SuppressWarnings("unchecked")
	@Override
	public PortalStatInfo stat(PortalStatInfo psi) {
		DetachedCriteria criteria=DetachedCriteria.forClass(Article.class);
		criteria.setProjection(Projections.rowCount());
		
		List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(criteria);
		
		
//		String hql="select count(*) from Article";
//		List<Long> list = (List<Long>) this.getHibernateTemplate().find(hql);
		psi.setArtsTotal(list.get(0));
		criteria.add(Restrictions.eq("deled", false ) );
		criteria.add(Restrictions.eq("status", true ) );
		
		list = (List<Long>) this.getHibernateTemplate().findByCriteria(criteria);
//		hql="select count(*) from Article a where a.status is true ";
//		list = (List<Long>) this.getHibernateTemplate().find(hql);
		psi.setArtsPassed(list.get(0));
		
		return psi;
	}

	@Override
	public long countByUid(long uid) {
		DetachedCriteria criteria=DetachedCriteria.forClass(Article.class);
		criteria.add(Restrictions.eq("deled", false ) );
		criteria.setProjection(Projections.rowCount());
		criteria.createAlias("user", "u");
		criteria.add(Restrictions.eq("u.id", uid ) );
		
		@SuppressWarnings("unchecked")
		List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(criteria);
		return list.get(0);
//		String hql="select count(*) from Article a where a.user.id="+uid;
		/*@SuppressWarnings("unchecked")
		List<Long> list = (List<Long>) this.getHibernateTemplate().find(hql,uid);*/
//		return HibernateUtil.countHql(this.getHibernateTemplate(), hql);
	}
	
	
	@Override
	public void modifyTopOne(long id,boolean state) {
		HibernateUtil.executeHql(this.getHibernateTemplate(), "update Article a set a.topOne=false where a.topOne=true");
//		this.getHibernateTemplate().bulkUpdate("update Article a set a.topOne=false where a.topOne=true");
		if (state){
//			this.getHibernateTemplate().bulkUpdate("update Article a set a.topOne=true where a.id="+id);
			HibernateUtil.executeHql(this.getHibernateTemplate(), "update Article a set a.topOne=true where a.id="+id);
		}
	}

	@Override
	public List<Long> queryAllPassedID(long startID) {
		DetachedCriteria criteria=DetachedCriteria.forClass(Article.class);
		criteria.add(Restrictions.eq("deled", false ) );
		criteria.add(Restrictions.eq("status", true ) );
		criteria.setProjection(Projections.property("id"));
		
//		String hql="select a.id from Article a where a.status is true ";
		if (startID>0L) {
//			hql += " and a.id>"+startID;
			criteria.add(Restrictions.eq("id", startID ) );
		}
		criteria.addOrder(Order.asc("id") );
		
		/*hql += " order by a.id asc" ;
		@SuppressWarnings("unchecked")
		List<Long> list = (List<Long>) this.getHibernateTemplate().find(hql);*/
		
		@SuppressWarnings("unchecked")
		List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(criteria);
		
		return list;
	}

	@Override
	public Article findNeighbour(long aid, int mod, long gid) {
		Article cur=findByID(aid);
		if (cur==null) {
			return null;
		}

		ArticleGroup g;
		String modStr;
		if (mod == 0) {
			modStr = " a.creationTime < " + cur.getCreationTime() + " order by a.creationTime desc";
		} else {
			modStr = " a.creationTime > " + cur.getCreationTime() + " order by a.creationTime asc";
		}
		
		if (gid > 0) {
			g = this.getHibernateTemplate().get(ArticleGroup.class, gid);
		} else {
			g = null;
		}
		
		String hql;
		String gCmd;
		
		if (g != null) {
			gCmd = " and a.agroup.footLeft >= " + g.getFootLeft() + " and a.agroup.footRight <= " +g.getFootRight();
			hql = "from Article a where a.deled is false and a.status=true " + gCmd + " and " + modStr;
		} else {
			hql = "from Article a where a.deled is false and a.status=true  and "
					+ modStr;
		}
		
		Rs rs=HibernateCallbackUtil.getRs(this.getHibernateTemplate(), hql, 0, 1, 1);
		if (rs.getCount()>0 && !rs.getList().isEmpty() && rs.getList().size()>0) {
			return (Article) rs.getList().get(0);
		}else {
			return null;
		}
	}

}
