/*
 * 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.jdbc;

import org.apache.calcite.avatica.AvaticaStatement;
import org.apache.calcite.avatica.AvaticaUtils;
import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.ColumnMetaData.ArrayType;
import org.apache.calcite.avatica.ColumnMetaData.AvaticaType;
import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.SqlType;
import org.apache.calcite.avatica.util.DateTimeUtils;

import com.google.common.base.Optional;

import java.sql.Array;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Struct;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

/** Implementation of {@link org.apache.calcite.avatica.Meta.MetaResultSet}
 * upon a JDBC {@link java.sql.ResultSet}.
 *
 * @see org.apache.calcite.avatica.jdbc.JdbcMeta */
class JdbcResultSet extends Meta.MetaResultSet {
  protected JdbcResultSet(String connectionId, int statementId,
      boolean ownStatement, Meta.Signature signature, Meta.Frame firstFrame) {
    this(connectionId, statementId, ownStatement, signature, firstFrame, -1L);
  }

  protected JdbcResultSet(String connectionId, int statementId,
      boolean ownStatement, Meta.Signature signature, Meta.Frame firstFrame,
      long updateCount) {
    super(connectionId, statementId, ownStatement, signature, firstFrame, updateCount);
  }

  /** Creates a result set. */
  public static JdbcResultSet create(String connectionId, int statementId,
      ResultSet resultSet) {
    // -1 still limits to 100 but -2 does not limit to any number
    return create(connectionId, statementId, resultSet,
        JdbcMeta.UNLIMITED_COUNT);
  }

