package com.igumnov.common;

import com.igumnov.common.dependency.DependencyException;
import com.igumnov.common.orm.DDLHistory;
import com.igumnov.common.orm.Transaction;
import com.igumnov.common.reflection.ReflectionException;
import org.apache.commons.dbcp2.BasicDataSource;

import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.sql.*;
import java.util.ArrayList;

public class ORM {
    private static BasicDataSource ds;

    public static void connectionPool(String driverClass, String url, String user, String password, int minPoolSize, int maxPoolSize) throws DependencyException {
        ds = new BasicDataSource();
        ds.setDriverClassName(driverClass);
        ds.setUrl(url);
        ds.setUsername(user);
        ds.setPassword(password);
        ds.setInitialSize(minPoolSize);
        ds.setMaxTotal(maxPoolSize);
        Dependency.bind("dataSource", ds);

    }

    public static void applyDDL(String sqlFolder) throws java.sql.SQLException, IOException, ReflectionException, IllegalAccessException, InstantiationException {
        Connection con = null;
        int i=1;
        ResultSet tables=null;
        try {
            con = ds.getConnection();
            DatabaseMetaData dbm = con.getMetaData();
            tables = dbm.getTables(null, null, "DDLHISTORY", null);
            if (tables.next()) {
                ArrayList<Object> ret = findBy("true order by id limit 1", DDLHistory.class);
                i = 1 + ((DDLHistory)ret.get(0)).getId();
            } else {

                Statement stmt=null;
                try {
                    stmt = con.createStatement();
                    String sql = "CREATE TABLE DDLHistory (id INT PRIMARY KEY, applyDate DATE)";
                    stmt.execute(sql);
                    Log.debug(sql);
                } finally {
                    if(stmt!=null) {
                        try {
                            stmt.close();
                        } catch (Exception e) {}
                    }
                }


            }

            tables.close();

        } finally {
            try {
                if (con != null) con.close();
            } catch (Exception e) {
            }
            try {
                if (tables != null) tables.close();
            } catch (Exception e) {
            }

        }

        try {
            for (; true; i++) {
                Connection c=ds.getConnection();
                try {
                    c.setAutoCommit(false);
                    File.readLines(sqlFolder + "/" + i + ".sql").forEach((line) -> {
                        Statement stmt = null;
                        try {
                            stmt = c.createStatement();
                            stmt.execute(line);
                            Log.debug(line);

                        } catch (SQLException e) {
                            Log.error("SQL error: ", e);
                        } finally {
                            try {
                                if (stmt != null) stmt.close();
                            } catch (Exception e) {
                            }
                        }
                    });
                    c.commit();
                    DDLHistory ddl = new DDLHistory();
                    ddl.setId(i);
                    ddl.setApplyDate(new java.util.Date());
                    insert(ddl);
                } finally {
                    try {
                        if (c != null) {
                            c.setAutoCommit(true);
                            c.close();
                        }
                    } catch (Exception e) {
                    }
                }
            }
        } catch (NoSuchFileException e) {
            //It is last sql file
        }

    }

    public static Transaction beginTransaction() throws SQLException {
        return new Transaction(ds.getConnection());
    }



    public static Object update(Object obj) throws IllegalAccessException, SQLException {
        Transaction tx = null;
        Object ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.update(obj);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;

    }


    public static Object insert(Object obj) throws IllegalAccessException, SQLException, ReflectionException {
        Transaction tx = null;
        Object ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.insert(obj);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;

    }

    public static ArrayList<Object> findBy(String where, Class classObject, Object... params) throws SQLException, IllegalAccessException, InstantiationException, ReflectionException {
        Transaction tx = null;
        ArrayList<Object> ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.findBy(where,classObject,params);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;
    }

    public static Object findOne(Class className, Object primaryKey) throws SQLException, ReflectionException, InstantiationException, IllegalAccessException {
        Transaction tx = null;
        Object ret;
        try {
            tx = ORM.beginTransaction();
            ret =  tx.findOne(className,primaryKey);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;
    }

    public static int deleteBy(String where, Class classObject, Object... params) throws SQLException {
        Transaction tx = null;
        int ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.deleteBy(where,classObject,params);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;
    }

    public static int delete(Object obj) throws IllegalAccessException, SQLException {
        Transaction tx = null;
        int ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.delete(obj);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;
    }

    public static ArrayList<Object> findAll(Class classObject) throws SQLException, ReflectionException, InstantiationException, IllegalAccessException {

        Transaction tx = null;
        ArrayList<Object> ret;
        try {
            tx = ORM.beginTransaction();
            ret = tx.findAll(classObject);

        } finally {
            if (tx != null) {
                tx.commit();
            }
        }
        return ret;

    }



}

@@ -966,25 +966,16 @@
  throws 
-java.sql.
 SQLExcep
@@ -1055,32 +1055,32 @@
 tionException %7B%0A
+
         Connecti
@@ -1873,38 +1873,8 @@
 ) %7B%0A
-                        try %7B%0A
     
@@ -1915,57 +1915,8 @@
 ();%0A
-                        %7D catch (Exception e) %7B%7D%0A
     
@@ -2017,34 +2017,16 @@
 nally %7B%0A
-            try %7B%0A
         
@@ -2067,76 +2067,8 @@
 ();%0A
-            %7D catch (Exception e) %7B%0A            %7D%0A            try %7B%0A
     
@@ -2118,58 +2118,8 @@
 e();
-%0A            %7D catch (Exception e) %7B%0A            %7D
 %0A%0A  
@@ -2886,32 +2886,93 @@
 (Exception e) %7B%0A
+                                Log.error(%22SQL error: %22, e);%0A
                 
@@ -3281,34 +3281,8 @@
 y %7B%0A
-                    try %7B%0A
     
@@ -3400,32 +3400,32 @@
      c.close();%0A
+
                 
@@ -3438,74 +3438,8 @@
   %7D%0A
-                    %7D catch (Exception e) %7B%0A                    %7D%0A
     

Remove catch (Exception e) {}