package com.conveyal.gtfs;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import static com.conveyal.gtfs.util.Util.randomIdString;

public class TestUtils {

    private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
    private static String pgUrl = "jdbc:postgresql://localhost/postgres";

    /**
     * Forcefully drops a database even if other users are connected to it.
     *
     * @param dbName
     */
    public static void dropDB(String dbName) {
        // first, terminate all other user sessions
        executeAndClose("SELECT pg_terminate_backend(pg_stat_activity.pid) " +
            "FROM pg_stat_activity " +
            "WHERE pg_stat_activity.datname = '" + dbName + "' " +
            "AND pid <> pg_backend_pid()");
        // drop the db
        executeAndClose("DROP DATABASE " + dbName);
    }

    /**
     * Boilerplate for opening a connection, executing a statement and closing connection.
     *
     * @param statement
     * @return true if everything worked.
     */
    private static boolean executeAndClose(String statement) {
        Connection connection;
        try {
            connection = DriverManager.getConnection(pgUrl);
        } catch (SQLException e) {
            e.printStackTrace();
            LOG.error("Error creating new database!");
            return false;
        }

        try {
            connection.prepareStatement(statement).execute();
        } catch (SQLException e) {
            e.printStackTrace();
            LOG.error("Error creating new database!");
            return false;
        }

        try {
            connection.close();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            LOG.error("Error closing connection!");
            return false;
        }
    }

    /**
     * Generate a new database for isolating a test.
     *
     * @return The name of the name database, or null if creation unsucessful
     */
    public static String generateNewDB() {
        String newDBName = randomIdString();
        if (executeAndClose("CREATE DATABASE " + newDBName)) {
            return newDBName;
        } else {
            return null;
        }
    }

    /**
     * Helper to return the relative path to a test resource file
     *
     * @param fileName
     * @return
     */
    public static String getResourceFileName(String fileName) {
        return "./src/test/resources/" + fileName;
    }
}

@@ -167,16 +167,66 @@
 ception;
+%0Aimport java.util.concurrent.atomic.AtomicInteger;
 %0A%0Aimport
@@ -384,16 +384,89 @@
 class);%0A
+    private static final AtomicInteger UNIQUE_ID = new AtomicInteger(0);%0A
     priv
@@ -2265,24 +2265,22 @@
 BName = 
-randomId
+unique
 String()
@@ -2680,11 +2680,252 @@
 e;%0A    %7D
+%0A%0A    /**%0A     * Generate a unique string.  Mostly copied from the uniqueId method of https://github.com/javadev/underscore-java%0A     */%0A    public static String uniqueString() %7B%0A        return %22test_db_%22 + UNIQUE_ID.incrementAndGet();%0A    %7D
 %0A%7D%0A

refactor test util to use simpler db name generator