package org.bench4q.master.domain.repository;

import java.util.List;
import java.util.Set;

import org.bench4q.master.domain.entity.plugin.BehaviorInfo;
import org.bench4q.master.domain.entity.plugin.PluginInfo;
import org.bench4q.master.domain.entity.plugin.PluginUI;
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.Restrictions;
import org.springframework.stereotype.Component;

@Component
public class PluginRepository extends AbstractRepositoty {
	public boolean attatch(PluginUI pluginUI) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			PluginInfo pluginInfo = null;
			pluginInfo = (PluginInfo) session
					.createCriteria(PluginInfo.class)
					.add(Restrictions.eq("name", pluginUI.getPluginInfo()
							.getName())).uniqueResult();
			if (pluginInfo != null) {
				logger.info("the plugin already exists");
				return false;
			}
			session.merge(pluginUI);
			transaction.commit();
			return true;
		} catch (Exception e) {
			transaction.rollback();
			logger.error(ExceptionLog.getStackTrace(e));
			return false;
		} finally {
			releaseSession(session);
		}
	}

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

	public boolean detach(String pluginName) {
		Session session = this.getSessionHelper().openSession();
		Transaction transaction = session.beginTransaction();
		try {
			PluginUI pluginUI = getPluginUI(pluginName);
			if (pluginUI == null) {
				logger.info("plugin not exist");
				return false;
			}
			session.delete(pluginUI);
			transaction.commit();
			return true;
		} catch (Exception e) {
			logger.error(ExceptionLog.getStackTrace(e));
			transaction.rollback();
			return false;
		} finally {
			releaseSession(session);
		}
	}

	public List<PluginUI> loadPlugins() {
		Session session = this.getSessionHelper().openSession();
		try {
			@SuppressWarnings("unchecked")
			List<PluginUI> ret = session.createCriteria(PluginUI.class)
					.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
			return ret;
		} catch (Exception e) {
			logger.error(ExceptionLog.getStackTrace(e));
			return null;
		} finally {
			releaseSession(session);
		}
	}

	public Set<BehaviorInfo> loadBehaviorInfos(String pluginName) {
		Session session = this.getSessionHelper().openSession();
		try {
			PluginUI pluginUI = dogetPluginUI(pluginName, session);
			Set<BehaviorInfo> behaviorInfos = pluginUI.getBehaviorInfos();
			logger.info(behaviorInfos.size());
			return behaviorInfos;
		} catch (Exception e) {
			logger.info(ExceptionLog.getStackTrace(e));
			return null;
		} finally {
			releaseSession(session);
		}
	}

	public boolean isExist(PluginUI plugin) {
		Session session = this.getSessionHelper().openSession();
		PluginInfo pluginAlreadyExist = (PluginInfo) session
				.createCriteria(PluginInfo.class)
				.add(Restrictions.eq("name", plugin.getPluginInfo().getName()))
				.uniqueResult();
		releaseSession(session);
		return pluginAlreadyExist != null;
	}

	public boolean isExist(String pluginName) {
		if (getPluginUI(pluginName) == null)
			return false;
		else {
			return true;
		}
	}

	public PluginUI getPluginUI(String pluginName) {
		if (pluginName == null) {
			logger.info("plugin name is null");
			return null;
		}
		PluginUI pluginUI = null;
		Session session = this.getSessionHelper().openSession();
		pluginUI = dogetPluginUI(pluginName, session);
		releaseSession(session);
		if (pluginUI == null)
			logger.info(pluginName + " plugin is null from repository");
		return pluginUI;
	}

	public PluginUI dogetPluginUI(String pluginName, Session session) {
		PluginInfo pluginInfo = deGetPluginInfo(pluginName, session);
		if (pluginInfo == null)
			return null;
		return (PluginUI) session.createCriteria(PluginUI.class)
				.add(Restrictions.eq("pluginInfo", pluginInfo)).uniqueResult();
	}

	private PluginInfo deGetPluginInfo(String pluginName, Session session) {
		return (PluginInfo) session.createCriteria(PluginInfo.class)
				.add(Restrictions.eq("name", pluginName)).uniqueResult();
	}

	public boolean clearPlugins() {

		List<PluginUI> pluginUIs = this.loadPlugins();
		for (PluginUI pluginUI : pluginUIs) {
			if (!this.detach(pluginUI.getPluginInfo().getName()))
				return false;
		}
		return true;
	}

}
