package com.wb.controls;

import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.wb.tool.DataAutoGenProvider;
import com.wb.tool.DataProvider;
import com.wb.util.DbUtil;
import com.wb.util.StringUtil;
import com.wb.util.WebUtil;
import org.json.JSONArray;
import org.json.JSONObject;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.*;
import java.util.Map.Entry;

/**
 * 数据库内容查询控件，见：{@link DataProvider}
 */
public class DpAutoGenControl extends Control {
    public void create() throws Exception {
        getContent(true);
    }

    public String createfalse() throws Exception {
        return getContent(false);
    }


    private String getSchema(Connection conn) throws Exception {
        String schema;
        schema = conn.getMetaData().getUserName();
        if ((schema == null) || (schema.length() == 0)) {
            throw new Exception("ORACLE数据库模式不允许为空");
        }
        return schema.toUpperCase().toString();

    }

    public String gettables(String sql) {

       // String sql = "select id,name from apbpst";

        // 新建 MySQL Parser
        SQLStatementParser parser = new OracleStatementParser(sql);

        // 使用Parser解析生成AST，这里SQLStatement就是AST
        SQLStatement statement = parser.parseStatement();

        // 使用visitor来访问AST
        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();

        statement.accept(visitor);
        //  System.ouimport com.alibaba.druid.sql.ast.SQLStatement;

        //  statement.(visitor);

        // 从visitor中拿出你所关注的信息
        System.out.println(visitor.getTables());

        return "";
    }

    /**
     * 获取列信息
     * @param jndi
     * @return
     * @throws Exception
     */

    public List  getcolumnconinfo(String jndi) throws Exception {
        List result = new ArrayList();
        Connection conn = DbUtil.getConnection(request, jndi);

        //String sql=  gs("sql");
       // String tables= gettables(sql);
        ResultSet rs=null;
        try {

            String tablename = request.getParameter("tableName");
            //读取表注释
            DatabaseMetaData dbmd = conn.getMetaData();
            String[] types = {"TABLE"};

             rs = conn.getMetaData().getColumns(null, getSchema(conn), tablename.toUpperCase(), "%");

            while (rs.next()) {
                //System.out.println("字段名："+rs.getString("COLUMN_NAME")+"--字段注释："+rs.getString("REMARKS")+"--字段数据类型："+rs.getString("TYPE_NAME"));
                Map map = new HashMap();
                String colName = rs.getString("COLUMN_NAME");
                map.put("code", colName);

                String remarks = rs.getString("REMARKS");
                if (remarks == null || remarks.equals("")) {
                    remarks = colName;
                }
                map.put("name", remarks);

                String dbType = rs.getString("TYPE_NAME");
                map.put("dbType", dbType);

                // map.put("valueType", changeDbType(dbType));
                result.add(map);
            }
            return result;
        }catch (Exception e){

            e.printStackTrace();
            return null;
        }





    }

    /**
     * 获取查询的内容，该内容为从数据库查询获得的结果转换为指定类型的脚本或二进制流。
     *
     * @param directOutput 是否直接输出到客户端，如果为false仅返回脚本类型的内容。
     * @return 当directOutput为false时，返回脚本类内容，否则返回null。
     */
    public String getContent(boolean directOutput) throws Exception {
        if (gb("disabled", false))
            return null;
        long startTime = System.currentTimeMillis();
        DataAutoGenProvider dp;
        Long totalCount = null;
        ResultSet resultSet = null, totalResultSet = null;
        Object result, totalResult;
        String sql, totalSql, jndi = gs("jndi");
        String limitRecords = gs("limitRecords");
        String limitExportRecords = gs("limitExportRecords");
        String loadParams = gs("loadParams");
        String totalLoadParams = gs("totalLoadParams");
        String startParam = request.getParameter("start");
        String limitParam = request.getParameter("limit");
        String type = gs("type"), dictTableNames;
        long beginIndex, endIndex;

        try {
            if (type.isEmpty() && "1".equals(request.getParameter("_istree")))
                type = "tree";
            if (StringUtil.isEmpty(type) || "array".equals(type))
                setOrderVars();
            sql = gs("sql");
            totalSql = gs("totalSql");
            if (StringUtil.isEmpty(startParam)) {
                beginIndex = 1;
                request.setAttribute("start", 0l);
            } else
                beginIndex = Long.parseLong(startParam) + 1;
            if (StringUtil.isEmpty(limitParam)) {
                endIndex = Long.MAX_VALUE;
                request.setAttribute("limit", endIndex);
            } else
                endIndex = beginIndex + Long.parseLong(limitParam) - 1;
            // beginIndex和endIndex可用于SQL between语句
            request.setAttribute("beginIndex", beginIndex);
            request.setAttribute("endIndex", endIndex);

             sql="select * from "+request.getAttribute("tableName").toString();

            result = getResult(DbUtil.run(request, sql, jndi, loadParams));

           List datacolumninfo= getcolumnconinfo(jndi);

            if (result instanceof ResultSet) {
                resultSet = (ResultSet) result;// ResultSet在请求结束后自动关闭
            } else {
                String text = StringUtil.concat(
                        "{\"total\":1,\"metaData\":{\"fields\":[{\"name\":\"result\",\"type\":\"string\"}]},\"columns\":[{\"xtype\":\"rownumberer\",\"width\":40},{\"dataIndex\":\"result\",flex:1,\"text\":\"result\"}],\"rows\":[{\"result\":",
                        result == null ? "null" : StringUtil.quote(result.toString()), "}],\"elapsed\":",
                        Long.toString(System.currentTimeMillis() - startTime), "}");
                if (directOutput) {
                    WebUtil.send(response, text);
                    return null;
                } else
                    return text;
            }
            if (!StringUtil.isEmpty(totalSql)) {
                totalResult = getResult(DbUtil.run(request, totalSql, jndi, totalLoadParams));
                if (totalResult == null)
                    throw new NullPointerException("No value in the totalSql.");
                if (totalResult instanceof ResultSet) {
                    totalResultSet = (ResultSet) totalResult;
                    if (totalResultSet.next()) {
                        // 比使用totalResultSet.getLong更安全和通用
                        totalCount = Long.parseLong(totalResultSet.getString(1));
                    } else
                        throw new NullPointerException("Empty total ResultSet.");
                } else
                    totalCount = Long.parseLong(totalResult.toString());
            }
            dp = new DataAutoGenProvider();
            dp.startTime = startTime;
            dp.request = request;
            dp.response = response;
            dp.resultSet = resultSet;
            dp.fields = gs("fields");
            dp.fieldsTag = gs("fieldsTag");
            dp.keyDefines = gs("keyDefines");
            dp.totalCount = totalCount;
            dp.createColumns = gb("createColumns", true);
            if (gb("autoPage", true)) {
                dp.beginIndex = beginIndex;
                dp.endIndex = endIndex;
            }
            if (!limitRecords.isEmpty())
                dp.limitRecords = Integer.parseInt(limitRecords);
            if (!limitExportRecords.isEmpty())
                dp.limitExportRecords = Integer.parseInt(limitExportRecords);
            dp.tag = gs("tag");
            dp.type = type;
            dictTableNames = gs("dictTableNames");
            dp.createKeyValues = gb("createKeyValues", false);
            if (dictTableNames.isEmpty())
                dp.dictTableNames = null;
            else
                dp.dictTableNames = StringUtil.split(dictTableNames, ',', true);
            dp.dictFieldsMap = gs("dictFieldsMap");
            if (directOutput) {
                dp.output(datacolumninfo);
                return null;
            } else
                return dp.getScript(datacolumninfo);
        } finally {
            if (resultSet != null)
                resultSet.close();
            if (totalResultSet != null)
                totalResultSet.close();
        }
    }

