// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.googlesource.gerrit.plugins.verifystatus;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.gerrit.common.Version;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.verifystatus.server.CiDb;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/** Simple interactive SQL query tool. */
@RequiresCapability(AccessCiDatabaseCapability.ID)
public class VerifyStatusQueryShell {
  public interface Factory {
    VerifyStatusQueryShell create(@Assisted InputStream in, @Assisted OutputStream out);
  }

  public static enum OutputFormat {
    PRETTY,
    JSON,
    JSON_SINGLE
  }

  private final BufferedReader in;
  private final PrintWriter out;
  private final SchemaFactory<CiDb> dbFactory;
  private OutputFormat outputFormat = OutputFormat.PRETTY;

  private CiDb db;
  private Connection connection;
  private Statement statement;

  @Inject
  VerifyStatusQueryShell(
      SchemaFactory<CiDb> dbFactory, @Assisted InputStream in, @Assisted OutputStream out) {
    this.dbFactory = dbFactory;
    this.in = new BufferedReader(new InputStreamReader(in, UTF_8));
    this.out = new PrintWriter(new OutputStreamWriter(out, UTF_8));
  }

  public void setOutputFormat(OutputFormat fmt) {
    outputFormat = fmt;
  }

  public void run() {
    try {
      db = dbFactory.open();
      try {
        connection = ((JdbcSchema) db).getConnection();
        connection.setAutoCommit(true);

        statement = connection.createStatement();
        try {
          showBanner();
          readEvalPrintLoop();
        } finally {
          statement.close();
          statement = null;
        }
      } finally {
        db.close();
        db = null;
      }
    } catch (OrmException | SQLException err) {
      out.println("fatal: Cannot open connection: " + err.getMessage());
    } finally {
      out.flush();
    }
  }

  public void execute(String query) {
    try {
      db = dbFactory.open();
      try {
        connection = ((JdbcSchema) db).getConnection();
        connection.setAutoCommit(true);

        statement = connection.createStatement();
        try {
          executeStatement(query);
        } finally {
          statement.close();
          statement = null;
        }
      } finally {
        db.close();
        db = null;
      }
    } catch (OrmException | SQLException err) {
      out.println("fatal: Cannot open connection: " + err.getMessage());
    } finally {
      out.flush();
    }
  }

  private void readEvalPrintLoop() {
    final StringBuilder buffer = new StringBuilder();
    boolean executed = false;
    for (; ; ) {
      if (outputFormat == OutputFormat.PRETTY) {
        print(buffer.length() == 0 || executed ? "gerrit> " : "     -> ");
      }
      String line = readLine();
      if (line == null) {
        return;
      }

      if (line.startsWith("\\")) {
        // Shell command, check the various cases we recognize
        //
        line = line.substring(1);
        if (line.equals("h") || line.equals("?")) {
          showHelp();

        } else if (line.equals("q")) {
          if (outputFormat == OutputFormat.PRETTY) {
            println("Bye");
          }
          return;

        } else if (line.equals("r")) {
          buffer.setLength(0);
          executed = false;

        } else if (line.equals("p")) {
          println(buffer.toString());

        } else if (line.equals("g")) {
          if (buffer.length() > 0) {
            executeStatement(buffer.toString());
            executed = true;
          }

        } else if (line.equals("d")) {
          listTables();

        } else if (line.startsWith("d ")) {
          showTable(line.substring(2).trim());

        } else {
          final String msg = "'\\" + line + "' not supported";
          switch (outputFormat) {
            case JSON_SINGLE:
            case JSON:
              {
                final JsonObject err = new JsonObject();
                err.addProperty("type", "error");
                err.addProperty("message", msg);
                println(err.toString());
                break;
              }
            case PRETTY:
            default:
              println("ERROR: " + msg);
              println("");
              showHelp();
              break;
          }
        }
        continue;
      }

      if (executed) {
        buffer.setLength(0);
        executed = false;
      }
      if (buffer.length() > 0) {
        buffer.append('\n');
      }
      buffer.append(line);

      if (buffer.length() > 0 && buffer.charAt(buffer.length() - 1) == ';') {
        executeStatement(buffer.toString());
        executed = true;
      }
    }
  }

  private void listTables() {
    final DatabaseMetaData meta;
    try {
      meta = connection.getMetaData();
    } catch (SQLException e) {
      error(e);
      return;
    }

    final String[] types = {"TABLE", "VIEW"};
    try (ResultSet rs = meta.getTables(null, null, null, types)) {
      if (outputFormat == OutputFormat.PRETTY) {
        println("                     List of relations");
      }
      showResultSet(
          rs,
          false,
          0,
          Identity.create(rs, "TABLE_SCHEM"),
          Identity.create(rs, "TABLE_NAME"),
          Identity.create(rs, "TABLE_TYPE"));
    } catch (SQLException e) {
      error(e);
    }

    println("");
  }

