package com.atlassian.stash.internal.plugin;

import com.atlassian.stash.internal.AbstractHibernateDao;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Collections;

/**
 * Default implementation for persisting the plugins's states.
 */
@Repository("pluginStateDao")
public class HibernatePluginStateDao extends AbstractHibernateDao<String, PluginState> implements PluginStateDao {

    @Autowired
    public HibernatePluginStateDao(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

    @Override
    protected Iterable<Order> getImplicitOrder() {
        return Collections.singleton(Order.asc("name"));
    }

    @Override
    public PluginState findByName(String name) {
        Query query = session().createQuery("from PluginState where name = :name");
        query.setParameter("name", name);
        PluginState pluginState = (PluginState) query.uniqueResult();
        if (pluginState != null) {
            session().evict(pluginState);
        }
        return pluginState;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Iterable<PluginState> findAll() {
        Iterable<PluginState> result = session().createQuery("FROM PluginState").list();
        // detach all plugin state entities straightaway. There's no point in keeping them in the session
        // because any change to any of the pluginstate will wipe out the whole table and rebuild
        // all state. This is pretty horrific, but that's the way the plugin system works.
        for (PluginState state : result) {
            session().evict(state);
        }
        return result;
    }

    @Override
    public void clear() {
        session().createQuery("DELETE FROM PluginState").executeUpdate();
    }
}
