package com.tohi.com.tohi.system.db;

import com.tohi.common.pwdutil.PropertiesConfigurerUtil;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

public final class DBConnectionPool extends Pool{
    private int checkedOut;//正在使用的连接数
    private Vector<Connection> freeConnections = new Vector<Connection>();

    private String passWord = null;// 密码
    private String url=null;//连接字符串
    private String userName = null;// 用户名
    private static int num = 0;//空闲连接数
    private static int numActive =0;//当前可用的连接数

    private static DBConnectionPool pool= null;//连接池实例变量

    // 产生数据连接池
    public static synchronized DBConnectionPool getInstance(){
        if(pool==null)
            pool = new DBConnectionPool();
        return pool;
    }
    private DBConnectionPool(){
        try{
            //初始normalConn 个连接
            init();
            for (int i=0;i< normalConnect; i++){
                Connection c = newConnection();
                if (c!= null) {
                    freeConnections.addElement(c); //往容器中添加一个连接对象
                    num++;//记录总连接数
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void init() throws IOException {
        this.userName = PropertiesConfigurerUtil.getProperty("userName");
        this.passWord= PropertiesConfigurerUtil.getProperty("passWord");
        this.url= PropertiesConfigurerUtil.getProperty("url");
        this.driverName=PropertiesConfigurerUtil.getProperty("driverName");
        this.maxConnect = Integer.parseInt(PropertiesConfigurerUtil.getProperty("maxConnect"));
        this.normalConnect =Integer.parseInt(PropertiesConfigurerUtil.getProperty("normalConnect"));
    }

    // 如果不再使用某个连接对象，可调此方法将该对象释放到连接池
    public synchronized void freeConnection(Connection con){
        freeConnections.addElement(con);
        num++;
        checkedOut--;
        numActive--;
        notifyAll();//解锁
    }

    //创建一个新连接
    private Connection newConnection(){
        Connection con = null;
        try{
            // 用户、密码都为空
            if(userName == null){
                con = DriverManager.getConnection(url);
            }else{
                con = DriverManager.getConnection(url,userName,passWord);
            }
            String shcemaOwner = PropertiesConfigurerUtil.getProperty("shcema-owner-name");
            this.changeSchemaOwnerOracle(con,shcemaOwner);
            System.out.println("创建一个新连接");
        }catch (Exception e){
                e.printStackTrace();
                return null;
        }

        return con;
    }

    private static void changeSchemaOwnerOracle(Connection connection, String schemaowner) throws Exception {
        Statement st = connection.createStatement();
        String sql = "alter session set current_schema = " + schemaowner;
        st.execute(sql);
        st.close();
    }

            //返回当前空闲连接数
            public int getnum() {
                return num;
            }
    // 返回当前连接数
        public int getnumActive() {
            return numActive;
        }

    // (单例模式)获取一个可用连接
    public synchronized Connection getConnection(){
        Connection con = null;
        if(freeConnections.size() > 0 ){
            num--;
            con = (Connection) freeConnections.firstElement();
            freeConnections.removeElementAt(0);
            try{
                if (con.isClosed()){
                    System.out.println("从连接池中删除一个无效连接");
                    con = getConnection();
                }
            }catch (Exception e){
                System.out.println("从连接池中删除一个无效连接");
                e.printStackTrace();
                con = getConnection();
            }
        }else if(maxConnect == 0 || checkedOut < maxConnect){
                con = newConnection();
        }
        if(con != null){
            checkedOut++; //当前连接数+1
        }
        numActive++;
        return con;
    }

    // 获取一个连接，并加上等待时间限制，单位为毫秒
    public synchronized Connection getConnection(long timeout){
        long startTime = new Date().getTime();
        Connection con;
        while ((con = getConnection())== null){
            try{
                wait(timeout);//线程等待
            }catch (InterruptedException     e){

            }

            if((new Date().getTime() - startTime) >= timeout){
                return null;
            }
        }
        return con;
    }

    //关闭所有连接
    public synchronized  void release(){
        try{
            //将当前连接赋值到枚举中
            Enumeration allConnections = freeConnections.elements();
            //使用循环关闭所用连接
            while (allConnections.hasMoreElements()) {
                //如果此枚举对象至少还有一个可提供的元素，则返回此枚举对象的下一个元素
                Connection con = (Connection) allConnections.nextElement();
                try {
                    con.close();
                    num--;
                }catch (Exception e){

                }
            }
            freeConnections.removeAllElements();
            numActive = 0 ;
        }catch (Exception e){
            System.out.println("无法关闭连接池中的连接");
        }finally {
            super.release();
        }
    }

    // 建立连接池
    public void createPool(){
        pool = new DBConnectionPool();
        if (pool != null){
            System.out.println("创建连接池成功");
          }else {
            System.out.println("创建连接池失败");
        }

     }


}
