package net.waltzstudio.base.framework.dao;

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.seasar.extension.jdbc.AutoSelect;
import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.SqlFileSelect;
import org.seasar.extension.jdbc.SqlFileUpdate;
import org.seasar.framework.beans.util.BeanMap;
import org.seasar.framework.util.StringUtil;
import org.seasar.framework.util.tiger.GenericUtil;
import net.waltzstudio.base.framework.entity.Entity;
import net.waltzstudio.base.framework.entity.EntityName;

public abstract class Dao<T extends Entity> implements EntityName {

	@Resource
	protected JdbcManager jdbcManager;

	protected Class<T> entityClass;

	protected String sqlFilePathPrefix;

	@SuppressWarnings("unchecked")
	public Dao() {
		Map<TypeVariable<?>, Type> map = GenericUtil.getTypeVariableMap(getClass());
		for (Class<?> c = getClass(); c != Object.class; c = c.getSuperclass()) {
			if (c.getSuperclass() == Dao.class) {
				Type type = c.getGenericSuperclass();
				Type[] arrays = GenericUtil.getGenericParameter(type);
				setEntityClass((Class<T>) GenericUtil.getActualClass(arrays[0], map));
				break;
			}
		}
	}

	public Dao(Class<T> entityClass) {
		setEntityClass(entityClass);
	}

	protected void setEntityClass(Class<T> entityClass) {
		this.entityClass = entityClass;
		sqlFilePathPrefix = "META-INF/sql/" + StringUtil.replace(entityClass.getName(), ".", "/") + "/";
	}

	protected AutoSelect<T> select() {
		return jdbcManager.from(entityClass);
	}

	public List<T> findAll() {
		return select().getResultList();
	}

	public List<T> findByCondition(BeanMap conditions) {
		return select().where(conditions).getResultList();
	}

	public long getCount() {
		return select().getCount();
	}

	public int insert(T entity) {
		return jdbcManager.insert(entity).execute();
	}

	public int update(T entity) {
		return jdbcManager.update(entity).execute();
	}

	public int delete(T entity) {
		return jdbcManager.delete(entity).execute();
	}

	protected <T2> SqlFileSelect<T2> selectBySqlFile(Class<T2> baseClass, String path) {
		return jdbcManager.selectBySqlFile(baseClass, sqlFilePathPrefix + path);
	}

	protected <T2> SqlFileSelect<T2> selectBySqlFile(Class<T2> baseClass, String path, Object parameter) {
		return jdbcManager.selectBySqlFile(baseClass, sqlFilePathPrefix + path, parameter);
	}

	protected SqlFileUpdate updateBySqlFile(String path) {
		return jdbcManager.updateBySqlFile(sqlFilePathPrefix + path);
	}

	protected SqlFileUpdate updateBySqlFile(String path, Object parameter) {
		return jdbcManager.updateBySqlFile(sqlFilePathPrefix + path, parameter);
	}

}
