package com.ces.mybatis.Interceptor;

import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.ces.mybatis.typeHandler.ContentTypeHandler;


@Intercepts({
    @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", args = {Statement.class})
})
@Component
public class SqlLogInterceptor implements Interceptor {

	final Log log = LogFactory.getLog(ContentTypeHandler.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();

        StatementHandler statementHandler = (StatementHandler)target;

        try {
            return invocation.proceed();
        } finally {

            BoundSql boundSql = statementHandler.getBoundSql();
            String sql = boundSql.getSql();
            Object parameterObject = boundSql.getParameterObject();
            List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();

            // 格式化Sql语句，去除换行符，替换参数
            sql = sql.replaceAll("\r|\n|\t", " ").replaceAll("\\s+", " ");
            if(parameterObject == null){
                sql = sql.replaceAll("\\?", " null");
                return sql;
            }
            if(Map.class.isAssignableFrom(parameterObject.getClass())){
                Map pb = (Map)parameterObject;
                for(ParameterMapping temp: parameterMappingList){
                    if (pb.get(temp.getProperty()) != null){
                        if (pb.get(temp.getProperty()).getClass().isAssignableFrom(JSONObject.class)){
                            JSONObject infObject = (JSONObject) pb.get(temp.getProperty());
                            sql = sql.replaceFirst("\\?","'" + infObject.toJSONString() + "'");
                        }else {
                            sql = sql.replaceFirst("\\?","'" + pb.get(temp.getProperty()) + "'");
                        }
                    }else {
                        sql = sql.replaceFirst("\\?","'null'");
                    }
                }
            }
            if(String.class.isAssignableFrom(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", parameterObject == null ? "null" : "'" + parameterObject + "'");
            }
            if(Number.class.isAssignableFrom(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", parameterObject == null ? "null" : parameterObject.toString());
            }

            log.warn("SQL：" + sql + ";");

        }
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
