package com.chenyang.nse.bussiness.controller.core;

import com.chenyang.nse.bussiness.entity.cache.LoginUser;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreEngine;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreSubset;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreSubsetcolumns;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreSubsettask;
import com.chenyang.nse.bussiness.entity.orm.table.core.masking.TCoreMaskingRule;
import com.chenyang.nse.bussiness.entity.vo.ComboboxVO;
import com.chenyang.nse.bussiness.entity.vo.ResultVO;
import com.chenyang.nse.bussiness.entity.vo.SubSetColumn;
import com.chenyang.nse.bussiness.service.core.DataSystemService;
import com.chenyang.nse.bussiness.service.core.ImportMaskingRuleService;
import com.chenyang.nse.bussiness.service.core.SubsetService;
import com.chenyang.nse.bussiness.tools.jdbc.JdbcTool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping({"/core/createsubsettask"})
public class CreateSubsetTaskController {
   @Autowired
   private DataSystemService dataSystemService;
   @Autowired
   private SubsetService subsetService;
   @Autowired
   private ImportMaskingRuleService importMaskingRuleService;
   private static List<String> noSizeList = new ArrayList();

   @RequestMapping
   public String index(String subsetName, HttpServletRequest request, HttpServletResponse response, Model model) {
      LoginUser loginUser = (LoginUser)request.getSession().getAttribute("loginUser");
      model.addAttribute("privileges", loginUser.getPrivileges());
      return "core/createsubsettask/createsubsettask";
   }

   @ResponseBody
   @RequestMapping({"/querydatasystem"})
   public List<TCoreDatasystem> querydatasource(HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.dataSystemService.querydatasource();
   }

   @ResponseBody
   @RequestMapping({"/queryShemas"})
   public List<ComboboxVO> queryShemas(String dbType, String dataSystemId, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.dataSystemService.queryShemas(dbType, dataSystemId);
   }

   @ResponseBody
   @RequestMapping({"/queryTables"})
   public List<String> queryTables(String dataSystemId, String schema, HttpServletRequest request, HttpServletResponse response, Model model) {
      if (schema == null) {
         return new ArrayList();
      } else {
         TCoreDatasystem datasystem = this.dataSystemService.queryDataSystemById(dataSystemId);
         this.iskeberos(datasystem);
         Connection conn = JdbcTool.getConnection(datasystem);
         List<String> tables = getTablesOfSchema(conn, datasystem.getDbtype(), schema);
         Collections.sort(tables);

         try {
            conn.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }

         return tables;
      }
   }

   @ResponseBody
   @RequestMapping({"/queryColumns"})
   public List<SubSetColumn> queryColumns(String dataSystemId, String schema, String tableName, HttpServletRequest request, HttpServletResponse response, Model model) {
      TCoreDatasystem datasystem = this.dataSystemService.queryDataSystemById(dataSystemId);
      this.iskeberos(datasystem);
      Connection conn = JdbcTool.getConnection(datasystem);
      List<SubSetColumn> columns = getColumnDataOfTable(conn, datasystem.getDbtype(), tableName, schema);

      try {
         conn.close();
      } catch (SQLException e) {
         e.printStackTrace();
      }

      return columns;
   }

   @ResponseBody
   @RequestMapping({"/checkSubsetName"})
   public boolean checkSubsetName(String subsetName, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.subsetService.checkSubsetName(subsetName);
   }

   @ResponseBody
   @RequestMapping({"/save"})
   public TCoreSubset save(TCoreSubset subset, @RequestParam("subsetColumns[]") List<String> subsetColumns, HttpServletRequest request, HttpServletResponse response, Model model) {
      TCoreSubset result = this.subsetService.saveSubsetAndColumns(subset, subsetColumns);
      request.getSession().setAttribute("lastSelectSubsetName", null);
      return result;
   }

