package com.atlassian.stash.internal.ao;

import com.atlassian.activeobjects.spi.TransactionSynchronisationManager;
import com.atlassian.plugin.spring.AvailableToPlugins;
import com.atlassian.stash.internal.spring.TransactionSynchronizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;

@AvailableToPlugins(TransactionSynchronisationManager.class)
@Component("transactionSynchronisationManager")
public class SpringTransactionSynchronisationManager implements TransactionSynchronisationManager {

    private final TransactionSynchronizer synchronizer;

    @Autowired
    public SpringTransactionSynchronisationManager(TransactionSynchronizer synchronizer) {
        this.synchronizer = synchronizer;
    }

    @Override
    public boolean isActiveSynchronisedTransaction() {
        return synchronizer.isAvailable();
    }

    @Override
    public boolean runOnRollBack(Runnable callback) {
        return maybeRegister(callback, TransactionSynchronization.STATUS_ROLLED_BACK);
    }

    @Override
    public boolean runOnSuccessfulCommit(Runnable callback) {
        return maybeRegister(callback, TransactionSynchronization.STATUS_COMMITTED);
    }

    private boolean maybeRegister(Runnable callback, int status) {
        return synchronizer.register(new RunnableTransactionSynchronization(callback, status));
    }

    private static class RunnableTransactionSynchronization extends TransactionSynchronizationAdapter {

        private final Runnable runnable;
        private final int status;

        private RunnableTransactionSynchronization(Runnable runnable, int status) {
            this.runnable = runnable;
            this.status = status;
        }

        @Override
        public void afterCompletion(int status) {
            if (this.status == status) {
                runnable.run();
            }
        }
    }
}
