package util.sqlparse.visitor.mysql.visitor;

import bean.DataBase;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLMergeStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import java.util.List;
import java.util.Map;
import util.JdbcUtil;
import util.sqlparse.visitor.common.bean.SQLResult;
import util.sqlparse.visitor.common.bean.TableInfo;
import util.sqlparse.visitor.common.memo.TableMemo;
import util.sqlparse.visitor.mysql.SQLParser;

public class Desensitization {
   public Map parseColumn(Map params) {
      return this.parseData(params);
   }

   public Map parseData(Map params) {
      String sql = (String)params.get("sql");
      SQLParser parser = new SQLParser();
      DataBase dataBase = null;
      params.put("newSql", sql);
      String url = (String)params.get("url");
      String ipPort = url.split("/")[2];

      for(DataBase base : JdbcUtil.dataBaseList) {
         if (base.getIp_port().equalsIgnoreCase(ipPort)) {
            dataBase = base;
         }
      }

      String schema = (String)params.get("schema");
      SQLResult result = parser.parse(sql, dataBase, schema);
      switch (result.statementType) {
         case select:
            FieldReplaceController controller = new FieldReplaceController(result, params);
            controller.perform();
         default:
            return params;
      }
   }

   public Map parseTable(Map params) {
      String replaceTable = params.get("replaceTable").toString();
      String replaceNewTable = params.get("replaceNewTable").toString();
      SQLResult result = this.getSqlResult(params);
      List<TableInfo> tables = result.tables;
      params.put("isMatched", "false");

      for(TableInfo table : tables) {
         for(TableMemo tableMemo : table.getMemos()) {
            boolean isMatched;
            if (result.isCaseSensitive) {
               isMatched = JdbcUtil.followRulesCaseSens(tableMemo.name, "`?" + replaceTable + "`?");
            } else {
               isMatched = JdbcUtil.followRules(tableMemo.name, "`?" + replaceTable + "`?");
            }

            if (isMatched) {
               tableMemo.name = replaceNewTable;
               tableMemo.nowName = replaceNewTable;
               SQLExprTableSource ref = (SQLExprTableSource)tableMemo.ref;
               SQLExpr ts = ref.getExpr();
               if (ts instanceof SQLIdentifierExpr) {
                  ((SQLIdentifierExpr)ts).setName(replaceNewTable);
               } else if (ts instanceof SQLPropertyExpr) {
                  SQLPropertyExpr propertyExpr = (SQLPropertyExpr)ts;
                  propertyExpr.setName(replaceNewTable);
               }

               int type = this.getTableSourceTopType(ref);
               if (ref.getAlias() == null && type == 1) {
                  ref.setAlias(replaceTable);
               }

               params.put("isMatched", "true");
            }
         }
      }

      params.put("newSql", result.statement.toString());
      return params;
   }

   private int getTableSourceTopType(SQLTableSource ts) {
      if (ts == null) {
         return 0;
      } else {
         for(SQLObject cursor = ts; cursor != null; cursor = cursor.getParent()) {
            if (cursor instanceof SQLUpdateStatement) {
               return 0;
            }

            if (cursor instanceof SQLInsertStatement) {
               return 0;
            }

            if (cursor instanceof SQLDeleteStatement) {
               return 0;
            }

            if (cursor instanceof SQLMergeStatement) {
               return 0;
            }

            if (cursor instanceof SQLSelect) {
               return 1;
            }

            if (cursor instanceof SQLSelectQuery) {
               return 1;
            }

            if (cursor instanceof SQLSelectStatement) {
               return 1;
            }
         }

         return 0;
      }
   }

   public Map parseRowVisit(Map params) {
      SQLResult result = this.getSqlResult(params);
      RowVisitController controller = new RowVisitController(result, params);
      controller.perform();
      return params;
   }

   private SQLResult getSqlResult(Map params) {
      String sql = (String)params.get("sql");
      SQLParser parser = new SQLParser();
      DataBase dataBase = null;
      params.put("newSql", sql);
      String url = (String)params.get("url");
      String ipPort = url.split("/")[2];

      for(DataBase base : JdbcUtil.dataBaseList) {
         if (base.getIp_port().equalsIgnoreCase(ipPort)) {
            dataBase = base;
         }
      }

      String schema = (String)params.get("schema");
      SQLResult result = parser.parse(sql, dataBase, schema);
      return result;
   }
}
