/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you 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.calcite.avatica;

import org.apache.calcite.avatica.Meta.Signature;
import org.apache.calcite.avatica.remote.TypedValue;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

/**
 * Implementation of {@link java.sql.PreparedStatement}
 * for the Avatica engine.
 *
 * <p>This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs;
 * it is instantiated using {@link AvaticaFactory#newPreparedStatement}.</p>
 */
public abstract class AvaticaPreparedStatement
    extends AvaticaStatement
    implements PreparedStatement, ParameterMetaData {
  private final ResultSetMetaData resultSetMetaData;
  private Calendar calendar;
  protected final TypedValue[] slots;
  protected final List<List<TypedValue>> parameterValueBatch;

  /**
   * Creates an AvaticaPreparedStatement.
   *
   * @param connection Connection
   * @param h Statement handle
   * @param signature Result of preparing statement
   * @param resultSetType Result set type
   * @param resultSetConcurrency Result set concurrency
   * @param resultSetHoldability Result set holdability
   * @throws SQLException If fails due to underlying implementation reasons.
   */
  protected AvaticaPreparedStatement(AvaticaConnection connection,
      Meta.StatementHandle h,
      Meta.Signature signature,
      int resultSetType,
      int resultSetConcurrency,
      int resultSetHoldability) throws SQLException {
    super(connection, h, resultSetType, resultSetConcurrency,
        resultSetHoldability, signature);
    this.slots = new TypedValue[signature.parameters.size()];
    this.resultSetMetaData =
        connection.factory.newResultSetMetaData(this, signature);
    this.parameterValueBatch = new ArrayList<>();
  }

  @Override protected List<TypedValue> getParameterValues() {
    return Arrays.asList(slots);
  }

  /** Returns a copy of the current parameter values.
   * @return A copied list of the parameter values
   */
  protected List<TypedValue> copyParameterValues() {
    // For implementing batch update, we need to make a copy of slots, not just a thin reference
    // to it as as list. Otherwise, subsequent setFoo(..) calls will alter the underlying array
    // and modify our cached TypedValue list.
    List<TypedValue> copy = new ArrayList<>(slots.length);
    for (TypedValue value : slots) {
      copy.add(value);
    }
    return copy;
  }

  /** Returns a calendar in the connection's time zone, creating one the first
   * time this method is called.
   *
   * <p>Uses the calendar to offset date-time values when calling methods such
   * as {@link #setDate(int, Date)}.
   *
   * <p>A note on thread-safety. This method does not strictly need to be
   * {@code synchronized}, because JDBC does not promise thread safety if
   * different threads are accessing the same statement, or even different
   * objects within a particular connection.
   *
   * <p>The calendar returned is to be used only within this statement, and
   * JDBC only allows access to a statement from within one thread, so
   * therefore does not need to be synchronized when accessed.
   */
  protected synchronized Calendar getCalendar() {
    if (calendar == null) {
      calendar = Calendar.getInstance(connection.getTimeZone(), Locale.ROOT);
    }
    return calendar;
  }

  protected List<List<TypedValue>> getParameterValueBatch() {
    return this.parameterValueBatch;
  }

  // implement PreparedStatement

  public ResultSet executeQuery() throws SQLException {
    checkOpen();
    this.updateCount = -1;
    final Signature sig = getSignature();
    return getConnection().executeQueryInternal(this, sig, null,
        new QueryState(sig.sql), false);
  }

  public ParameterMetaData getParameterMetaData() throws SQLException {
    checkOpen();
    return this;
  }

  public final int executeUpdate() throws SQLException {
    return AvaticaUtils.toSaturatedInt(executeLargeUpdate());
  }

  public long executeLargeUpdate() throws SQLException {
    checkOpen();
    getConnection().executeQueryInternal(this, null, null,
        new QueryState(getSignature().sql), true);
    return updateCount;
  }

  public void setNull(int parameterIndex, int sqlType) throws SQLException {
    getSite(parameterIndex).setNull(sqlType);
  }

  public void setBoolean(int parameterIndex, boolean x) throws SQLException {
    getSite(parameterIndex).setBoolean(x);
  }

  public void setByte(int parameterIndex, byte x) throws SQLException {
    getSite(parameterIndex).setByte(x);
  }

  public void setShort(int parameterIndex, short x) throws SQLException {
    getSite(parameterIndex).setShort(x);
  }

  public void setInt(int parameterIndex, int x) throws SQLException {
    getSite(parameterIndex).setInt(x);
  }

  public void setLong(int parameterIndex, long x) throws SQLException {
    getSite(parameterIndex).setLong(x);
  }

  public void setFloat(int parameterIndex, float x) throws SQLException {
    getSite(parameterIndex).setFloat(x);
  }

  public void setDouble(int parameterIndex, double x) throws SQLException {
    getSite(parameterIndex).setDouble(x);
  }

  public void setBigDecimal(int parameterIndex, BigDecimal x)
      throws SQLException {
    getSite(parameterIndex).setBigDecimal(x);
  }

  public void setString(int parameterIndex, String x) throws SQLException {
    getSite(parameterIndex).setString(x);
  }

  public void setBytes(int parameterIndex, byte[] x) throws SQLException {
    getSite(parameterIndex).setBytes(x);
  }

  public void setAsciiStream(int parameterIndex, InputStream x, int length)
      throws SQLException {
    getSite(parameterIndex).setAsciiStream(x, length);
  }

  @SuppressWarnings("deprecation")
  public void setUnicodeStream(int parameterIndex, InputStream x, int length)
      throws SQLException {
    getSite(parameterIndex).setUnicodeStream(x, length);
  }

  public void setBinaryStream(int parameterIndex, InputStream x, int length)
      throws SQLException {
    getSite(parameterIndex).setBinaryStream(x, length);
  }

  public void clearParameters() throws SQLException {
    checkOpen();
    for (int i = 0; i < slots.length; i++) {
      slots[i] = null;
    }
  }

  public void setObject(int parameterIndex, Object x, int targetSqlType)
      throws SQLException {
    getSite(parameterIndex).setObject(x, targetSqlType);
  }

  public void setObject(int parameterIndex, Object x) throws SQLException {
    getSite(parameterIndex).setObject(x);
  }

  public boolean execute() throws SQLException {
    checkOpen();
    this.updateCount = -1;
    // We don't know if this is actually an update or a query, so call it a query so we pass the
    // Signature to the server.
    getConnection().executeQueryInternal(this, getSignature(), null,
        new QueryState(getSignature().sql), false);
    // Result set is null for DML or DDL.
    // Result set is closed if user cancelled the query.
    return openResultSet != null && !openResultSet.isClosed();
  }

  public void addBatch() throws SQLException {
    checkOpen();
    // Need to copy the parameterValues into a new list, not wrap the array in a list
    // as getParameterValues does.
    this.parameterValueBatch.add(copyParameterValues());
  }

  @Override public void clearBatch() throws SQLException {
    checkOpen();
    this.parameterValueBatch.clear();
  }

  @Override public int[] executeBatch() throws SQLException {
    return AvaticaUtils.toSaturatedInts(executeLargeBatch());
  }

  public long[] executeLargeBatch() throws SQLException {
    checkOpen();
    // Overriding the implementation in AvaticaStatement.
    try {
      return getConnection().executeBatchUpdateInternal(this);
    } finally {
      // If we failed to send this batch, that's a problem for the user to handle, not us.
      // Make sure we always clear the statements we collected to submit in one RPC.
      this.parameterValueBatch.clear();
    }
  }

  public void setCharacterStream(int parameterIndex, Reader reader, int length)
      throws SQLException {
    getSite(parameterIndex).setCharacterStream(reader, length);
  }

  public void setRef(int parameterIndex, Ref x) throws SQLException {
    getSite(parameterIndex).setRef(x);
  }

  public void setBlob(int parameterIndex, Blob x) throws SQLException {
    getSite(parameterIndex).setBlob(x);
  }

  public void setClob(int parameterIndex, Clob x) throws SQLException {
    getSite(parameterIndex).setClob(x);
  }

  public void setArray(int parameterIndex, Array x) throws SQLException {
    getSite(parameterIndex).setArray(x);
  }

  public ResultSetMetaData getMetaData() throws SQLException {
    checkOpen();
    return resultSetMetaData;
  }

  public void setDate(int parameterIndex, Date x, Calendar calendar)
      throws SQLException {
    getSite(parameterIndex).setDate(x, calendar);
  }

  public void setDate(int parameterIndex, Date x) throws SQLException {
    setDate(parameterIndex, x, getCalendar());
  }

  public void setTime(int parameterIndex, Time x, Calendar calendar)
      throws SQLException {
    getSite(parameterIndex).setTime(x, calendar);
  }

  public void setTime(int parameterIndex, Time x) throws SQLException {
    setTime(parameterIndex, x, getCalendar());
  }

  public void setTimestamp(int parameterIndex, Timestamp x, Calendar calendar)
      throws SQLException {
    getSite(parameterIndex).setTimestamp(x, calendar);
  }

  public void setTimestamp(int parameterIndex, Timestamp x)
      throws SQLException {
    setTimestamp(parameterIndex, x, getCalendar());
  }

  public void setNull(int parameterIndex, int sqlType, String typeName)
      throws SQLException {
    getSite(parameterIndex).setNull(sqlType, typeName);
  }

  public void setURL(int parameterIndex, URL x) throws SQLException {
    getSite(parameterIndex).setURL(x);
  }

  public void setObject(int parameterIndex, Object x, int targetSqlType,
      int scaleOrLength) throws SQLException {
    getSite(parameterIndex).setObject(x, targetSqlType, scaleOrLength);
  }

  public void setRowId(int parameterIndex, RowId x) throws SQLException {
    getSite(parameterIndex).setRowId(x);
  }

  public void setNString(int parameterIndex, String value) throws SQLException {
    getSite(parameterIndex).setNString(value);
  }

  public void setNCharacterStream(int parameterIndex, Reader value, long length)
      throws SQLException {
    getSite(parameterIndex).setNCharacterStream(value, length);
  }

  public void setNClob(int parameterIndex, NClob value) throws SQLException {
    getSite(parameterIndex).setNClob(value);
  }

  public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
    getSite(parameterIndex).setClob(reader, length);
  }

  public void setBlob(int parameterIndex, InputStream inputStream, long length)
      throws SQLException {
    getSite(parameterIndex).setBlob(inputStream, length);
  }

  public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
    getSite(parameterIndex).setNClob(reader, length);
  }

  public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
    getSite(parameterIndex).setSQLXML(xmlObject);
  }

  public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
    getSite(parameterIndex).setAsciiStream(x, length);
  }

  public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
    getSite(parameterIndex).setBinaryStream(x, length);
  }

  public void setCharacterStream(int parameterIndex, Reader reader, long length)
      throws SQLException {
    getSite(parameterIndex).setCharacterStream(reader, length);
  }

  public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
    getSite(parameterIndex).setAsciiStream(x);
  }

  public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
    getSite(parameterIndex).setBinaryStream(x);
  }

  public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
    getSite(parameterIndex).setCharacterStream(reader);
  }

  public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
    getSite(parameterIndex).setNCharacterStream(value);
  }

  public void setClob(int parameterIndex, Reader reader) throws SQLException {
    getSite(parameterIndex).setClob(reader);
  }

  public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
    getSite(parameterIndex).setBlob(inputStream);
  }

  public void setNClob(int parameterIndex, Reader reader) throws SQLException {
    getSite(parameterIndex).setNClob(reader);
  }

  // implement ParameterMetaData



  protected AvaticaParameter getParameter(int param) throws SQLException {
    try {
      return getSignature().parameters.get(param - 1);
    } catch (IndexOutOfBoundsException e) {
      //noinspection ThrowableResultOfMethodCallIgnored
      throw AvaticaConnection.HELPER.toSQLException(
          AvaticaConnection.HELPER.createException(
              "parameter ordinal " + param + " out of range"));
    }
  }

  protected AvaticaSite getSite(int param) throws SQLException {
    checkOpen();
    final AvaticaParameter parameter = getParameter(param);
    return new AvaticaSite(parameter, getCalendar(), param - 1, slots);
  }

  public int getParameterCount() {
    return getSignature().parameters.size();
  }

  public int isNullable(int param) throws SQLException {
    return ParameterMetaData.parameterNullableUnknown;
  }

  public boolean isSigned(int index) throws SQLException {
    return getParameter(index).signed;
  }

  public int getPrecision(int index) throws SQLException {
    return getParameter(index).precision;
  }

  public int getScale(int index) throws SQLException {
    return getParameter(index).scale;
  }

  public int getParameterType(int index) throws SQLException {
    return getParameter(index).parameterType;
  }

  public String getParameterTypeName(int index) throws SQLException {
    return getParameter(index).typeName;
  }

  public String getParameterClassName(int index) throws SQLException {
    return getParameter(index).className;
  }

  public int getParameterMode(int param) throws SQLException {
    //noinspection UnusedDeclaration
    AvaticaParameter paramDef = getParameter(param); // forces param range check
    return ParameterMetaData.parameterModeIn;
  }
}

// End AvaticaPreparedStatement.java