  private void showTable(String tableName) {
    final DatabaseMetaData meta;
    try {
      meta = connection.getMetaData();

      if (meta.storesUpperCaseIdentifiers()) {
        tableName = tableName.toUpperCase();
      } else if (meta.storesLowerCaseIdentifiers()) {
        tableName = tableName.toLowerCase();
      }
    } catch (SQLException e) {
      error(e);
      return;
    }

    try (ResultSet rs = meta.getColumns(null, null, tableName, null)) {
      if (!rs.next()) {
        throw new SQLException("Table " + tableName + " not found");
      }

      if (outputFormat == OutputFormat.PRETTY) {
        println("                     Table " + tableName);
      }
      showResultSet(
          rs,
          true,
          0,
          Identity.create(rs, "COLUMN_NAME"),
          new Function("TYPE") {
            @Override
            String apply(final ResultSet rs) throws SQLException {
              String type = rs.getString("TYPE_NAME");
              switch (rs.getInt("DATA_TYPE")) {
                case java.sql.Types.CHAR:
                case java.sql.Types.VARCHAR:
                  type += "(" + rs.getInt("COLUMN_SIZE") + ")";
                  break;
              }

              String def = rs.getString("COLUMN_DEF");
              if (def != null && !def.isEmpty()) {
                type += " DEFAULT " + def;
              }

              int nullable = rs.getInt("NULLABLE");
              if (nullable == DatabaseMetaData.columnNoNulls) {
                type += " NOT NULL";
              }
              return type;
            }
          });
    } catch (SQLException e) {
      error(e);
      return;
    }

    try (ResultSet rs = meta.getIndexInfo(null, null, tableName, false, true)) {
      Map<String, IndexInfo> indexes = new TreeMap<>();
      while (rs.next()) {
        final String indexName = rs.getString("INDEX_NAME");
        IndexInfo def = indexes.get(indexName);
        if (def == null) {
          def = new IndexInfo();
          def.name = indexName;
          indexes.put(indexName, def);
        }

        if (!rs.getBoolean("NON_UNIQUE")) {
          def.unique = true;
        }

        final int pos = rs.getInt("ORDINAL_POSITION");
        final String col = rs.getString("COLUMN_NAME");
        String desc = rs.getString("ASC_OR_DESC");
        if ("D".equals(desc)) {
          desc = " DESC";
        } else {
          desc = "";
        }
        def.addColumn(pos, col + desc);

        String filter = rs.getString("FILTER_CONDITION");
        if (filter != null && !filter.isEmpty()) {
          def.filter.append(filter);
        }
      }

      if (outputFormat == OutputFormat.PRETTY) {
        println("");
        println("Indexes on " + tableName + ":");
        for (IndexInfo def : indexes.values()) {
          println("  " + def);
        }
      }
    } catch (SQLException e) {
      error(e);
      return;
    }

    println("");
  }

  private void executeStatement(final String sql) {
    final long start = TimeUtil.nowMs();
    final boolean hasResultSet;
    try {
      hasResultSet = statement.execute(sql);
    } catch (SQLException e) {
      error(e);
      return;
    }

    try {
      if (hasResultSet) {
        try (ResultSet rs = statement.getResultSet()) {
          showResultSet(rs, false, start);
        }

      } else {
        final int updateCount = statement.getUpdateCount();
        final long ms = TimeUtil.nowMs() - start;
        switch (outputFormat) {
          case JSON_SINGLE:
          case JSON:
            {
              final JsonObject tail = new JsonObject();
              tail.addProperty("type", "update-stats");
              tail.addProperty("rowCount", updateCount);
              tail.addProperty("runTimeMilliseconds", ms);
              println(tail.toString());
              break;
            }

          case PRETTY:
          default:
            println("UPDATE " + updateCount + "; " + ms + " ms");
            break;
        }
      }
    } catch (SQLException e) {
      error(e);
    }
  }

  /**
   * Outputs a result set to stdout.
   *
   * @param rs ResultSet to show.
   * @param alreadyOnRow true if rs is already on the first row. false otherwise.
   * @param start Timestamp in milliseconds when executing the statement started. This timestamp is
   *     used to compute statistics about the statement. If no statistics should be shown, set it to
   *     0.
   * @param show Functions to map columns
   * @throws SQLException
   */
  private void showResultSet(final ResultSet rs, boolean alreadyOnRow, long start, Function... show)
      throws SQLException {
    switch (outputFormat) {
      case JSON_SINGLE:
      case JSON:
        showResultSetJson(rs, alreadyOnRow, start, show);
        break;
      case PRETTY:
      default:
        showResultSetPretty(rs, alreadyOnRow, start, show);
        break;
    }
  }

