package org.jerrymouse.cc.site.database;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jerrymouse.database.DaoSupport;

public abstract class BaseDao<T> implements DaoSupport<T> {
	private static Log log = LogFactory.getLog(BaseDao.class);

	private static EntityManagerFactory pmfInstance;

	private static String pmfName = "normal-pmf";

	protected static EntityManager getEntityManager() {
		return getEntityManagerFactory().createEntityManager();
	}

	protected static EntityManagerFactory getEntityManagerFactory() {
		if (pmfInstance == null) {
			log.debug("pmf:" + pmfName);
			pmfInstance = Persistence.createEntityManagerFactory(pmfName);
		}
		return pmfInstance;
	}

	public boolean delete(Object key, Class<T> type) {
		log.info("delete " + key.toString());
		EntityManager em = getEntityManager();
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			T object = get(em, key, type);
			if (object == null)
				return false;
			em.remove(object);
			transaction.commit();
			log.info("delete success");
		} finally {
			if (transaction.isActive()) {
				transaction.rollback();
			}
			em.close();
		}
		return true;
	}

	protected T get(EntityManager em, Object key, Class<T> type) {
		return em.find(type, key);
	}

	public T get(Object key, Class<T> type) {
		log.info("getting" + type.toString() + ":" + key.toString());
		T object;
		EntityManager em = getEntityManager();
		try {
			object = get(em, key, type);
			log.info("getting success");
		} finally {
			em.close();
		}
		return object;
	}

	@SuppressWarnings("unchecked")
	public List<T> list(Class<T> type) {
		EntityManager em = getEntityManager();
		try {
			Query query = em.createQuery("SELECT e FROM " + type.getName()
					+ " e");
			List<T> list = query.getResultList();
			list.size();
			return list;
		} finally {
			em.close();
		}

	}

	public boolean post(T object) {
		log.info("posting " + object);
		EntityManager em = getEntityManager();
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			em.persist(object);
			transaction.commit();
			log.info("post success");
		} finally {
			if (transaction.isActive()) {
				transaction.rollback();
				return false;
			}
			em.close();
		}
		return true;
	}

	public boolean put(T object) {
		log.info("putting " + object);
		EntityManager em = getEntityManager();
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			em.merge(object);
			transaction.commit();
			log.info("put success");
		} finally {
			if (transaction.isActive()) {
				transaction.rollback();
				return false;
			}
			em.close();
		}
		return true;
	}

}
