package com.atlassian.bitbucket.mesh.liquibase;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import liquibase.Scope;
import liquibase.exception.LiquibaseException;
import liquibase.integration.spring.SpringLiquibase;
import liquibase.ui.ConsoleUIService;

import javax.annotation.Nonnull;
import javax.sql.DataSource;

import static org.apache.commons.io.output.NullPrintStream.NULL_PRINT_STREAM;

public class ExtendedSpringLiquibase extends SpringLiquibase {

    public ExtendedSpringLiquibase(@Nonnull String changelog, @Nonnull DataSource dataSource) {
        setChangeLog(changelog);
        setDataSource(dataSource);
    }

    @Override
    public void afterPropertiesSet() throws LiquibaseException {
        //This redirects some silly output Liquibase tries to add. Liquibase uses a ConsoleUIService
        //by default, which writes directly to stdout and stderr. There's no UIService output we want,
        //though, so this replaces that default service with one that discards all output.
        //Note: Everywhere Liquibase writes to the UIService it also logs, so using LoggingUIService
        //would end up doubling up all the logging.
        ConsoleUIService uiService = new ConsoleUIService();
        uiService.setErrorStream(NULL_PRINT_STREAM);
        uiService.setOutputStream(NULL_PRINT_STREAM);

        try {
            String scope = Scope.enter(ImmutableMap.of(Scope.Attr.ui.name(), uiService));
            try {
                super.afterPropertiesSet();
            } finally {
                Scope.exit(scope);
            }
        } catch (Exception e) {
            Throwables.propagateIfPossible(e, LiquibaseException.class);

            throw new LiquibaseException("Could not update scope", e);
        }
    }
}