   @ResponseBody
   @RequestMapping({"/delete"})
   public boolean delete(String id, HttpServletRequest request, HttpServletResponse response, Model model) {
      this.subsetService.delete(id);
      request.getSession().setAttribute("lastSelectSubsetName", null);
      return true;
   }

   @ResponseBody
   @RequestMapping({"/querySubset"})
   public List<TCoreSubset> querySubset(String dataSystemId, String schema, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.subsetService.querySubset(dataSystemId, schema);
   }

   @ResponseBody
   @RequestMapping({"/querySubsetById"})
   public TCoreSubset querySubsetById(String id, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.subsetService.querySubsetById(id);
   }

   @ResponseBody
   @RequestMapping({"/querySubsetColumns"})
   public List<TCoreSubsetcolumns> querySubsetColumns(String subsetid, HttpServletRequest request, HttpServletResponse response, Model model) {
      List<TCoreSubsetcolumns> list = this.subsetService.querySubsetColumns(subsetid);
      return list;
   }

   @ResponseBody
   @RequestMapping({"/checkWhereStatement"})
   public ResultVO checkWhereStatement(String dataSystemId, String schema, String whereStatements, HttpServletRequest request, HttpServletResponse response, Model model) {
      TCoreDatasystem datasystem = this.dataSystemService.queryDataSystemById(dataSystemId);
      this.iskeberos(datasystem);
      Connection conn = JdbcTool.getConnection(datasystem);
      String[] arr = whereStatements.split(",");

      for(String tableWhere : arr) {
         String[] tempArr = tableWhere.split(":");
         if (tempArr.length != 2) {
            return new ResultVO("过滤条件格式不正确！", false);
         }

         String sql = MessageFormat.format("select * from {0}.{1} where {2}", schema, tempArr[0], tempArr[1]);

         try {
            PreparedStatement statement = conn.prepareStatement(sql);
            ResultSet resultSet = statement.executeQuery();
            resultSet.close();
            statement.close();
         } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return new ResultVO(tempArr[0] + ": " + e.getMessage(), false);
         }
      }

      try {
         conn.close();
      } catch (SQLException e) {
         e.printStackTrace();
      }

