package com.hotent.base.util;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Component;

import com.alibaba.druid.pool.DruidPooledConnection;

/**
 * 
 * @author jason
 *
 */
@Component
public class TransactionThreadLocal {

	private static ThreadLocal<Connection> currentConnections = new ThreadLocal<Connection>();

	private static ThreadLocal<List<Map<Connection, DataSource>>> connectionAndDSList = new ThreadLocal<List<Map<Connection, DataSource>>>();

	private void cleanAll() {
		connectionAndDSList.remove();
		currentConnections.remove();
	}

	public void cleanCurrentConnection() {
		currentConnections.remove();
	}

	public void setCurrentConnections(Connection connection) {
		currentConnections.set(connection);
	}

	public Connection getCurrentConnection() {
		Connection connection = currentConnections.get();
		return connection;
	}

	/**
	 * <pre>
	 * 提交
	 * </pre>
	 * 
	 * @throws SQLException
	 */
	public void commit() throws SQLException {
		List<Map<Connection, DataSource>> list = connectionAndDSList.get();
		if (list == null) {
			return;
		}
		list.stream().forEach(tmMap -> {
			tmMap.forEach((connection, dataSource) -> {
				try {
					if (!connection.isClosed()) {
						connection.commit();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				} finally {
					// 释放资源
					if (connection != null) {
						DataSourceUtils.releaseConnection(connection, dataSource);
					}
				}

			});
		});
		cleanAll();
	}

	/**
	 * <pre>
	 * 回滚
	 * </pre>
	 * 
	 * @throws SQLException
	 */
	public void rollback() throws SQLException {
		List<Map<Connection, DataSource>> list = connectionAndDSList.get();
		if (list == null) {
			return;
		}
		list.stream().forEach(tmMap -> {
			tmMap.forEach((connection, dataSource) -> {
				try {
					if (!connection.isClosed()) {
						connection.rollback();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				} finally {
					// 释放资源
					if (connection != null) {
						DataSourceUtils.releaseConnection(connection, dataSource);
					}
				}

			});
		});
		cleanAll();
	}

	/**
	 * Releases this <code>Connection</code> object's database and JDBC resources
	 * immediately instead of waiting for them to be automatically released.
	 * <P>
	 * Calling the method <code>close</code> on a <code>Connection</code> object
	 * that is already closed is a no-op.
	 * <P>
	 * It is <b>strongly recommended</b> that an application explicitly commits or
	 * rolls back an active transaction prior to calling the <code>close</code>
	 * method. If the <code>close</code> method is called and there is an active
	 * transaction, the results are implementation-defined.
	 * <P>
	 *
	 * @exception SQLException SQLException if a database access error occurs
	 */
	public void close() throws SQLException {
		List<Map<Connection, DataSource>> list = connectionAndDSList.get();
		if (list == null) {
			return;
		}
		list.stream().forEach(tmMap -> {
			tmMap.forEach((connection, dataSource) -> {
				// 释放资源
				try {
					if (connection != null && !connection.isClosed()) {
						DataSourceUtils.releaseConnection(connection, dataSource);
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}

			});
		});
		cleanAll();
	}

	public void addConnectionAndDS(Map<Connection, DataSource> map) {
		List<Map<Connection, DataSource>> list = connectionAndDSList.get();
		if (list == null) {
			list = new ArrayList<Map<Connection, DataSource>>();
		}
		if(list.contains(map)) {
			return;
		}
		list.add(map);
		connectionAndDSList.set(list);
	}

}