  /**
   * Outputs a result set to stdout in Json format.
   *
   * @param rs ResultSet to show.
   * @param alreadyOnRow true if rs is already on the first row. false otherwise.
   * @param start Timestamp in milliseconds when executing the statement started. This timestamp is
   *     used to compute statistics about the statement. If no statistics should be shown, set it to
   *     0.
   * @param show Functions to map columns
   * @throws SQLException
   */
  private void showResultSetJson(
      final ResultSet rs, boolean alreadyOnRow, long start, Function... show) throws SQLException {
    JsonArray collector = new JsonArray();
    final ResultSetMetaData meta = rs.getMetaData();
    final Function[] columnMap;
    if (show != null && 0 < show.length) {
      columnMap = show;

    } else {
      final int colCnt = meta.getColumnCount();
      columnMap = new Function[colCnt];
      for (int colId = 0; colId < colCnt; colId++) {
        final int p = colId + 1;
        final String name = meta.getColumnLabel(p);
        columnMap[colId] = new Identity(p, name);
      }
    }

    int rowCnt = 0;
    while (alreadyOnRow || rs.next()) {
      final JsonObject row = new JsonObject();
      final JsonObject cols = new JsonObject();
      for (Function function : columnMap) {
        String v = function.apply(rs);
        if (v == null) {
          continue;
        }
        cols.addProperty(function.name.toLowerCase(), v);
      }
      row.addProperty("type", "row");
      row.add("columns", cols);
      switch (outputFormat) {
        case JSON:
          println(row.toString());
          break;
        case JSON_SINGLE:
          collector.add(row);
          break;
        case PRETTY:
        default:
          final JsonObject obj = new JsonObject();
          obj.addProperty("type", "error");
          obj.addProperty("message", "Unsupported Json variant");
          println(obj.toString());
          return;
      }
      alreadyOnRow = false;
      rowCnt++;
    }

    JsonObject tail = null;
    if (start != 0) {
      tail = new JsonObject();
      tail.addProperty("type", "query-stats");
      tail.addProperty("rowCount", rowCnt);
      final long ms = TimeUtil.nowMs() - start;
      tail.addProperty("runTimeMilliseconds", ms);
    }

    switch (outputFormat) {
      case JSON:
        if (tail != null) {
          println(tail.toString());
        }
        break;
      case JSON_SINGLE:
        if (tail != null) {
          collector.add(tail);
        }
        println(collector.toString());
        break;
      case PRETTY:
      default:
        final JsonObject obj = new JsonObject();
        obj.addProperty("type", "error");
        obj.addProperty("message", "Unsupported Json variant");
        println(obj.toString());
    }
  }

  /**
   * Outputs a result set to stdout in plain text format.
   *
   * @param rs ResultSet to show.
   * @param alreadyOnRow true if rs is already on the first row. false otherwise.
   * @param start Timestamp in milliseconds when executing the statement started. This timestamp is
   *     used to compute statistics about the statement. If no statistics should be shown, set it to
   *     0.
   * @param show Functions to map columns
   * @throws SQLException
   */
  private void showResultSetPretty(
      final ResultSet rs, boolean alreadyOnRow, long start, Function... show) throws SQLException {
    final ResultSetMetaData meta = rs.getMetaData();

    final Function[] columnMap;
    if (show != null && 0 < show.length) {
      columnMap = show;

    } else {
      final int colCnt = meta.getColumnCount();
      columnMap = new Function[colCnt];
      for (int colId = 0; colId < colCnt; colId++) {
        final int p = colId + 1;
        final String name = meta.getColumnLabel(p);
        columnMap[colId] = new Identity(p, name);
      }
    }

    final int colCnt = columnMap.length;
    final int[] widths = new int[colCnt];
    for (int c = 0; c < colCnt; c++) {
      widths[c] = columnMap[c].name.length();
    }

    final List<String[]> rows = new ArrayList<>();
    while (alreadyOnRow || rs.next()) {
      final String[] row = new String[columnMap.length];
      for (int c = 0; c < colCnt; c++) {
        row[c] = columnMap[c].apply(rs);
        if (row[c] == null) {
          row[c] = "NULL";
        }
        widths[c] = Math.max(widths[c], row[c].length());
      }
      rows.add(row);
      alreadyOnRow = false;
    }

    final StringBuilder b = new StringBuilder();
    for (int c = 0; c < colCnt; c++) {
      if (0 < c) {
        b.append(" | ");
      }

      String n = columnMap[c].name;
      if (widths[c] < n.length()) {
        n = n.substring(0, widths[c]);
      }
      b.append(n);

      if (c < colCnt - 1) {
        for (int pad = n.length(); pad < widths[c]; pad++) {
          b.append(' ');
        }
      }
    }
    println(" " + b.toString());

    b.setLength(0);
    for (int c = 0; c < colCnt; c++) {
      if (0 < c) {
        b.append("-+-");
      }
      for (int pad = 0; pad < widths[c]; pad++) {
        b.append('-');
      }
    }
    println(" " + b.toString());

    boolean dataTruncated = false;
    for (String[] row : rows) {
      b.setLength(0);
      b.append(' ');

      for (int c = 0; c < colCnt; c++) {
        final int max = widths[c];
        if (0 < c) {
          b.append(" | ");
        }

        String s = row[c];
        if (1 < colCnt && max < s.length()) {
          s = s.substring(0, max);
          dataTruncated = true;
        }
        b.append(s);

        if (c < colCnt - 1) {
          for (int pad = s.length(); pad < max; pad++) {
            b.append(' ');
          }
        }
      }
      println(b.toString());
    }

    if (dataTruncated) {
      warning("some column data was truncated");
    }

    if (start != 0) {
      final int rowCount = rows.size();
      final long ms = TimeUtil.nowMs() - start;
      println("(" + rowCount + (rowCount == 1 ? " row" : " rows") + "; " + ms + " ms)");
    }
  }

