package brn.distsim.ormapper.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;


import org.hibernate.Session;

import brn.distsim.ormapper.class2hbm.IdGenerator;

public abstract class SessionHandler {
	protected int simulationId;

	protected Connection connection;

	protected Properties hbProps;

	protected Session session;

	protected Interceptor interceptor;

	public SessionHandler(String dbUrl, String dbUser, String dbPasswd,
			int jobId) throws ClassNotFoundException, SQLException {
		SimulationIdResolver.setSimulationId(jobId);
    IdGenerator.setSimulationId(jobId);
		this.simulationId = jobId;
		setProperties(dbUrl, dbUser, dbPasswd);
	}

	 public SessionHandler(String resUrl, String resUser, String resPasswd,
	      String defUrl, String defUser, String defPasswd)
	      throws SQLException, ClassNotFoundException {
	    setProperties(resUrl, resUser, resPasswd);
	    Connection defConnection = DriverManager.getConnection(defUrl, defUser,
	        defPasswd);
	    Statement statement = defConnection.createStatement();
	    statement.executeUpdate(
	        "INSERT INTO simulations SET groupId=1, defined=NOW();",
	        Statement.RETURN_GENERATED_KEYS);
	    ResultSet key = statement.getGeneratedKeys();
	    key.next();
	    simulationId = key.getInt(1);
	    SimulationIdResolver.setSimulationId(simulationId);
	    IdGenerator.setSimulationId(simulationId);
	  }


	private void setProperties(String dbUrl, String dbUser, String dbPasswd)
			throws SQLException, ClassNotFoundException {
		interceptor = new Interceptor();
		Class.forName("com.mysql.jdbc.Driver");
		connection = DriverManager.getConnection(dbUrl, dbUser, dbPasswd);

		hbProps = new Properties();
		hbProps.put("hibernate.query.substitutions", "yes 'Y', no 'N'");
		hbProps.put("hibernate.dialect",
				"org.hibernate.dialect.MySQLInnoDBDialect");
		hbProps.put("hibernate.connection.driver_class",
				"com.mysql.jdbc.Driver");
		hbProps.put("hibernate.connection.url", dbUrl);
		hbProps.put("hibernate.connection.username", dbUser);
		hbProps.put("hibernate.connection.password", dbPasswd);
		hbProps.put("hibernate.cache.provider_class",
				"org.hibernate.cache.HashtableCacheProvider");
		hbProps.put("hibernate.current_session_context_class", "thread");
		hbProps.put("hibernate.jdbc.batch_size", "50");
		hbProps.put("hibernate.cache.use_second_level_cache", "false");
		hbProps.put("hibernate.jdbc.use_streams_for_binary", "true");
		hbProps.put("hibernate.connection.isolation", "1");
		hbProps.put("hibernate.connection.autocommit", "true");
		hbProps.put("hibernate.jdbc.batch_versioned_data", "true");
		hbProps.put("hibernate.default_batch_fetch_size", "8");
		hbProps.put("hibernate.max_fetch_depth", "1");
		hbProps.put("hibernate.connection.pool_size", "5");
		hbProps.put("hibernate.proxool.pool_alias", "pool1");
		hbProps.put("hibernate.order_updates", "true");
		hbProps.put("hibernate.connection.isolation", "1");
		// hbProps.put("hibernate.generate_statistics", "true");

//		hbProps.put("hibernate.c3p0.min_size", "0");
//    hbProps.put("hibernate.c3p0.max_size", "10");
//    hbProps.put("hibernate.c3p0.timeout","5");
    //hbProps.put("hibernate.c3p0.max_statements","200");

    hbProps.put("hibernate.connection.cachePrepStmts", "true");
    hbProps.put("hibernate.connection.cacheCallableStatements", "true");
    hbProps.put("hibernate.connection.cacheServerConfiguration", "true");
    hbProps.put("hibernate.connection.useLocalSessionState", "true");
    hbProps.put("hibernate.connection.elideSetAutoCommits", "true");
    hbProps.put("hibernate.connection.alwaysSendSetIsolation", "false");
    hbProps.put("hibernate.connection.enableQueryTimeouts", "true");

    hbProps.put("hibernate.connection.allowMultiQueries", "true");
    hbProps.put("hibernate.connection.cacheResultSetMetadata", "true");
    hbProps.put("hibernate.connection.callableStatementCacheSize", "200");
    hbProps.put("hibernate.connection.detectServerPreparedStmts", "true");
    hbProps.put("hibernate.connection.metadataCacheSize", "100");
    hbProps.put("hibernate.connection.preparedStatementCacheSize", "100");
    hbProps.put("hibernate.connection.preparedStatementCacheSqlLimit", "256");

    hbProps.put("hibernate.connection.reportMetricsIntervalMillis", "30000");
    hbProps.put("hibernate.connection.gatherPerformanceMetrics", "true");

    hbProps.put("hibernate.connection.emulateUnsupportedPstmts", "false");
    hbProps.put("hibernate.connection.rewriteBatchedStatements", "true");

		//hbProps.put("hibernate.show_sql", "true");
		//hbProps.put("hibernate.use_sql_comments", "true");
		//hbProps.put("hibernate.format_sql", "true");
	}

  public void close() {
    try {
      if (session != null)
        session.close();
    } catch (Throwable e) {}
    try {
      if (connection != null)
        connection.close();
    } catch (Throwable e) {}

    session = null;
    connection = null;
  }

  public void finalize() throws Throwable {
    close();
  }

}
