package com.sifang.modules.order.utils;

import com.google.common.collect.Lists;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import org.hibernate.Session;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author Ivan
 * 手动JDBC处理批量持久化操作
 */
public class DBUtils {
	

	public static Map<Integer, String> wrapTransactionListMap(Map<Integer, String> map, String sql){
		if(map == null) return null;
		int i = map.size();
		map.put(i, sql);
		i++;
		return map;
	}
	
	/****
	 * @param :进行事务处理的list,注意list中执行sql语句的顺序!!
	 * @param session
	 */
	public static int insertInTransaction(Map<Integer, String> map, Session session){
		final Map<Integer, String> operMap = map;//进行处理的事务list
		return session.doReturningWork(new ReturningWork<Integer>() {
			@Override
			public Integer execute(Connection conn) throws SQLException {
				Savepoint sp = conn.setSavepoint();
				boolean isReadOnly = conn.isReadOnly();
				boolean isAutoCommit = conn.getAutoCommit();
				conn.setAutoCommit(false);
				conn.setReadOnly(false);
				try{
					for(int i = 0 ; i < operMap.size(); i++){
						String sql = operMap.get(i);
						PreparedStatement pstm = conn.prepareStatement(sql);
						pstm.getConnection().setAutoCommit(false);
						pstm.executeUpdate();
					}
					conn.commit();
					conn.setReadOnly(isReadOnly);
					conn.setAutoCommit(isAutoCommit);
				}catch (Exception e) {
					e.printStackTrace();
					conn.rollback(sp);
					conn.commit();
					return -1;
				}
				return 0;
			}
		});
	}
	
	/**
	 * 单条记录的更新
	 * @param sql
	 * @param
	 * @param session
	 */
	public static boolean updateSQL(String sql, Session session) {
		final String UPDATESQL = sql;
		try{
			session.doWork(new Work() {
				public void execute(Connection connection) throws SQLException {
					boolean isReadOnly = connection.isReadOnly();
					connection.setReadOnly(false);
					PreparedStatement pstm = connection.prepareStatement(UPDATESQL);
					pstm.executeUpdate();
					connection.setReadOnly(isReadOnly);
					//DBUtils.closePreparedStatement(pstm);
					//DBUtils.closeConnection(connection);
				}
			});
		}catch (Exception e) {
			e.printStackTrace();
			System.out.println("update DB failed!!!");
			System.out.println(">>>>>>>>>>>>>>>>>>>>>>");
			System.out.println(sql);
			return false;
		}
		return true;
	}


	/**
	 * 根据传递过来的sql语句，执行批量操作
	 * @param sql
	 * @param paramList
	 * @param
	 * @return
	 */
	public static boolean batchSaveOrUpdateSQLCus(final String sql, List<Object[]> paramList){
		final String BATCHINSERSQL = sql;
		final List<Object[]> BATCHPARAMLIST = paramList;
		try{
			Db.tx(new IAtom() {
				@Override
				public boolean run() throws SQLException {
					System.out.println("sql : "+sql);
					// exe sql (name, mobile, address, brand, category, type, appliance_model, appliance_barcode, appliance_buy_time, purchase_price,id,site_id)
				String column = "name,mobile,address,brand,category,type,appliance_model,appliance_barcode,purchase_price,appliance_buy_time,id,site_id,create_time";
						List<Record> list = Lists.newArrayList();
					for(Object[] item : BATCHPARAMLIST){
						Record rd = new Record();
						rd.set("name", item[0]);
						rd.set("mobile", item[1]);
						rd.set("address", item[2]);
						rd.set("brand", item[5]);
						rd.set("category", item[4]);
						rd.set("type", item[3]);
						rd.set("appliance_model", item[6]);
						rd.set("appliance_barcode", item[7]);
						rd.set("purchase_price", item[8]);
						rd.set("appliance_buy_time", item[9]);
						rd.set("id", item[10]);
						rd.set("site_id", item[11]);
						rd.set("create_time", item[12]);
						list.add(rd);
					}
				int dsk[]=	Db.batch(BATCHINSERSQL,column,list,list.size());
					return true;
				}
			});

		}catch (Exception e) {
			e.printStackTrace();
			System.out.println("BatchInsert DB failed!!!");
			System.out.println(sql);
		//	throw new RuntimeException("BatchInsert DB failed!!!");
			return false;
		}
		return true;
	}