  private void warning(final String msg) {
    switch (outputFormat) {
      case JSON_SINGLE:
      case JSON:
        {
          final JsonObject obj = new JsonObject();
          obj.addProperty("type", "warning");
          obj.addProperty("message", msg);
          println(obj.toString());
          break;
        }

      case PRETTY:
      default:
        println("WARNING: " + msg);
        break;
    }
  }

  private void error(final SQLException err) {
    switch (outputFormat) {
      case JSON_SINGLE:
      case JSON:
        {
          final JsonObject obj = new JsonObject();
          obj.addProperty("type", "error");
          obj.addProperty("message", err.getMessage());
          println(obj.toString());
          break;
        }

      case PRETTY:
      default:
        println("ERROR: " + err.getMessage());
        break;
    }
  }

  private void print(String s) {
    out.print(s);
    out.flush();
  }

  private void println(String s) {
    out.print(s);
    out.print('\n');
    out.flush();
  }

  private String readLine() {
    try {
      return in.readLine();
    } catch (IOException e) {
      return null;
    }
  }

  private void showBanner() {
    if (outputFormat == OutputFormat.PRETTY) {
      println("Welcome to Gerrit Code Review " + Version.getVersion());
      try {
        print("(");
        print(connection.getMetaData().getDatabaseProductName());
        print(" ");
        print(connection.getMetaData().getDatabaseProductVersion());
        println(")");
      } catch (SQLException err) {
        error(err);
      }
      println("");
      println("Type '\\h' for help.  Type '\\r' to clear the buffer.");
      println("");
    }
  }

  private void showHelp() {
    final StringBuilder help = new StringBuilder();
    help.append("General\n");
    help.append("  \\q        quit\n");

    help.append("\n");
    help.append("Query Buffer\n");
    help.append("  \\g        execute the query buffer\n");
    help.append("  \\p        display the current buffer\n");
    help.append("  \\r        clear the query buffer\n");

    help.append("\n");
    help.append("Informational\n");
    help.append("  \\d        list all tables\n");
    help.append("  \\d NAME   describe table\n");

    help.append("\n");
    print(help.toString());
  }

  private abstract static class Function {
    final String name;

    Function(final String name) {
      this.name = name;
    }

    abstract String apply(ResultSet rs) throws SQLException;
  }

  private static class Identity extends Function {
    static Identity create(final ResultSet rs, final String name) throws SQLException {
      return new Identity(rs.findColumn(name), name);
    }

    final int colId;

    Identity(final int colId, final String name) {
      super(name);
      this.colId = colId;
    }

    @Override
    String apply(final ResultSet rs) throws SQLException {
      return rs.getString(colId);
    }
  }

  private static class IndexInfo {
    String name;
    boolean unique;
    final Map<Integer, String> columns = new TreeMap<>();
    final StringBuilder filter = new StringBuilder();

    void addColumn(int pos, String column) {
      columns.put(Integer.valueOf(pos), column);
    }

    @Override
    public String toString() {
      final StringBuilder r = new StringBuilder();
      r.append(name);
      if (unique) {
        r.append(" UNIQUE");
      }
      r.append(" (");
      boolean first = true;
      for (String c : columns.values()) {
        if (!first) {
          r.append(", ");
        }
        r.append(c);
        first = false;
      }
      r.append(")");
      if (filter.length() > 0) {
        r.append(" WHERE ");
        r.append(filter);
      }
      return r.toString();
    }
  }
}
