package com.atlassian.stash.internal.auth.trusted;

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;
import java.util.List;

@Repository("trustedApplicationDao")
public class HibernateTrustedApplicationDao extends AbstractHibernateDao<Integer, InternalTrustedApplication> implements TrustedApplicationDao {

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

    @Override
    public void deleteAll() {
        session().createQuery("delete from InternalTrustedApplication").executeUpdate();
    }

    @Override
    @SuppressWarnings("unchecked")
    public Iterable<InternalTrustedApplication> findAll() {
        List<InternalTrustedApplication> apps = session().createQuery("FROM InternalTrustedApplication").list();
        for (InternalTrustedApplication application : apps) {
            InternalTrustedApplication.initialize(application);
        }
        return apps;
    }

    @Override
    public InternalTrustedApplication getByApplicationId(String applicationId) {
        Query query = session().createQuery("FROM InternalTrustedApplication WHERE applicationId = :applicationId")
                .setParameter("applicationId", applicationId);

        return InternalTrustedApplication.initialize((InternalTrustedApplication) query.uniqueResult());
    }

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

    @Override
    public InternalTrustedApplication update(InternalTrustedApplication entity) {
        InternalTrustedApplication current = getByApplicationId(entity.getApplicationId());
        if (current != null) {
            // create a copy of the current version to ensure that the entity and its restrictions have their ids set.
            // if we were to update without having the ids on the restrictions, we'd end up creating duplicate
            // records in the database.
            entity = current.copy()
                    .id(entity.getId())
                    .certificateTimeout(entity.getCertificateTimeout())
                    .ipPatterns(entity.getIPPatterns())
                    .publicKey(entity.getPublicKey())
                    .urlPatterns(entity.getUrlPatterns())
                    .build();
        }

        return super.update(entity);
    }
}
