package org.bench4q.master.domain.repository;

import java.util.LinkedList;
import java.util.List;

import org.bench4q.master.domain.entity.Script;
import org.bench4q.master.domain.entity.User;
import org.bench4q.master.exception.ExceptionLog;
import org.bench4q.master.exception.ExceptionUtils.EntityUniqueAlReadyExistException;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;

@Component
public class ScriptRepositoty extends AbstractRepositoty {

	public Script attach(Script scriptWithoutId) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			Script script = (Script) session.merge(scriptWithoutId);
			transaction.commit();

			return script;
		} catch (Exception e) {
			transaction.rollback();
			logger.error(ExceptionLog.getStackTrace(e));
			return null;
		} finally {
			releaseSession(session);
		}
	}

	@Override
	protected void guardOtherUniqueConditionForEntity(
			String uniquePropertyName, String value)
			throws EntityUniqueAlReadyExistException {
		if (getScriptByName(value) != null) {
			throw new EntityUniqueAlReadyExistException("Script with the name "
					+ value + " already exists");
		}
	}

	public boolean detach(int id) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			Script script = (Script) session.get(Script.class, id);
			if (script == null) {
				return false;
			}
			session.delete(script);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			logger.error(ExceptionLog.getStackTrace(e));
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public boolean update(Script script) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.update(script);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public Script getEntity(int id) {
		Session session = this.getSessionHelper().openSession();
		Script result = (Script) session.get(Script.class, id);
		releaseSession(session);
		return result;
	}

	public Script getScriptByName(String name) {
		Session session = this.getSessionHelper().openSession();
		try {
			return (Script) session.createCriteria(Script.class)
					.add(Restrictions.eq("name", name)).uniqueResult();
		} catch (Exception e) {
			logger.info(ExceptionLog.getStackTrace(e));
			return null;
		} finally {
			releaseSession(session);
		}
	}

	@SuppressWarnings("unchecked")
	public List<Script> getWith(Criterion criterion, User user) {
		Session session = this.getSessionHelper().openSession();
		try {
			return session.createCriteria(Script.class)
					.add(Restrictions.eq("user", user)).add(criterion).list();
		} catch (Exception e) {
			return new LinkedList<Script>();
		} finally {
			releaseSession(session);
		}
	}

	public List<Script> loadEntities(User user) {
		Session session = this.getSessionHelper().openSession();
		@SuppressWarnings("unchecked")
		List<Script> scripts = session.createCriteria(Script.class)
				.add(Restrictions.eq("user", user))
				.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
		releaseSession(session);
		return scripts;
	}

}