      return new ResultVO((String)null, true);
   }

   @ResponseBody
   @RequestMapping({"/saveSubsetTask"})
   public TCoreSubsettask saveSubsetTask(TCoreSubsettask subsetTask, HttpServletRequest request, HttpServletResponse response, Model model) {
      LoginUser loginUser = (LoginUser)request.getSession().getAttribute("loginUser");
      String taskid = this.subsetService.saveSubsetTask(subsetTask, loginUser.getTsysUser().getId());
      return this.subsetService.queryTaskById(taskid);
   }

   @ResponseBody
   @RequestMapping({"/executeTask"})
   public String executeTask(TCoreSubsettask subsetTask, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.subsetService.executeTask(subsetTask);
   }

   @ResponseBody
   @RequestMapping({"/querymaskingengine"})
   public List<TCoreEngine> querymaskingengine(HttpServletRequest request, HttpServletResponse response, Model model) {
      List<TCoreEngine> list = this.importMaskingRuleService.queryMaskingEngine();
      return list;
   }

   @ResponseBody
   @RequestMapping({"/checkTaskName"})
   public boolean checkTaskName(String taskName, HttpServletRequest request, HttpServletResponse response, Model model) {
      return this.subsetService.checkTaskName(taskName);
   }

   @RequestMapping({"/queryMaskingRules"})
   @ResponseBody
   public List<TCoreMaskingRule> queryMaskingRules(HttpServletRequest request, HttpServletResponse response, Model model) {
      List<TCoreMaskingRule> list = this.importMaskingRuleService.queryValidRule();
      return list;
   }

   @RequestMapping({"/monitor"})
   public String monitor(String taskid, String recordid, HttpServletRequest request, HttpServletResponse response, Model model) {
      model.addAttribute("taskid", taskid);
      model.addAttribute("recordid", recordid);
      return "core/maskingtask/monitor";
   }

   private static boolean hasColumnSize(String columnType) {
      return !noSizeList.contains(columnType) && !columnType.startsWith("TIMESTAMP");
   }

   private static List<SubSetColumn> getColumnDataOfTable(Connection connection, String dbType, String tableName, String schema) {
      List<SubSetColumn> columns = new ArrayList();

      try {
         Map<String, String> pkeys = new HashMap();
         ResultSet pkResultSet = connection.getMetaData().getPrimaryKeys((String)null, schema, tableName);

         while(pkResultSet.next()) {
            String columnName = pkResultSet.getString("COLUMN_NAME");
            String num = pkResultSet.getString("KEY_SEQ");
            pkeys.put(columnName, num);
         }

         pkResultSet.close();

         ResultSet allColumnsResultSet;
         SubSetColumn col;
         for(allColumnsResultSet = connection.getMetaData().getColumns((String)null, schema, tableName, "%"); allColumnsResultSet.next(); columns.add(col)) {
            String columnName = allColumnsResultSet.getString("COLUMN_NAME");
            String typeName = allColumnsResultSet.getString("TYPE_NAME");
            String columnSize = allColumnsResultSet.getString("COLUMN_SIZE");
            String decimalDigits = allColumnsResultSet.getString("DECIMAL_DIGITS");
            if (decimalDigits == null || decimalDigits.equals("")) {
               decimalDigits = "0";
            }

            String columnType = typeName;
            if (hasColumnSize(typeName)) {
               String sizeAndPrecision = getColumnSize(allColumnsResultSet);
               if (sizeAndPrecision != null) {
                  columnType = typeName + "(" + sizeAndPrecision + ")";
               }
            }

            col = new SubSetColumn(columnName, columnType, typeName, columnSize, decimalDigits);
            if (pkeys.containsKey(columnName)) {
               col.setKeySeq((String)pkeys.get(columnName));
            }
         }

         allColumnsResultSet.close();
      } catch (Exception e) {
         e.printStackTrace();
      }

      return columns;
   }

   private static String getColumnSize(ResultSet resultSet) {
      String result = null;

      try {
         String columnSize = resultSet.getString("COLUMN_SIZE");
         if (columnSize != null && !columnSize.equals("0")) {
            String decimalDigits = resultSet.getString("DECIMAL_DIGITS");
            if (decimalDigits != null && !decimalDigits.equals("0")) {
               decimalDigits = "," + decimalDigits;
            } else {
               decimalDigits = "";
            }

            result = columnSize + decimalDigits;
         }
      } catch (Exception e) {
         e.printStackTrace();
      }

      return result;
   }

   private static List<String> getTablesOfSchema(Connection connection, String dbType, String schema) {
      List<String> allTableList = new ArrayList();

      try {
         ResultSet allTablesResultSet = connection.getMetaData().getTables((String)null, schema, "%", new String[]{"TABLE"});

         while(allTablesResultSet.next()) {
            allTableList.add(allTablesResultSet.getString("TABLE_NAME"));
         }

         allTablesResultSet.close();
      } catch (Exception e) {
         e.printStackTrace();
      }

      return allTableList;
   }

   public void iskeberos(TCoreDatasystem datasystem) {
      if ("HIVE".equals(datasystem.getDbtype()) && "on".equals(datasystem.getIskerberos())) {
         System.setProperty("java.security.krb5.conf", datasystem.getXmlpath() + "/krb5.conf");
      }

   }

   static {
      noSizeList.add("BLOB");
      noSizeList.add("CLOB");
      noSizeList.add("DATE");
      noSizeList.add("DATETIME");
      noSizeList.add("LONGBLOB");
      noSizeList.add("LONGTEXT");
      noSizeList.add("IMAGE");
      noSizeList.add("TEXT");
      noSizeList.add("INTEGER");
      noSizeList.add("TIME");
   }
}
