package org.umlg.sqlg.structure;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.SQLException;
import java.util.*;

/**
 * Date: 2014/07/12
 * Time: 7:00 AM
 */
public class SqlgDataSource {

    private Logger logger = LoggerFactory.getLogger(SqlgGraph.class.getName());
    public static final SqlgDataSource INSTANCE = new SqlgDataSource();
    private Map<String, ComboPooledDataSource> cpdss = new HashMap<>();

    private SqlgDataSource() {
    }

    public final DataSource get(String jdbcUrl) {
        return this.cpdss.get(jdbcUrl);
    }

    public void setupDataSource(String driver, String connectURI, String username, String password) throws PropertyVetoException {
        if (this.cpdss.get(connectURI) != null) {
            return;
        }
        logger.debug(String.format("Setting up datasource to %s for user %s", connectURI, username));
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setDriverClass(driver);
        cpds.setJdbcUrl(connectURI);
        cpds.setMaxPoolSize(100);
        if (!StringUtils.isEmpty(username)) {
            cpds.setUser(username);
        }
        if (!StringUtils.isEmpty(username)) {
            cpds.setPassword(password);
        }
        this.cpdss.put(connectURI, cpds);
    }

    public void close(String jdbcUrl) {
        ComboPooledDataSource remove = this.cpdss.remove(jdbcUrl);
        try {
            if (remove != null) {
                int numBusyConnections = remove.getNumBusyConnections();
                if (numBusyConnections > 0) {
//                    System.out.println("Open connection on calling close. " + numBusyConnections);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (remove != null)
                remove.close();
        }
    }

    public String getPoolStatsAsJson() {
        try {
            StringBuffer json = new StringBuffer();
            json.append("[");
            int count = 1;
            for (Map.Entry<String, ComboPooledDataSource> entry : this.cpdss.entrySet()) {
                ComboPooledDataSource comboPooledDataSource = entry.getValue();
                json.append("{\"jdbcUrl\":\"").append(entry.getKey()).append("\",");
                json.append("\"numConnections\":\"").append(String.valueOf(comboPooledDataSource.getNumConnections())).append("\",");
                json.append("\"numBusyConnections\":\"").append(String.valueOf(comboPooledDataSource.getNumConnections())).append("\",");
                json.append("\"numIdleConnections\":\"").append(String.valueOf(comboPooledDataSource.getNumConnections())).append("\",");
                json.append("\"numUnclosedOrphanedConnections\":\"").append(String.valueOf(comboPooledDataSource.getNumConnections())).append("\",");
                json.append("\"numMinPoolSize\":\"").append(String.valueOf(comboPooledDataSource.getMinPoolSize())).append("\",");
                json.append("\"numMaxPoolSize\":\"").append(String.valueOf(comboPooledDataSource.getMaxPoolSize())).append("\",");
                json.append("\"numMaxIdleTime\":\"").append(String.valueOf(comboPooledDataSource.getMaxIdleTime())).append("\"");
                json.append("}");
                if (count++ < this.cpdss.size()) {
                    json.append(",");
                }
            }
            json.append("]");
            return json.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    final static Set TO_STRING_IGNORE_PROPS = new HashSet(Arrays.asList(new String[]{
            "connection",
            "lastAcquisitionFailureDefaultUser",
            "lastCheckinFailureDefaultUser",
            "lastCheckoutFailureDefaultUser",
            "lastConnectionTestFailureDefaultUser",
            "lastIdleTestFailureDefaultUser",
            "logWriter",
            "loginTimeout",
            "numBusyConnections",
            "numBusyConnectionsAllUsers",
            "numBusyConnectionsDefaultUser",
            "numConnections",
            "numConnectionsAllUsers",
            "numConnectionsDefaultUser",
            "numFailedCheckinsDefaultUser",
            "numFailedCheckoutsDefaultUser",
            "numFailedIdleTestsDefaultUser",
            "numIdleConnections",
            "numIdleConnectionsAllUsers",
            "numThreadsAwaitingCheckoutDefaultUser",
            "numIdleConnectionsDefaultUser",
            "numUnclosedOrphanedConnections",
            "numUnclosedOrphanedConnectionsAllUsers",
            "numUnclosedOrphanedConnectionsDefaultUser",
            "numUserPools",
            "effectivePropertyCycleDefaultUser",
            "parentLogger",
            "startTimeMillisDefaultUser",
            "statementCacheNumCheckedOutDefaultUser",
            "statementCacheNumCheckedOutStatementsAllUsers",
            "statementCacheNumConnectionsWithCachedStatementsAllUsers",
            "statementCacheNumConnectionsWithCachedStatementsDefaultUser",
            "statementCacheNumStatementsAllUsers",
            "statementCacheNumStatementsDefaultUser",
            "statementDestroyerNumConnectionsInUseAllUsers",
            "statementDestroyerNumConnectionsWithDeferredDestroyStatementsAllUsers",
            "statementDestroyerNumDeferredDestroyStatementsAllUsers",
            "statementDestroyerNumConnectionsInUseDefaultUser",
            "statementDestroyerNumConnectionsWithDeferredDestroyStatementsDefaultUser",
            "statementDestroyerNumDeferredDestroyStatementsDefaultUser",
            "statementDestroyerNumThreads",
            "statementDestroyerNumActiveThreads",
            "statementDestroyerNumIdleThreads",
            "statementDestroyerNumTasksPending",
            "threadPoolSize",
            "threadPoolNumActiveThreads",
            "threadPoolNumIdleThreads",
            "threadPoolNumTasksPending",
            "threadPoolStackTraces",
            "threadPoolStatus",
            "overrideDefaultUser",
            "overrideDefaultPassword",
            "password",
            "reference",
            "upTimeMillisDefaultUser",
            "user",
            "userOverridesAsString",
            "allUsers",
            "connectionPoolDataSource",
            "propertyChangeListeners",
            "vetoableChangeListeners"
    }));

}

@@ -1224,16 +1224,50 @@
 e(100);%0A
+        cpds.setMaxIdleTime(300);%0A
         
@@ -1773,10 +1773,8 @@
 ) %7B%0A
-//
     
@@ -1793,26 +1793,20 @@
     
-System.out.println
+logger.debug
 (%22Op

add idle timeout