	/**
	 * 根据传递过来的sql语句，执行批量操作
	 * @param sql
	 * @param paramList
	 * @param session
	 * @return
	 */
	public static boolean batchSaveOrUpdateSQL(String sql, List<Object[]> paramList, Session session){
		final String BATCHINSERSQL = sql;
		final List<Object[]> BATCHPARAMLIST = paramList;
		try{
			session.doWork(new Work(){
				@Override
				public void execute(Connection connection) throws SQLException {
					boolean isReadOnly = connection.isReadOnly();
					connection.setReadOnly(false);
					PreparedStatement pstm = connection.prepareStatement(BATCHINSERSQL);
					for(int i =0; i < BATCHPARAMLIST.size(); i++){
						Object[] os = BATCHPARAMLIST.get(i);
						for(int j = 0; j<os.length; j++){
							pstm.setObject(j+1, os[j]);
						}
						pstm.addBatch();
					}
					pstm.executeBatch();
					connection.setReadOnly(isReadOnly);
					//DBUtils.closePreparedStatement(pstm);
					//DBUtils.closeConnection(connection);
				}
			});
		}catch (Exception e) {
			e.printStackTrace();
			System.out.println("BatchInsert DB failed!!!");
			System.out.println(">>>>>>>>>>>>>>>>>>>>>>");
			System.out.println(sql);
			throw new RuntimeException("BatchInsert DB failed!!!");
		}
		return true;
	}
	

	public static boolean insertSQL(String sql, Session session){
		final String insertQuery = sql;
		try{
			session.doWork(new Work() {
				public void execute(Connection connection) throws SQLException {
					boolean isReadOnly = connection.isReadOnly();
					connection.setReadOnly(false);
					PreparedStatement pstm = connection.prepareStatement(insertQuery);
					pstm.execute();
					connection.setReadOnly(isReadOnly);
					//DBUtils.closePreparedStatement(pstm);
					//DBUtils.closeConnection(connection);
				}
			});
		}catch (Exception e) {
			e.printStackTrace();
			System.out.println("insert DB failed!!!");
			System.out.println(">>>>>>>>>>>>>>>>>>>>>>");
			System.out.println(sql);
			return false;
		}
		return true;
	}
	
	public static List querySQL(String sql, Session session){
//		List list = new ArrayList();
		final String query = sql;
		
		ResultSet rs = 
		session.doReturningWork(new ReturningWork<ResultSet>() {
			public ResultSet execute(Connection connection) throws SQLException {
				PreparedStatement pstm = connection.prepareStatement(query);
				//DBUtils.closePreparedStatement(pstm);
				//DBUtils.closeConnection(connection);
				return pstm.executeQuery();
			}
		});

		List list = Result2List(rs);
		closeResultSet(rs);
		return list;
	}
	
	private static List Result2List(ResultSet rs){
		List list = new ArrayList();
		Map rowData = new HashMap();
		
		try {
			ResultSetMetaData md = rs.getMetaData();
			int columnCount = md.getColumnCount();
			while(rs.next()){
				rowData = new HashMap(columnCount);
				for(int i = 1; i<=columnCount; i++){
					rowData.put(md.getColumnLabel(i), rs.getObject(i));
				}
				list.add(rowData);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}
	
	public static void closeConnection(Connection con){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			con = null;
		}
	}
	
	public static void closeResultSet(ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
	}
	
	public static void closePreparedStatement(PreparedStatement pstm){
		if(pstm!=null){
			try {
				pstm.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			pstm = null;
		}
	}
}
