package org.bench4q.master.domain.repository;

import java.util.Collection;
import java.util.List;

import org.bench4q.master.domain.entity.Agent;
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.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;

@Component
public class AgentRepository extends AbstractRepositoty {

	public boolean attach(Agent agentWithoutId) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			Agent agent = (Agent) session
					.createCriteria(Agent.class)
					.add(Restrictions.eq("hostName",
							agentWithoutId.getHostName())).uniqueResult();
			if (agent != null) {
				return false;
			}
			session.merge(agentWithoutId);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			return false;
		} finally {
			releaseSession(session);
		}
	}

	@Override
	protected void guardOtherUniqueConditionForEntity(
			String uniquePropertyName, String value)
			throws EntityUniqueAlReadyExistException {
		Agent agent = this.getAgentBy(value);
		if (agent != null) {
			throw new EntityUniqueAlReadyExistException(
					"Agent with the hostName " + agent.getHostName()
							+ " already Exist");
		}
	}

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

	public boolean detach(String hostName) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			Agent agent = getAgentBy(hostName, session);
			if (agent == null) {
				return false;
			}
			session.delete(agent);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public boolean update(Agent agentForUpdate) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.update(agentForUpdate);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			logger.error(ExceptionLog.getStackTrace(e));
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public boolean Update(Collection<Agent> poolToUpdate) {
		if (poolToUpdate.size() == 0) {
			return true;
		}
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			for (Agent agent : poolToUpdate) {
				session.update(agent);
			}
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			logger.error(ExceptionLog.getStackTrace(e));
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public Agent getAgentBy(String hostName) {
		Session session = this.getSessionHelper().openSession();
		try {
			Agent agent = getAgentBy(hostName, session);
			return agent;
		} catch (Exception e) {
			return null;
		} finally {
			releaseSession(session);
		}
	}

	private Agent getAgentBy(String hostName, Session session) {
		return (Agent) session.createCriteria(Agent.class)
				.add(Restrictions.eq("hostName", hostName)).uniqueResult();
	}

	public Agent getEntity(int id) {
		Session session = this.getSessionHelper().openSession();
		try {
			return (Agent) session.get(Agent.class, id);
		} catch (Exception e) {
			return null;
		} finally {
			releaseSession(session);
		}
	}

	@SuppressWarnings("unchecked")
	public List<Agent> loadEntities() {
		Session session = this.getSessionHelper().openSession();
		try {
			return session.createCriteria(Agent.class)
					.addOrder(Order.desc("remainLoad"))
					.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			releaseSession(session);
		}
	}
}