    /**
     * 获取Query运行返回的ResultSet或影响记录数；如果存在输出参数，则尝试获取名称为
     * result的输出参数否则返回运行Query返回的值（结果集或影响记录数）。
     *
     * @param
     * @return 获取的结果集或影响记录数。
     */
    private Object getResult(Object result) {
        if (result instanceof HashMap<?, ?>) {
            HashMap<?, ?> map = (HashMap<?, ?>) result;
            // 设置输出参数值
            Set<?> es = map.entrySet();
            Entry<?, ?> entry;
            String name, itemId = StringUtil.select(gs("itemId"));
            for (Object e : es) {
                entry = (Entry<?, ?>) e;
                name = (String) entry.getKey();
                // 在hashmap中返回值名称为return
                if (name.equals("return")) {
                    if (!itemId.isEmpty())
                        name = itemId;
                } else {
                    if (!itemId.isEmpty())
                        name = StringUtil.concat(itemId, ".", name);
                }
                request.setAttribute(name, entry.getValue());
            }
            Object val = map.get(StringUtil.select(gs("resultName"), "result"));
            if (val == null)
                return map.get("return");
            else
                return val;
        } else
            return result;
    }

    /**
     * 设置sql.orderBy和sql.orderFields变量，以方便使用前端参数进行排序。仅适用于type为array。
     *
     * @throws Exception 设置过程发生异常。
     */
    private void setOrderVars() throws Exception {
        String sort = request.getParameter("sort");

        if (StringUtil.isEmpty(sort) || request.getAttribute("sql.orderBy") != null)
            return;
        JSONArray ja = new JSONArray(sort);
        int i, j = ja.length();
        if (j > 0) {
            JSONObject jo;
            StringBuilder exp = new StringBuilder();
            String property, defaultPrefix, prefix;
            JSONObject orderJo;
            String orderFields = gs("orderFields");

            if (StringUtil.isEmpty(orderFields)) {
                orderJo = null;
                defaultPrefix = null;
            } else {
                orderJo = new JSONObject(orderFields);
                defaultPrefix = orderJo.optString("default", null);
            }
            for (i = 0; i < j; i++) {
                jo = ja.getJSONObject(i);
                if (i > 0)
                    exp.append(',');
                property = jo.getString("property");
                // 检查名称合法性，防止被SQL注入
                if (!StringUtil.checkName(property)) {
                    throw new IllegalArgumentException("Invalid name \"" + property + "\".");
                }
                if (orderJo != null) {
                    if (orderJo.has(property)) {
                        prefix = orderJo.optString(property);
                        if (!prefix.isEmpty()) {
                            exp.append(prefix);
                            exp.append('.');
                        }
                    } else if (defaultPrefix != null) {
                        exp.append(defaultPrefix);
                        exp.append('.');
                    }
                }
                exp.append(property);
                if (StringUtil.isSame(jo.optString("direction"), "desc"))
                    exp.append(" desc");
            }
            request.setAttribute("sql.orderBy", " order by " + exp);
            // sql.orderFields前置","以方便使用，如：order by field{#sql.orderFields#}
            request.setAttribute("sql.orderFields", "," + exp);
        }
    }
}