package com.palmnest.dao;

import com.palmnest.application.bean.Page;
import com.palmnest.application.bean.Pagenation;
import com.palmnest.model.Element;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.springframework.jdbc.core.JdbcTemplate;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * Generic DAO (Data Access Object) with common methods to CRUD POJOs.
 *
 * <p>
 * Extend this interface if you want typesafe (no casting necessary) DAO's for
 * your domain objects.
 *
 * @param <T>  a type variable
 * @param <PK> the primary key for that type
 * @author <a href="mailto:chasel.java@gmail.com">Chasel Li</a>
 */
public interface GenericDao<T, PK extends Serializable> {

	/**
	 * Generic method used to get all objects of a particular type. This is the
	 * same as lookup up all rows in a table.
	 *
	 * @return List of populated objects
	 */
	List<T> getAll();

	/**
	 * Gets all records without duplicates.
	 * <p>
	 * Note that if you use this method, it is imperative that your model
	 * classes correctly implement the hashcode/equals methods
	 * </p>
	 *
	 * @return List of populated objects
	 */
	List<T> getAllDistinct();

	/**
	 * Gets all records that match a search term. "*" will get them all.
	 *
	 * @param searchTerm the term to search for
	 * @return the matching records
	 * @throws SearchException
	 */
	List<T> search(String searchTerm) throws SearchException;

	/**
	 * Generic method to get an object based on class and identifier. An
	 * ObjectRetrievalFailureException Runtime Exception is thrown if nothing is
	 * found.
	 *
	 * @param id the identifier (primary key) of the object to get
	 * @return a populated object
	 * @see org.springframework.orm.ObjectRetrievalFailureException
	 */
	T get(PK id);

	/**
	 * Checks for existence of an object of type T using the id arg.
	 *
	 * @param id the id of the entity
	 * @return - true if it exists, false if it doesn't
	 */
	boolean exists(PK id);

	/**
	 * Generic method to save an object - handles both update and insert.
	 *
	 * @param object the object to save
	 * @return the persisted object
	 */
	T save(T object);

	T saveObj(T object);

	void updateObj(T object);

	/**
	 * Generic method to delete an object
	 *
	 * @param object the object to remove
	 */
	void remove(T object);

	/**
	 * Generic method to delete an object
	 *
	 * @param id the identifier (primary key) of the object to remove
	 */
	void remove(PK id);

	/**
	 * Find a list of records by using a named query
	 *
	 * @param queryName   query name of the named query
	 * @param queryParams a map of the query names and the values
	 * @return a list of the records found
	 */
	List<T> findByNamedQuery(String queryName, Map<String, Object> queryParams);

	/**
	 * Generic method to regenerate full text index of the persistent class T
	 */
	void reindex();

	/**
	 * Generic method to regenerate full text index of all indexed classes
	 *
	 * @param async true to perform the reindexing asynchronously
	 */
	void reindexAll(boolean async);

	/**
	 * 分页
	 *
	 * @param <T>
	 * @param pageNo
	 * @param pageSize
	 * @param aliasMap
	 * @param filterList
	 * @param orderList
	 * @param clazz
	 * @return
	 */
	public <T> Pagenation<T> queryPage(int pageNo, int pageSize,
									   Map<String, String> aliasMap, List<Criterion> filterList,
									   List<Order> orderList, Class<?> clazz);

	public <T> Pagenation<T> queryPage(Map<String, String> aliasMap, List<Criterion> filterList,
									   List<Order> orderList, Class<?> clazz);

	public <T> Pagenation<T> queryPageByReceive(int pageNo, int pageSize,
												Map<String, String> aliasMap, List<Criterion> filterList,
												List<Order> orderList, Class<?> clazz);

	/**
	 * 按CODE查询字典
	 *
	 * @param code
	 * @return
	 */
	public List<Element> getElementsByGroupName(String code);

	/**
	 * 获取某表的最大操作版本号
	 *
	 * @param tableName
	 * @return
	 */
	public long getTabMaxOptVersion(String tableName);

	/**
	 * @return
	 */
	public JdbcTemplate getJdbcTemplate();

	/**
	 * 分页查询函数，使用sql，并且同时使用JdbcTemplate来查询.<br/>
	 * Jdbctemplate是从getJdbcTemplate()中获取
	 * 如果传过来的页码大于等于Integer.MAX_VALUE，则表示查询全部，否则按照分页查询 如果页码=0，则表示只查询总数，不查询明细
	 * 现在只支持ORACLE数据库，如果其他数据库需要扩展
	 *
	 * @param pageNo 页号,从1开始.
	 * @author 0008841
	 */
	public Page pagedQueryByJdbcTemplate(String sql, int pageNo, int pageSize);

}