/*
 * Copyright 2006-2018 The Apache Software Foundation.
 *
 * 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 org.apache.jdo.exectck;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * Utility class to load SQL files via JDBC.
 *
 * <p>The class expects a comment on a single line having a connect statement defining url, user and
 * password to connect to the database e.g. -- connect 'jdbc:derby:jdotckdb;create=true' user
 * 'tckuser' password 'tckuser';
 */
public class SQLFileLoader {

  // the reader for the sql file
  private Reader reader;
  // holds the next character that is just read from the reader
  private int nextChar;
  // holds the current SQL statement
  private StringBuilder currentStmt = new StringBuilder();
  // flag indicating whether a SQL string literal is processed
  private boolean scanStringLiteral = false;
  // the list of SQL statements
  private List<String> statements = new ArrayList<>();
  // the JDBC connection url
  private String connect;
  // the JDBC connection user
  private String user;
  // the JDBC connection password
  private String password;

  /**
   * Constructor. Reads the SQL statements from the specified file. The internal state of the class
   * is updated with the contents of the file and may be accessed using the getter methods (see
   * below).
   *
   * @param filename the name of the sql to be loaded
   * @throws IOException If an I/O error occurs
   */
  public SQLFileLoader(String filename) throws IOException {
    try (Reader r = new BufferedReader(new FileReader(filename))) {
      // init reader instance variable
      this.reader = r;
      // initialize nextChar with the first character from the stream
      this.nextChar = this.reader.read();

      int currentChar = next();
      // read characters from the stream
      while (currentChar != -1) {
        accept(currentChar);
        currentChar = next();
      }
      this.reader = null;
    }
  }

  /**
   * Returns the list of SQL statements processed by this SQLFileLoader.
   *
   * @return list of SQL statements
   */
  public List<String> getStatements() {
    return this.statements;
  }

  /**
   * Returns the JDBC connection URL.
   *
   * @return the JDBC connection URL
   */
  public String getConnect() {
    return this.connect;
  }

  /**
   * Returns the JDBC connection user.
   *
   * @return the JDBC connection user.
   */
  public String getUser() {
    return this.user;
  }

  /**
   * Returns the JDBC connection password.
   *
   * @return the JDBC connection password
   */
  public String getPassword() {
    return this.password;
  }

  /**
   * Checks the specified character whether it terminates a SQL Statement. If so the current SQL
   * statement is added to the list of processed SQL statements and a new SQL statement is
   * initialized. Otherwise the method appends the specified character to the current SQL statement.
   *
   * @param value character to be checked
   */
  private void accept(int value) {
    if (value == ';' && !this.scanStringLiteral) {
      // found statement end
      statements.add(currentStmt.toString());
      currentStmt = new StringBuilder();
    } else {
      currentStmt.append((char) value);
    }
  }

  /**
   * Returns the next character from the input that is not part of a comment. That means single line
   * comments and multi line comments are skipped. The method is able to handle SQL String literals.
   *
   * @return the next non comment character
   * @throws IOException If an I/O error occurs
   */
  private int next() throws IOException {
    int result = this.nextChar;
    switch (this.nextChar) {
      case '\'':
        this.scanStringLiteral = !this.scanStringLiteral;
        this.nextChar = this.reader.read();
        break;
      case '/':
        if (!this.scanStringLiteral) {
          int next = this.reader.read();
          if (next == '*') {
            this.nextChar = this.reader.read();
            skipToEndOfMLComment();
            skipWhitespace();
            return next();
          } else {
            this.nextChar = next;
          }
        } else {
          this.nextChar = this.reader.read();
        }
        break;
      case '-':
        if (!this.scanStringLiteral) {
          int next = this.reader.read();
          if (next == '-') {
            this.nextChar = reader.read();
            handleSingleLineComment();
            skipWhitespace();
            return next();
          } else {
            this.nextChar = next;
          }
        } else {
          this.nextChar = this.reader.read();
        }
        break;
      case ' ':
      case '\t':
      case '\n':
      case '\r':
        if (!this.scanStringLiteral) {
          skipWhitespace();
          result = ' ';
        } else {
          this.nextChar = this.reader.read();
        }
        break;
      default:
        this.nextChar = this.reader.read();
        break;
    }
    return result;
  }

  /**
   * Skips a single line comment. That means any character from -- to the end of the line are
   * akipped.
   *
   * @throws IOException If an I/O error occurs
   */
  private void handleSingleLineComment() throws IOException {
    Optional<String> optConnect = readIdentFollowedByLiteral("connect");
    optConnect.ifPresent(x -> this.connect = x);
    Optional<String> optUser = readIdentFollowedByLiteral("user");
    optUser.ifPresent(x -> this.user = x);
    Optional<String> optPassword = readIdentFollowedByLiteral("password");
    optPassword.ifPresent(x -> this.password = x);
    skipToEOL();
  }

