package io.dropwizard.migrations;

import com.codahale.metrics.MetricRegistry;
import io.dropwizard.Configuration;
import io.dropwizard.cli.ConfiguredCommand;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.db.DatabaseConfiguration;
import io.dropwizard.db.ManagedDataSource;
import io.dropwizard.setup.Bootstrap;
import liquibase.Liquibase;
import liquibase.exception.LiquibaseException;
import liquibase.exception.ValidationFailedException;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

import java.sql.SQLException;

public abstract class AbstractLiquibaseCommand<T extends Configuration> extends ConfiguredCommand<T> {
    private final DatabaseConfiguration<T> strategy;
    private final Class<T> configurationClass;

    protected AbstractLiquibaseCommand(String name,
                                       String description,
                                       DatabaseConfiguration<T> strategy,
                                       Class<T> configurationClass) {
        super(name, description);
        this.strategy = strategy;
        this.configurationClass = configurationClass;
    }

    @Override
    protected Class<T> getConfigurationClass() {
        return configurationClass;
    }

    @Override
    public void configure(Subparser subparser) {
        super.configure(subparser);

        subparser.addArgument("--migrations")
                 .dest("migrations-file")
                 .help("the file containing the Liquibase migrations for the application");
    }

    @Override
    @SuppressWarnings("UseOfSystemOutOrSystemErr")
    protected void run(Bootstrap<T> bootstrap, Namespace namespace, T configuration) throws Exception {
        final DataSourceFactory dbConfig = strategy.getDataSourceFactory(configuration);
        dbConfig.setMaxSize(1);
        dbConfig.setMinSize(1);
        dbConfig.setInitialSize(1);

        try (CloseableLiquibase liquibase = openLiquibase(dbConfig, namespace)) {
            run(namespace, liquibase);
        } catch (ValidationFailedException e) {
            e.printDescriptiveError(System.err);
            throw e;
        }
    }

    private CloseableLiquibase openLiquibase(DataSourceFactory dataSourceFactory,
                                           Namespace namespace) throws ClassNotFoundException, SQLException, LiquibaseException {
        final ManagedDataSource dataSource = dataSourceFactory.build(new MetricRegistry(), "liquibase");
        final String migrationsFile = (String) namespace.get("migrations-file");
        if (migrationsFile == null) {
            return new CloseableLiquibase(dataSource);
        }
        return new CloseableLiquibase(dataSource, migrationsFile);
    }

    protected abstract void run(Namespace namespace, Liquibase liquibase) throws Exception;
}

@@ -351,16 +351,52 @@
 uibase;%0A
+import liquibase.database.Database;%0A
 import l
@@ -1473,17 +1473,16 @@
         
- 
 .dest(%22m
@@ -1498,17 +1498,16 @@
 -file%22)%0A
- 
         
@@ -1588,16 +1588,345 @@
 ation%22);
+%0A%0A        subparser.addArgument(%22--catalog%22)%0A                .dest(%22catalog%22)%0A                .help(%22Specify the database catalog (use database default if omitted)%22);%0A%0A        subparser.addArgument(%22--schema%22)%0A                .dest(%22schema%22)%0A                .help(%22Specify the database schema (use database default if omitted)%22);
 %0A    %7D%0A%0A
@@ -2297,16 +2297,22 @@
    try (
+final 
 Closeabl
@@ -2591,16 +2591,22 @@
 quibase(
+final 
 DataSour
@@ -2637,51 +2637,14 @@
 ory,
-%0A                                          
+ final
  Nam
@@ -2660,16 +2660,28 @@
 mespace)
+%0A           
  throws 
@@ -2731,32 +2731,76 @@
 baseException %7B%0A
+        final CloseableLiquibase liquibase;%0A
         final Ma
@@ -2884,24 +2884,25 @@
 iquibase%22);%0A
+%0A
         fina
@@ -2930,17 +2930,8 @@
 le =
- (String)
  nam
@@ -2940,16 +2940,22 @@
 pace.get
+String
 (%22migrat
@@ -3009,38 +3009,43 @@
 ) %7B%0A            
-return
+liquibase =
  new CloseableLi
@@ -3070,24 +3070,31 @@
 );%0A        %7D
+ else %7B
 %0A        ret
@@ -3090,22 +3090,31 @@
         
-return
+    liquibase =
  new Clo
@@ -3154,24 +3154,617 @@
 tionsFile);%0A
+        %7D%0A%0A        final Database database = liquibase.getDatabase();%0A        final String catalogName = namespace.getString(%22catalog%22);%0A        final String schemaName = namespace.getString(%22schema%22);%0A%0A        if(database.supportsCatalogs() && catalogName != null) %7B%0A            database.setDefaultCatalogName(catalogName);%0A            database.setOutputDefaultCatalog(true);%0A        %7D%0A        if(database.supportsSchemas() && schemaName != null) %7B%0A            database.setDefaultSchemaName(schemaName);%0A            database.setOutputDefaultSchema(true);%0A        %7D%0A%0A        return liquibase;%0A
     %7D%0A%0A    p

Add `--catalog` and `--schema` to AbstractLiquibaseCommand, fixes #584