package com.yanzuoguang.db.impl;

import com.yanzuoguang.db.DbExecute;
import com.yanzuoguang.extend.ConfigDb;
import com.yanzuoguang.util.vo.MapRow;
import com.yanzuoguang.util.vo.Ref;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据库操作类
 *
 * @author 颜佐光
 */
@Component
public class DbExecuteImpl implements DbExecute {

    @Resource
    @Qualifier("jdbcTemplate")
    private JdbcTemplate jdbc;

    @Resource
    private DbPrintSql printSql;

    @Resource
    private ConfigDb configDb;

    /**
     * 更新SQL语句的执行
     *
     * @param targetClass 触发类
     * @param sqlName     SQL语句名称
     * @param sql         SQL语句
     * @param paras       参数信息
     * @return
     */
    @Override
    public int update(Class targetClass, String sqlName, String sql, Object... paras) {
        int row = 0;
        long start = System.currentTimeMillis();
        try {
            sql = this.handleParas(sql, paras);
            row = jdbc.update(sql, paras);
            return row;
        } finally {
            printSql.print(targetClass, sqlName, start, row, sql, paras);
        }
    }

    /**
     * 查询数据
     *
     * @param targetClass 触发类
     * @param sqlName     SQL语句名称
     * @param cls         查询的结果的类型
     * @param rowHandle   通过该类来处理结果
     * @param sql         需要查询的SQL语句
     * @param paras       查询语句的参数
     * @param <T>         返回的集合的类型
     * @return 集合
     */
    @Override
    public <T extends Object> void query(Class targetClass, Class<T> cls, DbRow<T> rowHandle, String sqlName, String sql, Object... paras) {
        Ref<Integer> row = new Ref<Integer>(0);
        long start = System.currentTimeMillis();
        try {
            sql = this.handleParas(sql, paras);
            RowCallbackHandler rowCallbackHandler = new RowCallbackHandler() {
                @Override
                public void processRow(ResultSet rs) throws SQLException {
                    AllBeanRowMapper<T> rowMap = AllBeanRowMapper.getInstance(cls, configDb);
                    T data = rowMap.mapRow(rs, row.value);
                    rowHandle.handle(data);
                    row.value++;
                }
            };

            jdbc.query(sql, rowCallbackHandler, paras);
        } finally {
            printSql.print(targetClass, sqlName, start, row.value, sql, paras);
        }

    }

    /**
     * 查询数据,并返回集合
     *
     * @param targetClass 触发类
     * @param sqlName     SQL语句名称
     * @param cls         查询的结果的类型
     * @param sql         需要查询的SQL语句
     * @param paras       查询语句的参数
     * @param <T>         返回的集合的类型
     * @return 集合
     */
    @Override
    public <T extends Object> List<T> query(Class targetClass, Class<T> cls, String sqlName, String sql, Object... paras) {
        int row = 0;
        long start = System.currentTimeMillis();
        try {
            sql = this.handleParas(sql, paras);
            List<T> ret = jdbc.query(sql, paras, AllBeanRowMapper.getInstance(cls, configDb));
            if (ret == null) {
                ret = new ArrayList<T>();
            }
            row = ret.size();
            return ret;
        } finally {
            printSql.print(targetClass, sqlName, start, row, sql, paras);
        }
    }

    /**
     * 查询数据,并返回集合
     *
     * @param targetClass 触发类
     * @param sqlName     SQL语句名称
     * @param sql         需要查询的SQL语句
     * @param paras       查询语句的参数
     * @return 集合
     */
    @Override
    public List<MapRow> query(Class targetClass, String sqlName, String sql, Object... paras) {
        return query(targetClass, MapRow.class, sqlName, sql, paras);
    }

    /**
     * 查询第一个单元格的信息
     *
     * @param targetClass 触发类
     * @param sqlName     SQL语句名称
     * @param sql         SQL语句
     * @param paras       参数信息
     * @return 第一个单元格的数据
     */
    @Override
    public Object queryCell(Class targetClass, String sqlName, String sql, Object... paras) {
        int row = 0;
        long start = System.currentTimeMillis();
        try {
            sql = this.handleParas(sql, paras);
            SqlRowSet rowSet = jdbc.queryForRowSet(sql, paras);
            while (rowSet.next()) {
                row = 1;
                return rowSet.getObject(1);
            }
            return null;
        } finally {
            printSql.print(targetClass, sqlName, start, row, sql, paras);
        }
    }

    /**
     * 处理SQL语句和参数值
     *
     * @param sql
     * @param paras
     * @return
     */
    protected String handleParas(String sql, Object... paras) {
        return sql.replaceAll("1\\s*?=\\s*?1\\s*?(?i)AND", "")
                .replaceAll("(?i)WHERE\\s*?1\\s*?=\\s*?1", "")
                .replaceAll("((?i)ORDER\\s*?(?i)BY\\s*?)1\\s*?,", "$1")
                .replaceAll("(?i)ORDER\\s*?(?i)BY\\s*?1\\s*?", "")
                .replaceAll("((?i)GROUP\\s*?(?i)BY\\s*?)1\\s*?,", "$1")
                .replaceAll("(?i)GROUP\\s*?(?i)BY\\s*?1\\s*?", "");
    }

}