package com.yonge.toolset.mongodb.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import com.yonge.toolset.mongodb.PageInfo;

public abstract class BaseDaoWithMongo<PK, T extends Serializable> {

	@Resource
	private MongoTemplate mongoTemplate;

	public abstract Class<T> getClassEntity();

	/**
	 * 通过主键id获取对象
	 * @param id
	 * @return T
	 */
	public T get(PK id) {
		Query query = new Query(Criteria.where("_id").is(id));
		return mongoTemplate.findOne(query, getClassEntity());
	}

	/**
	 * 更新实体对象
	 * @param bean
	 */
	public long update(PK id, T bean) {
		Query query = new Query(Criteria.where("_id").is(id));

		Update update = new Update();

		Field[] fieldList = bean.getClass().getDeclaredFields();
		for (Field field : fieldList) {
			field.setAccessible(true);
			try {
				update.set(field.getName(), field.get(bean));
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}

		return mongoTemplate.updateFirst(query, update, getClassEntity()).getModifiedCount();
	}

	/**
	 * 通过主键id删除对象
	 * @param id
	 */
	public long delete(final PK id) {
		Query query = new Query(Criteria.where("_id").is(id));
		return mongoTemplate.remove(query, getClassEntity()).getDeletedCount();
	}

	/**
	 * 写入实体对象
	 * @param bean
	 */
	public void insert(T bean) {
		mongoTemplate.insert(bean);
	}

	/**
	 * 写入实体对象
	 * @param batchBean
	 * @param clazz
	 */
	public void batchInsert(List<T> batchBean, Class clazz) {
		mongoTemplate.insert(batchBean,clazz);
	}

	/**
	 * 通过参数查找所有结果集
	 * @param params
	 * @return
	 */
	public List<T> findAll(Map<String, Object> params) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		if (params != null) {
			for (Entry<String, Object> entry : params.entrySet()) {
				criteria.and(entry.getKey()).is(entry.getValue());
			}
		}
		query.addCriteria(criteria);
		return mongoTemplate.find(query, getClassEntity());
	}

	/**
	 * 通过参数查找结果集，适合分页场景
	 * @param params
	 * @return
	 */
	public PageInfo<T> queryPage(int page, int size, Map<String, Object> params) {
		PageInfo<T> pageInfo = new PageInfo<T>(page, size);

		List<T> dataList = null;
		long total = this.queryCount(params);
		if (total > 0) {
			pageInfo.setTotal(total);

			Query query = new Query();
			Criteria criteria = new Criteria();
			if (params != null) {
				for (Entry<String, Object> entry : params.entrySet()) {
					criteria.and(entry.getKey()).is(entry.getValue());
				}
			}
			query.addCriteria(criteria);
			query.skip(pageInfo.getOffset()).limit(pageInfo.getLimit());
			dataList = mongoTemplate.find(query, getClassEntity());
		}
		if (total == 0) {
			dataList = new ArrayList<T>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	/**
	 * 通过参数查找结果集数目
	 * @param params
	 * @return
	 */
	public long queryCount(Map<String, Object> params) {
		Query query = new Query();

		Criteria criteria = new Criteria();
		if (params != null) {
			for (Entry<String, Object> entry : params.entrySet()) {
				criteria.and(entry.getKey()).is(entry.getValue());
			}
		}
		query.addCriteria(criteria);
		return mongoTemplate.count(query, getClassEntity());
	}
}
