package no.valg.valgnatt.database.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public abstract class BaseDao<T, I extends Serializable> {
    @Resource
    SessionFactory sessionFactory;
    private Class<T> persistentClass;

    public BaseDao() {
        persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public T save(T entity) {
        sessionFactory.getCurrentSession().save(entity);
        return entity;
    }

    public T update(T entity) {
        sessionFactory.getCurrentSession().update(entity);
        return entity;
    }

    public T saveOrUpdate(T entity) {
        sessionFactory.getCurrentSession().saveOrUpdate(entity);
        return entity;
    }

    public T merge(T entity) {
        sessionFactory.getCurrentSession().merge(entity);
        return entity;
    }

    public void refresh(T entity) {
        sessionFactory.getCurrentSession().refresh(entity);
    }

    public void delete(T entity) {
        sessionFactory.getCurrentSession().delete(entity);
    }

    public boolean exists(I id) {
        return sessionFactory.getCurrentSession().get(persistentClass, id) != null;
    }

    public T get(I id) {
        return (T) sessionFactory.getCurrentSession().get(persistentClass, id);
    }
    
    public List<T> list() {
        Session session = sessionFactory.getCurrentSession();
        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<T> cq = cb.createQuery(persistentClass);
        cq.select(cq.from(persistentClass));
        TypedQuery<T> query = session.createQuery(cq);
        return query.getResultList();
    }

}
