package com.ntsky.bbs.dao.hibernate;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Collection;
import java.util.TreeMap;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.ntsky.bbs.Symbols;
import com.ntsky.bbs.domain.Forum;
import com.ntsky.bbs.domain.Topic;
import com.ntsky.bbs.dao.TopicDAO;
import com.ntsky.bbs.util.memory.ForumSingleton;
import com.ntsky.bbs.util.page.Pagination;
import com.ntsky.bbs.util.page.QueryResult;
import com.ntsky.bbs.exception.DAOException;
import com.ntsky.bbs.exception.ObjectExistException;
import com.ntsky.bbs.exception.ServiceException;

/**
 * 帮助信息Hibernate数据处理实现 
 * 
 * @author ntsky
 * @link www.ntsky.com
 * 
 * @version $Revision: 1.27 $ $Date: 2007/04/08 17:46:20 $
 */
public class TopicDAOHibernateImpl extends BaseDAOHibernateImpl implements TopicDAO {
	
	/**
	 * 取得制定论坛的贴子
	 * 
	 * @param forumId 论坛编号
	 * @param categoryId 类别编号 (-1,表示不设定CategoryId)
	 * @param status 贴子状态 (1 精华, 0 全部)
	 * @param pagination 分页参数
	 * @return QueryResult 帖子集合
	 * @throws DataAccessException
	 */
	public QueryResult findTopics(int forumId, int categoryId, Map orderMap, int status, Pagination pagination) throws DAOException {
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			detachedCriteria.add(Restrictions.eq("forumId",forumId));
			if(status!=0){
				detachedCriteria.add(Restrictions.eq("status",status));
			}
			if(categoryId != -1){
				detachedCriteria.add(Restrictions.eq("categoryId",categoryId));
			}
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			orderMap.put("lastPostTime","desc");
			return super.findItemsByCriteria(detachedCriteria,orderMap,pagination);
		}
		catch(DAOException de){
			throw new DAOException("列表主题发生错误");
		}
	}
	
	/**
	 * 取得用户发表的帖子 
	 * @param username 用户名
	 * @param forumId 论坛序号
	 * @param keyword 标题关键字
	 * @param orderMap 排序map
	 * @param pagination 分页对象
	 * @return 查询结果
	 * @throws DAOException
	 */
	public QueryResult findUserTopics(String username, int forumId, String keyword, Map orderMap, Pagination pagination) throws DAOException {
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			detachedCriteria.add(Restrictions.eq("username",username));
			if( forumId!=0 ){
				detachedCriteria.add(Restrictions.eq("forumId",forumId));
			}
			detachedCriteria.add(Restrictions.like("title","%"+keyword+"%"));
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			orderMap.put("lastPostTime","desc");
			return super.findItemsByCriteria(detachedCriteria,orderMap,pagination);
		}
		catch(DAOException de){
			throw new DAOException("列表主题发生错误");
		}
	}
	
	/**
	 * 检索帖子
	 * @param forumId 论坛编号
	 * @param type 检索类型
	 * @param keyword 检索关键字
	 * @param timePoint 时间点 当timePoint为""时，不进行时间设定
	 * @param way 时间方向
	 * @param orderMap 排序信息
	 * @param pagination 
	 * @return
	 * @throws DAOException
	 */
	public QueryResult searchTopics (int forumId, String type, String keyword, String timePoint, String way, Map orderMap, Pagination pagination) throws DAOException {
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			if(forumId != 0){
				detachedCriteria.add(Restrictions.eq("forumId",new Integer(forumId)));
			}
			detachedCriteria.add(Restrictions.like(type,"%"+keyword+"%"));
			if(!("".equals(timePoint))){
				if("after".equals(way)){
					detachedCriteria.add(Restrictions.gt("dateCreated",timePoint));
				}
				else{
					detachedCriteria.add(Restrictions.lt("dateCreated",timePoint));
				}
			}
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			return super.findItemsByCriteria(detachedCriteria,orderMap,pagination);
		}
		catch(DAOException de){
			throw new DAOException("列表主题发生错误");
		}
	}
	
	/**
	 * 取得制定论坛的贴子
	 * 
	 * @param forumId 论坛编号
	 * @param orderMap 排序数组
	 * @param pagination 分页对象
	 * @return QueryResult 论坛贴子列表
	 * @throws ServiceException
	 */
	public QueryResult findTopics (final int forumId, Map orderMap, final Pagination pagination) throws DAOException {
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			detachedCriteria.add(Restrictions.eq("forumId",forumId));
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			return super.findItemsByCriteria(detachedCriteria,orderMap,pagination);
		}
		catch(DAOException de){
			throw new DAOException("列表贴子发生错误");
		}

	}	
	
	/**
	 * 根据主题编号查找主题信息
	 * 
	 * @param topicId 主题编号
	 * @return Topic 主题对象
	 */	
	public Topic findTopic(long topicId) throws DAOException {
		try{
			return (Topic)super.get(Topic.class,new Long(topicId));
		}
		catch(ObjectExistException objectExistException){
			logger.error("取得 topicId(" +topicId+ ") 对应的帖子信息发生错误，该信息可能被删除.");
			throw new DAOException("取得 topicId(" +topicId+ ") 对应的帮助信息发生错误，该信息可能被删除.");
		}
		catch(Exception exception){
			logger.error("取得 topicId(" +topicId+ ") 对应的帮助信息发生错误 : " + exception.getMessage());
			throw new DAOException("取得 topicId(" +topicId+ ") 对应的帮助信息发生错误");
		}
	}
	
	/**
	 * 根据主题编号查找主题信息
	 * @param topicId 主题编号
	 * @return Topic 主题对象
	 */	
	public Topic viewTopic(long topicId) throws DAOException {
		try{
			return (Topic)super.find("from Topic as t left outer join fetch t.posts where t.id="+topicId).get(0);
		}
		catch(ObjectExistException objectExistException){
			throw new DAOException("取得 topicId(" +topicId+ ") 对应的帮助信息发生错误，该信息可能被删除.");
		}
		catch(Exception exception){
			throw new DAOException("取得 topicId(" +topicId+ ") 对应的帮助信息发生错误");
		}
	}
	
	/**
	 * 根据主题论坛版块编号删除主题
	 * 
	 * @param topicId 主题编号
	 * @return Topic 主题对象
	 */	
	public void deleteTopicByForum(int forumId) throws DAOException {
		try{
			super.executeHsql("delete from Topic where forumId='"+forumId+"'");
		}
		catch(DAOException daoException){
			logger.error("根据主题论坛版块编号topicId(" +forumId+ ")删除对应的帖子信息发生错误.");
			throw new DAOException("根据主题论坛版块编号forumId(" +forumId+ ")删除对应的帖子信息发生错误.");
		}
	}
	
	/**
	 * 更新贴子浏览次数
	 *  
	 * @param topicId 贴子编号
	 * @throws DAOException
	 */
	public void updateTopicViews(int topicId) throws DAOException{
		try{
			super.executeHsql("update Topic set views=views+1 where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("增加贴子topicId(" +topicId+ ")被浏览次数失败.");
		}
	}	
	
	/**
	 * 更新主题是否被删除状态
	 *
	 * @param topicId 主题编号
	 * @param isDelete 是否被删除
	 * isDelete 1 将主题丢弃到垃圾箱，0 主题状态正常
	 * @throws DAOException
	 */
	public void updateTopicIsDelete(int topicId,int isDelete) throws DAOException{
		try{
			super.executeHsql("update Topic set isDelete='"+isDelete+"' where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("更新主题是否被删除状态发生错误.");
		}
	}

	/**
	 * 更新主题是否被置顶
	 *
	 * @param topicId 主题编号
	 * @param isTop 是否被置顶
	 * isTop 1 置顶，0 主题状态正常
	 * @throws DAOException
	 */
	public void updateTopicIsTop(int topicId,int isTop) throws DAOException{
		try{
			super.executeHsql("update Topic set isTop='"+isTop+"' where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("更新主题是否被置顶发生错误.");
		}
	}
	
	/**
	 * 更改主题所属论坛
	 * 
	 * @param oldForumId 旧的论坛编号
	 * @param newForumId 新的论坛编号
	 * @throws DAOException
	 */
	public void updateTopicForum( int oldForumId, int newForumId ) throws DAOException {
		try{
			super.executeHsql("update Topic set forumId='"+newForumId+"' where forumId='"+oldForumId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("更改主题所属论坛发生错误.");
		}		
	}
	
	/**
	 * 更新主题状态
	 *
	 * @param topicId 主题编号
	 * @param status 是否被置顶
	 * status 1 精华贴，2 被锁定的贴子
	 * @throws DAOException
	 */
	public void updateTopicStatus(int topicId,int status) throws DAOException{
		try{
			super.executeHsql("update Topic set status='"+status+"' where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("更新主题状态发生错误.");
		}
	}
	
	/**
	 * 物理删除主题(不可恢复)
	 * @param topicId
	 * @throws DAOException
	 */
	public void deleteTopic(int topicId) throws DAOException{
		try{
			super.executeHsql("delete from Topic where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("物理删除主题(删除后不可恢复)发生错误.");
		}
	}
	
	/**
	 * 将主题丢到垃圾箱
	 * @param topicId 主题编号
	 * @throws DAOException
	 */
	public void trashTopic(int topicId) throws DAOException {
		try{
			super.executeHsql("update Topic set isDelete=1 where id='"+topicId+"'");
		}
		catch(DAOException daoException){
			throw new DAOException("将主题删除,丢到垃圾箱....");
		}
	}
	
	/**
	 * 取得主题总数
	 * @return
	 * @throws DAOException
	 */
	public int countTopic() throws DAOException{
		try{
			return (Integer)super.findByAggregate("select count(t.id) from Topic as t where t.isDelete=0");
		}
 		catch(DAOException daoException){
			throw new DAOException("统计贴子总数失败.");
		}
	}
	
	/**
	 * 根据ForumId统计主题总数
	 * @param forums
	 * @return
	 * @throws DAOException
	 */
	public int countTopic(List forums) throws DAOException{
		Forum forum = null;
		String forumEnum = "";
		try{
			for (int i = 0; i < forums.size(); i++) {
				forum = (Forum)forums.get(i);
				if(forums.size()-1==i){
					forumEnum = forumEnum + "t.forumId='"+forum.getId()+"'";
				}
				else{
					forumEnum = forumEnum + "t.forumId='"+forum.getId()+"' or ";
				}
			}
			return (Integer)super.findByAggregate("select count(t.id) from Topic as t where ("+forumEnum+") and t.isDelete=0");
		}
 		catch(DAOException daoException){
			throw new DAOException("统计贴子总数失败.");
		}		
	}	
	
	/**
	 * 根据论坛编号查找制定数目的主题
	 * @param forumId 论坛编号
	 * @param dataNum 结果数
	 * @return List 主题列表
	 * @throws DAOException
	 */
	public List findTopic(int forumId,int dataNum) throws DAOException{
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			detachedCriteria.add(Restrictions.eq("forumId",forumId));
			detachedCriteria.addOrder(Order.desc("lastPostTime"));
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			return super.find(detachedCriteria,dataNum);
		}
		catch(DAOException daoException){
			throw new DAOException("根据论坛编号查找制定数目的主题失败");
		}
	}
	
	/**
	 * 移动主题
	 *
	 * @param ids 主题列表
	 * @param forumId 论坛编号
	 * @throws DAOException
	 */
	public void moveTopic(int topicId,int forumId) throws ServiceException{
		try{
			super.executeHsql("update Topic set forumId='"+forumId+"' where id="+topicId);
		}
		catch(DAOException daoException){
			throw new DAOException("根据论坛编号查找制定数目的主题失败");
		}
	}
	
	/**
	 * 取得最新发表的帖子
	 * @param forumId 论坛编号 forumId 0 全部论坛查找
	 * @param num 信息数
	 * @return 主题数
	 * @throws DAOException
	 */
	public List findNewlyTopics(int forumId,int num) throws DAOException{
		try{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class); 
			if(forumId!=0){
				detachedCriteria.add(Restrictions.eq("forumId",forumId));
			}
			detachedCriteria.addOrder(Order.desc("dateCreated"));
			detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete",new Integer(1))));
			return super.find(detachedCriteria,num);
		}
		catch(DAOException daoException){
			throw new DAOException("列表最新发表的帖子失败");
		}		
	}

}