package com.wecise.odb.test;

import com.wecise.odb.jdbc.ODBCommandProtocol;
import com.wecise.odb.table.SimpleConsoleTable;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.commands.ProtocolCommand;
import redis.clients.jedis.util.SafeEncoder;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class Test {

    public static void main(String[] args) throws Exception {
//        Jedis jc = new Jedis("47.92.151.165", 11001);
//        String pong = jc.ping();
//        System.out.println(pong);
//        Object o = jc.sendCommand(ODBCommandProtocol.MQL.mql, "select id from /matrix/devops/ limit 1", "meta");
//        String s = new String((byte[]) o);
//        System.out.println(s);

//        Set<HostAndPort> jedisClusterNodes = new HashSet<>();
//        //Jedis Cluster will attempt to discover cluster nodes automatically
//        jedisClusterNodes.add(new HostAndPort("47.92.151.165", 11001));
//        JedisCluster jc = new JedisCluster(jedisClusterNodes);
//        jc.sendCommand("mql", ODBCommandProtocol.MQL.mql, "select id from /matrix/devops/ limit 1");

//        System.exit(0);

        test(false);
        System.out.println("JDBC Test");

        Class.forName("com.wecise.odb.jdbc.ODBDriver");
//        Connection conn = DriverManager.getConnection("jdbc:wecise:omdb://192.168.31.221,127.0.0.1:9062/matrix");
//        Connection conn = DriverManager.getConnection("jdbc:wecise:omdb://47.92.151.165:9062/matrix");
        Connection conn = DriverManager.getConnection("jdbc:wecise:omdb://47.92.151.165:11001/matrix");

        System.out.println("Meta info:");
        printMetaData(conn.getMetaData());

        System.out.println("Wait...");
        Thread.sleep(2000);
        System.out.println("Continue....");

        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("select id, host, config, depot from /matrix/system/hostinfo limit 100");
        printResult(rs);
        rs.close();
        stmt.close();

        Statement stmt2 = conn.createStatement();
        ResultSet rs2 = stmt2.executeQuery("select id, name, host as h, vtime, day, severity, tags from /matrix/devops/alert limit 2");
        printResult(rs2);
        rs2.close();
        stmt2.close();

        // Need odb server support
        PreparedStatement pstmt = conn.prepareStatement("select id, host from /matrix/devops/alert where host = ? limit 1");
        pstmt.setString(1, "wecise");
        ResultSet rs3 = pstmt.executeQuery();
        printResult(rs3);
        rs3.close();
        pstmt.close();

        Statement stmt4 = conn.createStatement();
        ResultSet rs4 = stmt4.executeQuery("match ('biz:查账系统')-[*]->() until 'router:router1','router:router2'");
        printResult(rs4);
        rs4.close();
        stmt4.close();

        conn.close();
    }

    private static void printMetaData(DatabaseMetaData meta) throws Exception {
        // https://blog.csdn.net/russle/article/details/53182848
        // https://aisia.moe/java6api-cn/java/sql/DatabaseMetaData.html
        ResultSet schemas = meta.getSchemas();
        String schem = null;
        String catalog = null;
        while (schemas.next()) {
            schem = schemas.getString(1);
            catalog = schemas.getString(2);
            System.out.println("    TABLE_SCHEM: " + schemas.getString(1));
            System.out.println("    TABLE_CATALOG: " + schemas.getString(2));
        }

        String[] type = new String[2];
        type[0] = "TABLE";
        type[1] = "VIEW";
        // _ = all table, ST_ = prefix ST table
        // % = all table, ST% = prefix ST table
        System.out.println("    Tables:");
        ResultSet tables = meta.getTables(catalog, schem, "%", type);
        String tname = null;
        while (tables.next()) {
            //TABLE_CAT
            String tableCatalog = tables.getString(1);
            //TABLE_SCHEM
            String tableSchema = tables.getString(2);
            //TABLE_NAME
            String tableName = tables.getString(3);
            //TABLE_TYPE
            String tableType = tables.getString(4);
            //REMARKS
            String remarks = tables.getString(5);
            //TYPE_CAT
            String typeCatalog = tables.getString(6);

            System.out.println("        tableCatalog:" + tableCatalog + ", tableSchema:" + tableSchema +", tableName:" + tableName
                    + ", tableType:" + tableType
                    + ", typeCatalog:" + typeCatalog
                    + ", remarks:" + remarks);

            if ("/matrix/devops/alert".equals(tableName)) {
                tname = tableName;
            }
        }

        System.out.println("    Table " + tname + " columns:");
        ResultSet columns = meta.getColumns(catalog, schem, tname, "%");
        while (columns.next()) {
            String columnName = columns.getString(4);
            int dataType = columns.getInt(5);
            String typeName = columns.getString(6);
            int columnSize = columns.getInt(7);
            System.out.println("        columnName:" + columnName + ", typeName:" + typeName +", columnSize:" + columnSize + ", dataType:" + dataType);
        }
    }

    private static void printResult(ResultSet rs) throws Exception {
        ResultSetMetaData meta = rs.getMetaData();
        ArrayList<Object> data = new ArrayList<>();
        Object[] header = new Object[meta.getColumnCount() + 1];
        header[0] = "No";
        for (int i = 1; i < header.length; i ++) {
            header[i] = meta.getColumnLabel(i);
        }
        data.add(header);
        while (rs.next()) {
            Object[] row = new Object[header.length];
            row[0] = rs.getRow();
            for (int i = 1; i <= meta.getColumnCount(); i++) {
                Object val;
                switch (meta.getColumnType(i)) {
                    case Types.TIMESTAMP:
                        val = rs.getTimestamp(i).getTime();
                        break;
                    case Types.DATE:
                        val = rs.getDate(i);
                        break;
                    case Types.JAVA_OBJECT:
                        val = rs.getObject(i);
                        break;
                    default: // default varchar
                        val = rs.getString(i);
                        break;
                }
                row[i] = val;
            }
            data.add(row);
        }

        SimpleConsoleTable<Object> consoleTable = new SimpleConsoleTable<>(data.toArray());
        System.out.println(consoleTable.toString());
    }

    private static void test(boolean exit) {
//        String s = "select * from test where age = ? and id = '\\'a?' and name = ? limit 1";
//        parseSql(s);

//        String[] a = new String[]{"a", "b", "c"};
//        ObjectPool pool = new ObjectPool(a);
//
//        Object v = pool.get();
//        System.out.println(v);
//        Thread.sleep(200);
//
//        Object v1 = pool.get();
//        System.out.println(v1);
//        Thread.sleep(200);
//
//        pool.release(v);
//        pool.release(v1);
//
//        Object v2 = pool.get();
//        System.out.println(v2);
//        Thread.sleep(500);
//        pool.release(v2);

        // 原数组， 原数组的开始位置， 目标数组， 目标数组的开始位置， 拷贝个数
//        byte[] b1 = new byte[3];
//        b1[0] = 'a';
//        b1[1] = 'b';
//        b1[2] = 'c';
//        byte[] b2 = new byte[3];
//        b2[0] = 'x';
//        b2[1] = 'y';
//        b2[2] = 'z';
//        byte[] b3 = Util.bytesMerger(b1, b2);
//        for (byte bt: b3) {
//            System.out.print(String.format("%c", bt));
//        }
//        System.out.println();
//
//        System.out.println(String.format("%c %c %c", b1[0], b1[1], b1[2]));
//        System.out.println(String.format("%c %c %c", b2[0], b2[1], b2[2]));
//        System.arraycopy(b2, 0, b1, 0, 2);
//        System.out.println(String.format("%c %c %c", b1[0], b1[1], b1[2]));
//
//        HashMap<String, String> meta = new HashMap<>();
//        meta.put("X-Accept-Body-Codec", "106");
//        HashMap<String, String> body = new HashMap<>();
//        body.put("keyspace", "matrix");
//        Message m = new Message("", 1, "/data/mql/execute", meta, 'j', new Gson().toJson(body));
//        System.out.println(new String(m.encode()));

        if (exit) {
            System.exit(0);
        }
    }

//    private static void parseSql(String sql) {
//        int num = 0;
//        char[] a = sql.toCharArray();
//        boolean ok = true;
//        boolean escape = false;
//        for (char c: a) {
//            if (!escape) {
//                if (c == '\\') {
//                    escape = true;
//                    continue;
//                }
//            } else {
//                escape = false;
//                continue;
//            }
//            if (c == '\'' || c == '"') {
//                ok = !ok;
//            }
//            if (ok && c == '?') {
//                num += 1;
//            }
//        }
//        System.out.println(num);
//    }
}