  /** Creates a result set with maxRowCount.
   *
   * <p>If {@code maxRowCount} is -2 ({@link JdbcMeta#UNLIMITED_COUNT}),
   * returns an unlimited number of rows in a single frame; any other
   * negative value (typically -1) returns an unlimited number of rows
   * in frames of the default frame size. */
  public static JdbcResultSet create(String connectionId, int statementId,
      ResultSet resultSet, int maxRowCount) {
    try {
      Meta.Signature sig = JdbcMeta.signature(resultSet.getMetaData());
      return create(connectionId, statementId, resultSet, maxRowCount, sig);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  public static JdbcResultSet create(String connectionId, int statementId,
      ResultSet resultSet, int maxRowCount, Meta.Signature signature) {
    try {
      final Calendar calendar = DateTimeUtils.calendar();
      final int fetchRowCount;
      if (maxRowCount == JdbcMeta.UNLIMITED_COUNT) {
        fetchRowCount = -1;
      } else if (maxRowCount < 0L) {
        fetchRowCount = AvaticaStatement.DEFAULT_FETCH_SIZE;
      } else if (maxRowCount > AvaticaStatement.DEFAULT_FETCH_SIZE) {
        fetchRowCount = AvaticaStatement.DEFAULT_FETCH_SIZE;
      } else {
        fetchRowCount = maxRowCount;
      }
      final Meta.Frame firstFrame = frame(null, resultSet, 0, fetchRowCount, calendar,
          Optional.of(signature));
      if (firstFrame.done) {
        resultSet.close();
      }
      return new JdbcResultSet(connectionId, statementId, true, signature,
          firstFrame);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /** Creates a empty result set with empty frame */
  public static JdbcResultSet empty(String connectionId, int statementId,
      Meta.Signature signature) {
    return new JdbcResultSet(connectionId, statementId, true, signature,
        Meta.Frame.EMPTY);
  }

  /** Creates a result set that only has an update count. */
  public static JdbcResultSet count(String connectionId, int statementId,
      int updateCount) {
    return new JdbcResultSet(connectionId, statementId, true, null, null, updateCount);
  }

  /** Creates a frame containing a given number or unlimited number of rows
   * from a result set. */
  static Meta.Frame frame(StatementInfo info, ResultSet resultSet, long offset,
      int fetchMaxRowCount, Calendar calendar, Optional<Meta.Signature> sig) throws SQLException {
    final ResultSetMetaData metaData = resultSet.getMetaData();
    final int columnCount = metaData.getColumnCount();
    final int[] types = new int[columnCount];
    Set<Integer> arrayOffsets = new HashSet<>();
    for (int i = 0; i < types.length; i++) {
      types[i] = metaData.getColumnType(i + 1);
      if (Types.ARRAY == types[i]) {
        arrayOffsets.add(i);
      }
    }
    final List<Object> rows = new ArrayList<>();
    // Meta prepare/prepareAndExecute 0 return 0 row and done
    boolean done = fetchMaxRowCount == 0;
    for (int i = 0; fetchMaxRowCount < 0 || i < fetchMaxRowCount; i++) {
      final boolean hasRow;
      if (null != info) {
        hasRow = info.next();
      } else {
        hasRow = resultSet.next();
      }
      if (!hasRow) {
        done = true;
        resultSet.close();
        break;
      }
      Object[] columns = new Object[columnCount];
      for (int j = 0; j < columnCount; j++) {
        columns[j] = getValue(resultSet, types[j], j, calendar);
        if (arrayOffsets.contains(j)) {
          // If we have an Array type, our Signature is lacking precision. We can't extract the
          // component type of an Array from metadata, we have to update it as we're serializing
          // the ResultSet.
          final Array array = resultSet.getArray(j + 1);
          // Only attempt to determine the component type for the array when non-null
          if (null != array && sig.isPresent()) {
            ColumnMetaData columnMetaData = sig.get().columns.get(j);
            ArrayType arrayType = (ArrayType) columnMetaData.type;
            SqlType componentSqlType = SqlType.valueOf(array.getBaseType());

            // Avatica Server will always return non-primitives to ensure nullable is guaranteed.
            ColumnMetaData.Rep rep = ColumnMetaData.Rep.serialRepOf(componentSqlType);
            AvaticaType componentType = ColumnMetaData.scalar(array.getBaseType(),
                array.getBaseTypeName(), rep);
            // Update the ArrayType from the Signature
            arrayType.updateComponentType(componentType);

            // We only need to update the array's type once.
            arrayOffsets.remove(j);
          }
        }
      }
      rows.add(columns);
    }
    return new Meta.Frame(offset, done, rows);
  }

  private static Object getValue(ResultSet resultSet, int type, int j,
      Calendar calendar) throws SQLException {
    switch (type) {
    case Types.BIGINT:
      final long aLong = resultSet.getLong(j + 1);
      return aLong == 0 && resultSet.wasNull() ? null : aLong;
    case Types.INTEGER:
      final int anInt = resultSet.getInt(j + 1);
      return anInt == 0 && resultSet.wasNull() ? null : anInt;
    case Types.SMALLINT:
      final short aShort = resultSet.getShort(j + 1);
      return aShort == 0 && resultSet.wasNull() ? null : aShort;
    case Types.TINYINT:
      final byte aByte = resultSet.getByte(j + 1);
      return aByte == 0 && resultSet.wasNull() ? null : aByte;
    case Types.DOUBLE:
    case Types.FLOAT:
      final double aDouble = resultSet.getDouble(j + 1);
      return aDouble == 0D && resultSet.wasNull() ? null : aDouble;
    case Types.REAL:
      final float aFloat = resultSet.getFloat(j + 1);
      return aFloat == 0D && resultSet.wasNull() ? null : aFloat;
    case Types.DATE:
      final Date aDate = resultSet.getDate(j + 1, calendar);
      return aDate == null
          ? null
          : (int) (aDate.getTime() / DateTimeUtils.MILLIS_PER_DAY);
    case Types.TIME:
      final Time aTime = resultSet.getTime(j + 1, calendar);
      return aTime == null
          ? null
          : (int) (aTime.getTime() % DateTimeUtils.MILLIS_PER_DAY);
    case Types.TIMESTAMP:
      final Timestamp aTimestamp = resultSet.getTimestamp(j + 1, calendar);
      return aTimestamp == null ? null : aTimestamp.getTime();
    case Types.ARRAY:
      final Array array = resultSet.getArray(j + 1);
      if (null == array) {
        return null;
      }
      try {
        // Recursively extracts an Array using its ResultSet-representation
        return extractUsingResultSet(array, calendar);
      } catch (UnsupportedOperationException | SQLFeatureNotSupportedException e) {
        // Not every database might implement Array.getResultSet(). This call
        // assumes a non-nested array (depends on the db if that's a valid assumption)
        return extractUsingArray(array, calendar);
      }
    case Types.STRUCT:
      Struct struct = resultSet.getObject(j + 1, Struct.class);
      Object[] attrs = struct.getAttributes();
      List<Object> list = new ArrayList<>(attrs.length);
      for (Object o : attrs) {
        list.add(o);
      }
      return list;
    default:
      return resultSet.getObject(j + 1);
    }
  }

  /**
   * Converts an Array into a List using {@link Array#getResultSet()}. This implementation is
   * recursive and can parse multi-dimensional arrays.
   */
  static List<?> extractUsingResultSet(Array array, Calendar calendar) throws SQLException {
    ResultSet arrayValues = array.getResultSet();
    TreeMap<Integer, Object> map = new TreeMap<>();
    while (arrayValues.next()) {
      // column 1 is the index in the array, column 2 is the value.
      // Recurse on `getValue` to unwrap nested types correctly.
      // `j` is zero-indexed and incremented for us, thus we have `1` being used twice.
      map.put(arrayValues.getInt(1), getValue(arrayValues, array.getBaseType(), 1, calendar));
    }
    // If the result set is not in the same order as the actual Array, TreeMap fixes that.
    // Need to make a concrete list to ensure Jackson serialization.
    return new ArrayList<>(map.values());
  }

  /**
   * Converts an Array into a List using {@link Array#getArray()}. This implementation assumes
   * a non-nested array. Use {link {@link #extractUsingResultSet(Array, Calendar)} if nested
   * arrays may be possible.
   */
  static List<?> extractUsingArray(Array array, Calendar calendar) throws SQLException {
    // No option but to guess as to what the type actually is...
    Object o = array.getArray();
    if (o instanceof List) {
      return (List<?>) o;
    }
    // Assume that it's a Java array.
    return AvaticaUtils.primitiveList(o);
  }
}

// End JdbcResultSet.java
