/*
 * 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.proto.Common;
import org.apache.calcite.avatica.util.ByteString;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.google.protobuf.Descriptors.FieldDescriptor;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Struct;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Metadata for a column.
 *
 * <p>(Compare with {@link java.sql.ResultSetMetaData}.)
 */
public class ColumnMetaData {
  private static final FieldDescriptor CATALOG_NAME_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.CATALOG_NAME_FIELD_NUMBER);
  private static final FieldDescriptor SCHEMA_NAME_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.SCHEMA_NAME_FIELD_NUMBER);
  private static final FieldDescriptor LABEL_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.LABEL_FIELD_NUMBER);
  private static final FieldDescriptor COLUMN_NAME_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.COLUMN_NAME_FIELD_NUMBER);
  private static final FieldDescriptor TABLE_NAME_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.TABLE_NAME_FIELD_NUMBER);
  private static final FieldDescriptor COLUMN_CLASS_NAME_DESCRIPTOR = Common.ColumnMetaData
      .getDescriptor().findFieldByNumber(Common.ColumnMetaData.COLUMN_CLASS_NAME_FIELD_NUMBER);

  public final int ordinal; // 0-based
  public final boolean autoIncrement;
  public final boolean caseSensitive;
  public final boolean searchable;
  public final boolean currency;
  public final int nullable;
  public final boolean signed;
  public final int displaySize;
  public final String label;
  public final String columnName;
  public final String schemaName;
  public final int precision;
  public final int scale;
  public final String tableName;
  public final String catalogName;
  public final boolean readOnly;
  public final boolean writable;
  public final boolean definitelyWritable;
  public final String columnClassName;
  public final AvaticaType type;

  @JsonCreator
  public ColumnMetaData(
      @JsonProperty("ordinal") int ordinal,
      @JsonProperty("autoIncrement") boolean autoIncrement,
      @JsonProperty("caseSensitive") boolean caseSensitive,
      @JsonProperty("searchable") boolean searchable,
      @JsonProperty("currency") boolean currency,
      @JsonProperty("nullable") int nullable,
      @JsonProperty("signed") boolean signed,
      @JsonProperty("displaySize") int displaySize,
      @JsonProperty("label") String label,
      @JsonProperty("columnName") String columnName,
      @JsonProperty("schemaName") String schemaName,
      @JsonProperty("precision") int precision,
      @JsonProperty("scale") int scale,
      @JsonProperty("tableName") String tableName,
      @JsonProperty("catalogName") String catalogName,
      @JsonProperty("type") AvaticaType type,
      @JsonProperty("readOnly") boolean readOnly,
      @JsonProperty("writable") boolean writable,
      @JsonProperty("definitelyWritable") boolean definitelyWritable,
      @JsonProperty("columnClassName") String columnClassName) {
    this.ordinal = ordinal;
    this.autoIncrement = autoIncrement;
    this.caseSensitive = caseSensitive;
    this.searchable = searchable;
    this.currency = currency;
    this.nullable = nullable;
    this.signed = signed;
    this.displaySize = displaySize;
    this.label = label;
    // Per the JDBC spec this should be just columnName.
    // For example, the query
    //     select 1 as x, c as y from t
    // should give columns
    //     (label=x, column=null, table=null)
    //     (label=y, column=c table=t)
    // But DbUnit requires every column to have a name. Duh.
    this.columnName = first(columnName, label);
    this.schemaName = schemaName;
    this.precision = precision;
    this.scale = scale;
    this.tableName = tableName;
    this.catalogName = catalogName;
    this.type = type;
    this.readOnly = readOnly;
    this.writable = writable;
    this.definitelyWritable = definitelyWritable;
    this.columnClassName = columnClassName;
  }

  public Common.ColumnMetaData toProto() {
    Common.ColumnMetaData.Builder builder = Common.ColumnMetaData.newBuilder();

    // Primitive fields (can't be null)
    builder.setOrdinal(ordinal)
      .setAutoIncrement(autoIncrement)
      .setCaseSensitive(caseSensitive)
      .setSearchable(searchable)
      .setCurrency(currency)
      .setNullable(nullable)
      .setSigned(signed)
      .setDisplaySize(displaySize)
      .setPrecision(precision)
      .setScale(scale)
      .setReadOnly(readOnly)
      .setWritable(writable)
      .setDefinitelyWritable(definitelyWritable);

    // Potentially null fields
    if (null != label) {
      builder.setLabel(label);
    }

    if (null != columnName) {
      builder.setColumnName(columnName);
    }

    if (null != schemaName) {
      builder.setSchemaName(schemaName);
    }

    if (null != tableName) {
      builder.setTableName(tableName);
    }

    if (null != catalogName) {
      builder.setCatalogName(catalogName);
    }

    if (null != type) {
      builder.setType(type.toProto());
    }

    if (null != columnClassName) {
      builder.setColumnClassName(columnClassName);
    }

    return builder.build();
  }

  public static ColumnMetaData fromProto(Common.ColumnMetaData proto) {
    AvaticaType nestedType = AvaticaType.fromProto(proto.getType());

    String catalogName = null;
    if (proto.hasField(CATALOG_NAME_DESCRIPTOR)) {
      catalogName = proto.getCatalogName();
    }

    String schemaName = null;
    if (proto.hasField(SCHEMA_NAME_DESCRIPTOR)) {
      schemaName = proto.getSchemaName();
    }

    String label = null;
    if (proto.hasField(LABEL_DESCRIPTOR)) {
      label = proto.getLabel();
    }

    String columnName = null;
    if (proto.hasField(COLUMN_NAME_DESCRIPTOR)) {
      columnName = proto.getColumnName();
    }

    String tableName = null;
    if (proto.hasField(TABLE_NAME_DESCRIPTOR)) {
      tableName = proto.getTableName();
    }

    String columnClassName = null;
    if (proto.hasField(COLUMN_CLASS_NAME_DESCRIPTOR)) {
      columnClassName = proto.getColumnClassName();
    }

    // Recreate the ColumnMetaData
    return new ColumnMetaData(proto.getOrdinal(), proto.getAutoIncrement(),
        proto.getCaseSensitive(), proto.getSearchable(), proto.getCurrency(), proto.getNullable(),
        proto.getSigned(), proto.getDisplaySize(), label, columnName,
        schemaName, proto.getPrecision(), proto.getScale(), tableName,
        catalogName, nestedType, proto.getReadOnly(), proto.getWritable(),
        proto.getDefinitelyWritable(), columnClassName);
  }

  @Override public int hashCode() {
    return Objects.hash(autoIncrement, caseSensitive, catalogName,
        columnClassName, columnName, currency, definitelyWritable, displaySize,
        label, nullable, ordinal, precision, readOnly, scale, schemaName,
        searchable, signed, tableName, type, writable);
  }

  @Override public boolean equals(Object o) {
    return o == this
        || o instanceof ColumnMetaData
        && autoIncrement == ((ColumnMetaData) o).autoIncrement
        && caseSensitive == ((ColumnMetaData) o).caseSensitive
        && Objects.equals(catalogName, ((ColumnMetaData) o).catalogName)
        && Objects.equals(columnClassName, ((ColumnMetaData) o).columnClassName)
        && Objects.equals(columnName, ((ColumnMetaData) o).columnName)
        && currency == ((ColumnMetaData) o).currency
        && definitelyWritable == ((ColumnMetaData) o).definitelyWritable
        && displaySize == ((ColumnMetaData) o).displaySize
        && Objects.equals(label, ((ColumnMetaData) o).label)
        && nullable == ((ColumnMetaData) o).nullable
        && ordinal == ((ColumnMetaData) o).ordinal
        && precision == ((ColumnMetaData) o).precision
        && readOnly == ((ColumnMetaData) o).readOnly
        && scale == ((ColumnMetaData) o).scale
        && Objects.equals(schemaName, ((ColumnMetaData) o).schemaName)
        && searchable == ((ColumnMetaData) o).searchable
        && signed == ((ColumnMetaData) o).signed
        && Objects.equals(tableName, ((ColumnMetaData) o).tableName)
        && Objects.equals(type, ((ColumnMetaData) o).type)
        && writable == ((ColumnMetaData) o).writable;
  }

  private static <T> T first(T t0, T t1) {
    return t0 != null ? t0 : t1;
  }

  /** Creates a {@link ScalarType}. */
  public static ScalarType scalar(int type, String typeName, Rep rep) {
    return new ScalarType(type, typeName, rep);
  }

  /** Creates a {@link StructType}. */
  public static StructType struct(List<ColumnMetaData> columns) {
    return new StructType(columns);
  }

  /** Creates an {@link ArrayType}. */
  public static ArrayType array(AvaticaType componentType, String typeName,
      Rep rep) {
    return new ArrayType(Types.ARRAY, typeName, rep, componentType);
  }

  /** Creates a ColumnMetaData for result sets that are not based on a struct
   * but need to have a single 'field' for purposes of
   * {@link java.sql.ResultSetMetaData}. */
  public static ColumnMetaData dummy(AvaticaType type, boolean nullable) {
    return new ColumnMetaData(
        0,
        false,
        true,
        false,
        false,
        nullable
            ? DatabaseMetaData.columnNullable
            : DatabaseMetaData.columnNoNulls,
        true,
        -1,
        null,
        null,
        null,
        -1,
        -1,
        null,
        null,
        type,
        true,
        false,
        false,
        type.columnClassName());
  }

  public ColumnMetaData setRep(Rep rep) {
    return new ColumnMetaData(ordinal, autoIncrement, caseSensitive, searchable,
        currency, nullable, signed, displaySize, label, columnName, schemaName,
        precision, scale, tableName, catalogName, type.setRep(rep), readOnly,
        writable, definitelyWritable, columnClassName);
  }

  /** Description of the type used to internally represent a value. For example,
   * a {@link java.sql.Date} might be represented as a {@link #PRIMITIVE_INT}
   * if not nullable, or a {@link #JAVA_SQL_DATE}. */
  public enum Rep {
    PRIMITIVE_BOOLEAN(boolean.class, Types.BOOLEAN),
    PRIMITIVE_BYTE(byte.class, Types.TINYINT),
    PRIMITIVE_CHAR(char.class, Types.CHAR),
    PRIMITIVE_SHORT(short.class, Types.SMALLINT),
    PRIMITIVE_INT(int.class, Types.INTEGER),
    PRIMITIVE_LONG(long.class, Types.BIGINT),
    PRIMITIVE_FLOAT(float.class, Types.FLOAT),
    PRIMITIVE_DOUBLE(double.class, Types.DOUBLE),
    BOOLEAN(Boolean.class, Types.BOOLEAN),
    BYTE(Byte.class, Types.TINYINT),
    CHARACTER(Character.class, Types.CHAR),
    SHORT(Short.class, Types.SMALLINT),
    INTEGER(Integer.class, Types.INTEGER),
    LONG(Long.class, Types.BIGINT),
    FLOAT(Float.class, Types.FLOAT),
    DOUBLE(Double.class, Types.DOUBLE),
    JAVA_SQL_TIME(Time.class, Types.TIME),
    JAVA_SQL_TIMESTAMP(Timestamp.class, Types.TIMESTAMP),
    JAVA_SQL_DATE(java.sql.Date.class, Types.DATE),
    JAVA_UTIL_DATE(java.util.Date.class, Types.DATE),
    BYTE_STRING(ByteString.class, Types.VARBINARY),
    STRING(String.class, Types.VARCHAR),

    /** Values are represented as some sub-class of {@link Number}.
     * The JSON encoding does this. */
    NUMBER(BigDecimal.class, Types.NUMERIC),

    ARRAY(Array.class, Types.ARRAY),
    MULTISET(List.class, Types.JAVA_OBJECT),
    STRUCT(Struct.class, Types.JAVA_OBJECT),

    OBJECT(Object.class, Types.JAVA_OBJECT);

    public final Class clazz;
    public final int typeId;

    public static final Map<Class, Rep> VALUE_MAP;

    static {
      Map<Class, Rep> builder = new HashMap<>();
      for (Rep rep : values()) {
        builder.put(rep.clazz, rep);
      }
      builder.put(byte[].class, BYTE_STRING);
      VALUE_MAP = Collections.unmodifiableMap(builder);
    }

    Rep(Class clazz, int typeId) {
      this.clazz = clazz;
      this.typeId = typeId;
    }

    public static Rep of(Type clazz) {
      //noinspection SuspiciousMethodCalls
      final Rep rep = VALUE_MAP.get(clazz);
      return rep != null ? rep : OBJECT;
    }

    /** Returns the value of a column of this type from a result set. */
    public Object jdbcGet(ResultSet resultSet, int i) throws SQLException {
      switch (this) {
      case PRIMITIVE_BOOLEAN:
        return resultSet.getBoolean(i);
      case PRIMITIVE_BYTE:
        return resultSet.getByte(i);
      case PRIMITIVE_SHORT:
        return resultSet.getShort(i);
      case PRIMITIVE_INT:
        return resultSet.getInt(i);
      case PRIMITIVE_LONG:
        return resultSet.getLong(i);
      case PRIMITIVE_FLOAT:
        return resultSet.getFloat(i);
      case PRIMITIVE_DOUBLE:
        return resultSet.getDouble(i);
      case BOOLEAN:
        final boolean aBoolean = resultSet.getBoolean(i);
        return resultSet.wasNull() ? null : aBoolean;
      case BYTE:
        final byte aByte = resultSet.getByte(i);
        return resultSet.wasNull() ? null : aByte;
      case SHORT:
        final short aShort = resultSet.getShort(i);
        return resultSet.wasNull() ? null : aShort;
      case INTEGER:
        final int anInt = resultSet.getInt(i);
        return resultSet.wasNull() ? null : anInt;
      case LONG:
        final long aLong = resultSet.getLong(i);
        return resultSet.wasNull() ? null : aLong;
      case FLOAT:
        final float aFloat = resultSet.getFloat(i);
        return resultSet.wasNull() ? null : aFloat;
      case DOUBLE:
        final double aDouble = resultSet.getDouble(i);
        return resultSet.wasNull() ? null : aDouble;
      case JAVA_SQL_DATE:
        return resultSet.getDate(i);
      case JAVA_SQL_TIME:
        return resultSet.getTime(i);
      case JAVA_SQL_TIMESTAMP:
        return resultSet.getTimestamp(i);
      case ARRAY:
        return resultSet.getArray(i);
      case STRUCT:
        return resultSet.getObject(i, Struct.class);
      default:
        return resultSet.getObject(i);
      }
    }

    public Common.Rep toProto() {
      return Common.Rep.valueOf(name());
    }

    public static Rep fromProto(Common.Rep proto) {
      if (Common.Rep.UNRECOGNIZED == proto) {
        // Un-set in the message, treat it as null
        return null;
      } else if (Common.Rep.BIG_DECIMAL == proto) {
        // BIG_DECIMAL has to come back as a NUMBER
        return Rep.NUMBER;
      } else if (Common.Rep.NULL == proto) {
        return Rep.OBJECT;
      }
      return Rep.valueOf(proto.name());
    }

    /**
     * Computes the given JDBC type for a primitive to the corresponding {@link Rep} for the
     * equivalent Object type. If the provided type is not for a primitive, a {@link Rep} for the
     * provided Object is returned.
     *
     * @param type The type of a value (based on {@link java.sql.Types}).
     * @return The corresponding non-primitive {@link Rep} for the given {@code type}.
     */
    public static ColumnMetaData.Rep nonPrimitiveRepOf(SqlType type) {
      if (null == type) {
        throw new NullPointerException();
      }
      if (boolean.class == type.clazz) {
        return ColumnMetaData.Rep.BOOLEAN;
      } else if (byte.class == type.clazz) {
        return ColumnMetaData.Rep.BYTE;
      } else  if (char.class == type.clazz) {
        return ColumnMetaData.Rep.CHARACTER;
      } else if (short.class == type.clazz) {
        return ColumnMetaData.Rep.SHORT;
      } else if (int.class == type.clazz) {
        return ColumnMetaData.Rep.INTEGER;
      } else if (long.class == type.clazz) {
        return ColumnMetaData.Rep.LONG;
      } else if (float.class == type.clazz) {
        return ColumnMetaData.Rep.FLOAT;
      } else if (double.class == type.clazz) {
        return ColumnMetaData.Rep.DOUBLE;
      }
      return ColumnMetaData.Rep.of(type.clazz);
    }

    /**
     * Computes the given JDBC type into the {@link Rep} for the wire (serial) form of that type.
     *
     * @param type The type of a value (based on {@link java.sql.Types}).
     * @return The corresponding {@link Rep} for the serial form of the {@code type}.
     */
    public static ColumnMetaData.Rep serialRepOf(SqlType type) {
      if (null == type) {
        throw new NullPointerException();
      }
      if (boolean.class == type.internal) {
        return ColumnMetaData.Rep.BOOLEAN;
      } else if (byte.class == type.internal) {
        return ColumnMetaData.Rep.BYTE;
      } else  if (char.class == type.internal) {
        return ColumnMetaData.Rep.CHARACTER;
      } else if (short.class == type.internal) {
        return ColumnMetaData.Rep.SHORT;
      } else if (int.class == type.internal) {
        return ColumnMetaData.Rep.INTEGER;
      } else if (long.class == type.internal) {
        return ColumnMetaData.Rep.LONG;
      } else if (float.class == type.internal) {
        return ColumnMetaData.Rep.FLOAT;
      } else if (double.class == type.internal) {
        return ColumnMetaData.Rep.DOUBLE;
      }
      return ColumnMetaData.Rep.of(type.internal);
    }
  }

  /** Base class for a column type. */
  @JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME,
      property = "type",
      defaultImpl = ScalarType.class)
  @JsonSubTypes({
      @JsonSubTypes.Type(value = ScalarType.class, name = "scalar"),
      @JsonSubTypes.Type(value = StructType.class, name = "struct"),
      @JsonSubTypes.Type(value = ArrayType.class, name = "array") })
  public static class AvaticaType {
    public final int id;
    public final String name;

    /** The type of the field that holds the value. Not a JDBC property. */
    public final Rep rep;

    public AvaticaType(int id, String name, Rep rep) {
      this.id = id;
      this.name = Objects.requireNonNull(name);
      this.rep = Objects.requireNonNull(rep);
    }

    public String columnClassName() {
      return SqlType.valueOf(id).boxedClass().getName();
    }

    public String getName() {
      return name;
    }

    public AvaticaType setRep(Rep rep) {
      throw new UnsupportedOperationException();
    }

    public Common.AvaticaType toProto() {
      Common.AvaticaType.Builder builder = Common.AvaticaType.newBuilder();

      builder.setName(name);
      builder.setId(id);
      builder.setRep(rep.toProto());

      return builder.build();
    }

    public static AvaticaType fromProto(Common.AvaticaType proto) {
      Common.Rep repProto = proto.getRep();
      Rep rep = Rep.valueOf(repProto.name());
      AvaticaType type;

      if (proto.hasComponent()) {
        // ArrayType
        // recurse on the type for the array elements
        AvaticaType nestedType = AvaticaType.fromProto(proto.getComponent());
        type = ColumnMetaData.array(nestedType, proto.getName(), rep);
      } else if (proto.getColumnsCount() > 0) {
        // StructType
        List<ColumnMetaData> columns = new ArrayList<>(proto.getColumnsCount());
        for (Common.ColumnMetaData protoColumn : proto.getColumnsList()) {
          columns.add(ColumnMetaData.fromProto(protoColumn));
        }
        type = ColumnMetaData.struct(columns);
      } else {
        // ScalarType
        type = ColumnMetaData.scalar(proto.getId(), proto.getName(), rep);
      }

      return type;
    }

    @Override public int hashCode() {
      return Objects.hash(id, name, rep);
    }

    @Override public boolean equals(Object o) {
      return o == this
          || o instanceof AvaticaType
          && id == ((AvaticaType) o).id
          && Objects.equals(name, ((AvaticaType) o).name)
          && rep == ((AvaticaType) o).rep;
    }
  }

  /** Scalar type. */
  public static class ScalarType extends AvaticaType {
    @JsonCreator
    public ScalarType(@JsonProperty("id") int id,
        @JsonProperty("name") String name,
        @JsonProperty("rep") Rep rep) {
      super(id, name, rep);
    }

    @Override public AvaticaType setRep(Rep rep) {
      return new ScalarType(id, name, rep);
    }
  }

  /** Record type. */
  public static class StructType extends AvaticaType {
    public final List<ColumnMetaData> columns;

    @JsonCreator
    public StructType(List<ColumnMetaData> columns) {
      super(Types.STRUCT, "STRUCT", ColumnMetaData.Rep.OBJECT);
      this.columns = columns;
    }

    @Override public Common.AvaticaType toProto() {
      Common.AvaticaType.Builder builder = Common.AvaticaType.newBuilder(super.toProto());
      for (ColumnMetaData valueType : columns) {
        builder.addColumns(valueType.toProto());
      }
      return builder.build();
    }

    @Override public int hashCode() {
      return Objects.hash(id, name, rep, columns);
    }

    @Override public boolean equals(Object o) {
      return o == this
          || o instanceof StructType
          && super.equals(o)
          && Objects.equals(columns, ((StructType) o).columns);
    }
  }

  /** Array type. */
  public static class ArrayType extends AvaticaType {
    private AvaticaType component;

    /**
     * Not for public use. Use {@link ColumnMetaData#array(AvaticaType, String, Rep)}.
     */
    @JsonCreator
    public ArrayType(@JsonProperty("type") int type, @JsonProperty("name") String typeName,
        @JsonProperty("rep") Rep representation, @JsonProperty("component") AvaticaType component) {
      super(type, typeName, representation);
      this.component = component;
    }

    /**
     * Updates the component of {@code this} to the given value. This is necessary to provide as
     * accurate-as-possible of an {@code ArrayType} in the {@code Signature}. It cannot be done
     * at initial construction of this object.
     */
    public void updateComponentType(AvaticaType component) {
      this.component = Objects.requireNonNull(component);
    }

    public AvaticaType getComponent() {
      return component;
    }

    @Override public Common.AvaticaType toProto() {
      Common.AvaticaType.Builder builder = Common.AvaticaType.newBuilder(super.toProto());

      builder.setComponent(component.toProto());

      return builder.build();
    }

    @Override public int hashCode() {
      return Objects.hash(id, name, rep, component);
    }

    @Override public boolean equals(Object o) {
      return o == this
          || o instanceof ArrayType
          && super.equals(o)
          && Objects.equals(component, ((ArrayType) o).component);
    }
  }
}

// End ColumnMetaData.java
