package com.atlassian.stash.internal.backup.liquibase;

import liquibase.database.Database;
import liquibase.database.typeconversion.TypeConverter;
import liquibase.snapshot.DatabaseSnapshot;
import org.springframework.dao.CleanupFailureDataAccessException;

import javax.annotation.Nonnull;

/**
 * Encapsulates all the state maintained by {@link DefaultLiquibaseDao} between invocations of
 * {@link DefaultLiquibaseDao#close}.
 * TODO There'd be some argument for making {@link DefaultLiquibaseDao} a non-singleton with non-threadlocal state, and
 * constructing one per thread using a factory, but we'll live with this for now.
 */
public interface LiquibaseSession {

    /**
     * @return The {@link Database} associated with this session. Each session is bound to a single database so
     * implementations should return the same object on subsequent invocations.
     */
    Database getDatabase();

    /**
     * @return The {@link DatabaseSnapshot} associated with this session. This should be used only for resolving
     * high-level, unchanging meta-data about the database, therefore for performance reasons implementations may cache
     * this value and return the same object on subsequent invocations. This means that operations like schema changes
     * will not always be reflected in the returned {@link DatabaseSnapshot shapshot}.
     */
    DatabaseSnapshot getSnapshot();

    /**
     * Increment the number of changes associated with the current transaction. Should be called every time an
     * additional change is made.
     */
    void incrementChangeCount();

    /**
     * @return the number of changes associated with the current transaction.
     */
    long getChangeCount();

    @Nonnull
    TypeConverter getTypeConverter();

    /**
     * Reset the number of changes associated with the current transaction. Should be called every time a transaction
     * is {@link Database#commit() committed} or {@link Database#rollback()
     * rolled-back}.
     */
    void resetChangeCount();

    /**
     * Close the session and release any resources.
     *
     * @throws CleanupFailureDataAccessException if there was a problem closing the underlying database connection.
     */
    void close();

}