  /**
   * Tries to read an Java identifier with the expected name followed by a SQL string literal.
   *
   * @param expected the expected Java identifier
   * @return an Optional with the text of SQL String literal if present; otherwise an empty Optional
   * @throws IOException If an I/O error occurs
   */
  private Optional<String> readIdentFollowedByLiteral(String expected) throws IOException {
    Optional<String> optIdent = readIdentifier();
    if (optIdent.isPresent()) {
      String ident = optIdent.get();
      if (ident.equalsIgnoreCase(expected)) {
        Optional<String> optLiteral = readSQLStringLiteral();
        if (optLiteral.isPresent()) {
          return optLiteral;
        }
      }
    }
    return Optional.empty();
  }

  /**
   * Tries to read a Java identifier.
   *
   * @return an Optional with the text of the identifier if present; otherwise an empty Optional
   * @throws IOException If an I/O error occurs
   */
  private Optional<String> readIdentifier() throws IOException {
    skipBlanksAndTabs();
    if (Character.isJavaIdentifierStart(this.nextChar)) {
      StringBuilder ident = new StringBuilder();
      ident.append((char) this.nextChar);
      this.nextChar = this.reader.read();
      while (Character.isJavaIdentifierPart(this.nextChar)) {
        ident.append((char) this.nextChar);
        this.nextChar = reader.read();
      }
      return Optional.of(ident.toString());
    }
    return Optional.empty();
  }

  /**
   * Tries to read a SQL String literal.
   *
   * @return an Optional with the text of the SQL String literal if present; otherwise an empty
   *     Optional
   * @throws IOException If an I/O error occurs
   */
  private Optional<String> readSQLStringLiteral() throws IOException {
    skipBlanksAndTabs();
    if (this.nextChar == '\'') {
      StringBuilder literal = new StringBuilder();
      this.nextChar = this.reader.read();
      while (this.nextChar != -1) {
        // possible end of SQL String literal
        if (this.nextChar == '\'') {
          this.nextChar = this.reader.read();
          // are there two single quotes?
          if (this.nextChar == '\'') {
            // yes -> append one ' and continue
            literal.append('\'');
          } else {
            // found end of literal
            break;
          }
        } else {
          literal.append((char) this.nextChar);
          this.nextChar = this.reader.read();
        }
      }
      return Optional.of(literal.toString());
    }
    return Optional.empty();
  }

  /**
   * Skip any whitespace characters. The variable nextChar holds the first non whitespace char.
   *
   * @throws IOException If an I/O error occurs
   */
  private void skipWhitespace() throws IOException {
    while (Character.isWhitespace(this.nextChar)) {
      this.nextChar = this.reader.read();
    }
  }

  /**
   * Skips any blank and tab characters. The variable nextChar holds the first non blank or non tab
   * char.
   *
   * @throws IOException If an I/O error occurs
   */
  private void skipBlanksAndTabs() throws IOException {
    while (this.nextChar == ' ' || this.nextChar == '\t') {
      this.nextChar = this.reader.read();
    }
  }

  /**
   * Skips to the end of the current line. The newline char is consumed. The variable nextChar holds
   * the first char of the next line.
   *
   * @throws IOException If an I/O error occurs
   */
  private void skipToEOL() throws IOException {
    while (this.nextChar != -1) {
      if (this.nextChar == '\n') {
        break;
      }
      this.nextChar = this.reader.read();
    }
    this.nextChar = this.reader.read();
  }

  /**
   * Skips to the end of a multi line comment. Any characters up to * followed by / are consumed.
   * The variable nextChar holds the first char after the comment.
   *
   * @throws IOException If an I/O error occurs
   */
  private void skipToEndOfMLComment() throws IOException {
    while (this.nextChar != -1) {
      if (this.nextChar == '*') {
        this.nextChar = this.reader.read();
        if (this.nextChar == '/') {
          break;
        }
      }
      this.nextChar = this.reader.read();
    }
    this.nextChar = this.reader.read();
  }

  /**
   * main method For testing; prints the internal state to System.out.
   *
   * @param args command line arguments
   */
  public static void main(String[] args) {
    for (String arg : args) {
      try {
        SQLFileLoader loader = new SQLFileLoader(arg);
        List<String> stmts = loader.getStatements();
        System.out.println(loader.getConnect());
        System.out.println(loader.getUser());
        System.out.println(loader.getPassword());
        stmts.forEach(System.out::println);
      } catch (IOException ex) {
        System.err.println(ex);
      }
    }
  }
}
