/*
 * 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.remote.TypedValue;
import org.apache.calcite.avatica.util.Cursor;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.Ref;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;

/**
 * A location that a value can be written to or read from.
 */
public class AvaticaSite {
  final AvaticaParameter parameter;

  /** Calendar is not thread-safe. But calendar is only used from within one
   * thread, and we have to trust that clients are not modifying calendars
   * that they pass to us in a method such as
   * {@link java.sql.PreparedStatement#setTime(int, Time, Calendar)}, so we do
   * not need to synchronize access. */
  final Calendar calendar;
  private final int index;
  final TypedValue[] slots;

  /** Value that means the parameter has been set to null.
   * If value is null, parameter has not been set. */
  public static final Object DUMMY_VALUE = Dummy.INSTANCE;

  public AvaticaSite(AvaticaParameter parameter, Calendar calendar, int index,
      TypedValue[] slots) {
    assert calendar != null;
    assert parameter != null;
    assert slots != null;
    this.parameter = parameter;
    this.calendar = calendar;
    this.index = index;
    this.slots = slots;
  }

  private TypedValue wrap(ColumnMetaData.Rep rep, Object o,
      Calendar calendar) {
    return TypedValue.ofJdbc(rep, o, calendar);
  }

  private TypedValue wrap(ColumnMetaData.Rep rep, Object o) {
    return TypedValue.ofJdbc(rep, o, calendar);
  }

  public boolean isSet(int index) {
    return slots[index] != null;
  }

  public void setByte(byte o) {
    slots[index] = wrap(ColumnMetaData.Rep.BYTE, o);
  }

  public void setChar(char o) {
    slots[index] = wrap(ColumnMetaData.Rep.CHARACTER, o);
  }

  public void setShort(short o) {
    slots[index] = wrap(ColumnMetaData.Rep.SHORT, o);
  }

  public void setInt(int o) {
    slots[index] = wrap(ColumnMetaData.Rep.INTEGER, o);
  }

  public void setLong(long o) {
    slots[index] = wrap(ColumnMetaData.Rep.LONG, o);
  }

  public void setBoolean(boolean o) {
    slots[index] = wrap(ColumnMetaData.Rep.BOOLEAN, o);
  }

  public void setRowId(RowId x) {
    slots[index] = wrap(ColumnMetaData.Rep.OBJECT, x);
  }

  public void setNString(String o) {
    slots[index] = wrap(ColumnMetaData.Rep.STRING, o);
  }

  public void setNCharacterStream(Reader value, long length) {
  }

  public void setNClob(NClob value) {
    slots[index] = wrap(ColumnMetaData.Rep.OBJECT, value);
  }

  public void setClob(Reader reader, long length) {
  }

  public void setBlob(InputStream inputStream, long length) {
  }

  public void setNClob(Reader reader, long length) {
  }

  public void setSQLXML(SQLXML xmlObject) {
    slots[index] = wrap(ColumnMetaData.Rep.OBJECT, xmlObject);
  }

  public void setAsciiStream(InputStream x, long length) {
  }

  public void setBinaryStream(InputStream x, long length) {
  }

  public void setCharacterStream(Reader reader, long length) {
  }

  public void setAsciiStream(InputStream x) {
  }

  public void setBinaryStream(InputStream x) {
  }

  public void setCharacterStream(Reader reader) {
  }

  public void setNCharacterStream(Reader value) {
  }

  public void setClob(Reader reader) {
  }

  public void setBlob(InputStream inputStream) {
  }

  public void setNClob(Reader reader) {
  }

  public void setUnicodeStream(InputStream x, int length) {
  }

  public void setFloat(float x) {
    slots[index] = wrap(ColumnMetaData.Rep.FLOAT, x);
  }

  public void setDouble(double x) {
    slots[index] = wrap(ColumnMetaData.Rep.DOUBLE, x);
  }

  public void setBigDecimal(BigDecimal x) {
    slots[index] = wrap(ColumnMetaData.Rep.NUMBER, x);
  }

  public void setString(String x) {
    slots[index] = wrap(ColumnMetaData.Rep.STRING, x);
  }

  public void setBytes(byte[] x) {
    slots[index] = wrap(ColumnMetaData.Rep.BYTE_STRING, x);
  }

  public void setTimestamp(Timestamp x, Calendar calendar) {
    slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_TIMESTAMP, x, calendar);
  }

  public void setTime(Time x, Calendar calendar) {
    slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_TIME, x, calendar);
  }

  public void setDate(Date x, Calendar calendar) {
    slots[index] = wrap(ColumnMetaData.Rep.JAVA_SQL_DATE, x, calendar);
  }

  public void setObject(Object x, int targetSqlType) {
    if (x == null || Types.NULL == targetSqlType) {
      setNull(targetSqlType);
      return;
    }
    switch (targetSqlType) {
    case Types.CLOB:
    case Types.DATALINK:
    case Types.NCLOB:
    case Types.OTHER:
    case Types.REF:
    case Types.SQLXML:
    case Types.STRUCT:
      throw notImplemented();
    case Types.ARRAY:
      setArray(toArray(x));
      break;
    case Types.BIGINT:
      setLong(toLong(x));
      break;
    case Types.BINARY:
    case Types.LONGVARBINARY:
    case Types.VARBINARY:
      setBytes(toBytes(x));
      break;
    case Types.BIT:
    case Types.BOOLEAN:
      setBoolean(toBoolean(x));
      break;
    case Types.BLOB:
      if (x instanceof Blob) {
        setBlob((Blob) x);
        break;
      } else if (x instanceof InputStream) {
        setBlob((InputStream) x);
      }
      throw unsupportedCast(x.getClass(), Blob.class);
    case Types.DATE:
      setDate(toDate(x), calendar);
      break;
    case Types.DECIMAL:
    case Types.NUMERIC:
      setBigDecimal(toBigDecimal(x));
      break;
    case Types.DISTINCT:
      throw notImplemented();
    case Types.DOUBLE:
    case Types.FLOAT: // yes really; SQL FLOAT is up to 8 bytes
      setDouble(toDouble(x));
      break;
    case Types.INTEGER:
      setInt(toInt(x));
      break;
    case Types.JAVA_OBJECT:
      setObject(x);
      break;
    case Types.LONGNVARCHAR:
    case Types.LONGVARCHAR:
    case Types.NVARCHAR:
    case Types.VARCHAR:
    case Types.CHAR:
    case Types.NCHAR:
      setString(toString(x));
      break;
    case Types.REAL:
      setFloat(toFloat(x));
      break;
    case Types.ROWID:
      if (x instanceof RowId) {
        setRowId((RowId) x);
        break;
      }
      throw unsupportedCast(x.getClass(), RowId.class);
    case Types.SMALLINT:
      setShort(toShort(x));
      break;
    case Types.TIME:
      setTime(toTime(x), calendar);
      break;
    case Types.TIMESTAMP:
      setTimestamp(toTimestamp(x), calendar);
      break;
    case Types.TINYINT:
      setByte(toByte(x));
      break;
    default:
      throw notImplemented();
    }
  }

  /** Similar logic to {@link #setObject}. */
  public static Object get(Cursor.Accessor accessor, int targetSqlType,
      Calendar localCalendar) throws SQLException {
    switch (targetSqlType) {
    case Types.CLOB:
    case Types.DATALINK:
    case Types.NCLOB:
    case Types.REF:
    case Types.SQLXML:
      throw notImplemented();
    case Types.STRUCT:
      return accessor.getStruct();
    case Types.ARRAY:
      return accessor.getArray();
    case Types.BIGINT:
      final long aLong = accessor.getLong();
      if (aLong == 0 && accessor.wasNull()) {
        return null;
      }
      return aLong;
    case Types.BINARY:
    case Types.LONGVARBINARY:
    case Types.VARBINARY:
      return accessor.getBytes();
    case Types.BIT:
    case Types.BOOLEAN:
      final boolean aBoolean = accessor.getBoolean();
      if (!aBoolean && accessor.wasNull()) {
        return null;
      }
      return aBoolean;
    case Types.BLOB:
      return accessor.getBlob();
    case Types.DATE:
      return accessor.getDate(localCalendar);
    case Types.DECIMAL:
    case Types.NUMERIC:
      return accessor.getBigDecimal();
    case Types.DISTINCT:
      throw notImplemented();
    case Types.DOUBLE:
    case Types.FLOAT: // yes really; SQL FLOAT is up to 8 bytes
      final double aDouble = accessor.getDouble();
      if (aDouble == 0 && accessor.wasNull()) {
        return null;
      }
      return aDouble;
    case Types.INTEGER:
      final int anInt = accessor.getInt();
      if (anInt == 0 && accessor.wasNull()) {
        return null;
      }
      return anInt;
    case Types.JAVA_OBJECT:
    case Types.NULL:
    case Types.OTHER:
      return accessor.getObject();
    case Types.LONGNVARCHAR:
    case Types.LONGVARCHAR:
    case Types.NVARCHAR:
    case Types.VARCHAR:
    case Types.CHAR:
    case Types.NCHAR:
      return accessor.getString();
    case Types.REAL:
      final float aFloat = accessor.getFloat();
      if (aFloat == 0 && accessor.wasNull()) {
        return null;
      }
      return aFloat;
    case Types.ROWID:
      throw notImplemented();
    case Types.SMALLINT:
      final short aShort = accessor.getShort();
      if (aShort == 0 && accessor.wasNull()) {
        return null;
      }
      return aShort;
    case Types.TIME:
      return accessor.getTime(localCalendar);
    case Types.TIMESTAMP:
      return accessor.getTimestamp(localCalendar);
    case Types.TINYINT:
      final byte aByte = accessor.getByte();
      if (aByte == 0 && accessor.wasNull()) {
        return null;
      }
      return aByte;
    default:
      throw notImplemented();
    }
  }

  public void setObject(Object x) {
    slots[index] = TypedValue.ofJdbc(x, calendar);
  }

  public void setNull(int sqlType) {
    slots[index] = wrap(ColumnMetaData.Rep.OBJECT, null);
  }

  public void setRef(Ref x) {
  }

  public void setBlob(Blob x) {
  }

  public void setClob(Clob x) {
  }

  public void setArray(Array x) {
    slots[index] = wrap(ColumnMetaData.Rep.ARRAY, x);
  }

  public void setNull(int sqlType, String typeName) {
  }

  public void setURL(URL x) {
  }

  public void setObject(Object x, int targetSqlType,
      int scaleOrLength) {
  }

  private static RuntimeException unsupportedCast(Class<?> from, Class<?> to) {
    return new UnsupportedOperationException("Cannot convert from "
        + from.getCanonicalName() + " to " + to.getCanonicalName());
  }

  private static RuntimeException notImplemented() {
    return new RuntimeException("not implemented");
  }

  private static Array toArray(Object x) {
    if (x instanceof Array) {
      return (Array) x;
    }
    throw unsupportedCast(x.getClass(), Array.class);
  }

  public static BigDecimal toBigDecimal(Object x) {
    if (x instanceof BigDecimal) {
      return (BigDecimal) x;
    } else if (x instanceof BigInteger) {
      return new BigDecimal((BigInteger) x);
    } else if (x instanceof Number) {
      if (x instanceof Double || x instanceof Float) {
        return new BigDecimal(((Number) x).doubleValue());
      } else {
        return new BigDecimal(((Number) x).longValue());
      }
    } else if (x instanceof Boolean) {
      return (Boolean) x ? BigDecimal.ONE : BigDecimal.ZERO;
    } else if (x instanceof String) {
      return new BigDecimal((String) x);
    }
    throw unsupportedCast(x.getClass(), BigDecimal.class);
  }

  private static boolean toBoolean(Object x) {
    if (x instanceof Boolean) {
      return (Boolean) x;
    } else if (x instanceof Number) {
      return ((Number) x).intValue() != 0;
    } else if (x instanceof String) {
      String s = (String) x;
      if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes")) {
        return true;
      } else if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no")) {
        return false;
      }
    }
    throw unsupportedCast(x.getClass(), Boolean.TYPE);
  }

  private static byte toByte(Object x) {
    if (x instanceof Number) {
      return ((Number) x).byteValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? (byte) 1 : (byte) 0;
    } else if (x instanceof String) {
      return Byte.parseByte((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Byte.TYPE);
    }
  }

  private static byte[] toBytes(Object x) {
    if (x instanceof byte[]) {
      return (byte[]) x;
    }
    if (x instanceof String) {
      return ((String) x).getBytes(StandardCharsets.UTF_8);
    }
    throw unsupportedCast(x.getClass(), byte[].class);
  }

  private static Date toDate(Object x) {
    if (x instanceof String) {
      return Date.valueOf((String) x);
    }
    return new Date(toLong(x));
  }

  private static Time toTime(Object x) {
    if (x instanceof String) {
      return Time.valueOf((String) x);
    }
    return new Time(toLong(x));
  }

  private static Timestamp toTimestamp(Object x) {
    if (x instanceof String) {
      return Timestamp.valueOf((String) x);
    }
    return new Timestamp(toLong(x));
  }

  private static double toDouble(Object x) {
    if (x instanceof Number) {
      return ((Number) x).doubleValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? 1D : 0D;
    } else if (x instanceof String) {
      return Double.parseDouble((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Double.TYPE);
    }
  }

  private static float toFloat(Object x) {
    if (x instanceof Number) {
      return ((Number) x).floatValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? 1F : 0F;
    } else if (x instanceof String) {
      return Float.parseFloat((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Float.TYPE);
    }
  }

  private static int toInt(Object x) {
    if (x instanceof Number) {
      return ((Number) x).intValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? 1 : 0;
    } else if (x instanceof String) {
      return Integer.parseInt((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Integer.TYPE);
    }
  }

  private static long toLong(Object x) {
    if (x instanceof Number) {
      return ((Number) x).longValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? 1L : 0L;
    } else if (x instanceof String) {
      return Long.parseLong((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Long.TYPE);
    }
  }

  private static short toShort(Object x) {
    if (x instanceof Number) {
      return ((Number) x).shortValue();
    } else if (x instanceof Boolean) {
      return (Boolean) x ? (short) 1 : (short) 0;
    } else if (x instanceof String) {
      return Short.parseShort((String) x);
    } else {
      throw unsupportedCast(x.getClass(), Short.TYPE);
    }
  }

  private static String toString(Object x) {
    if (x instanceof String) {
      return (String) x;
    } else if (x instanceof Character
        || x instanceof Boolean) {
      return x.toString();
    }
    throw unsupportedCast(x.getClass(), String.class);
  }

  /** Singleton value to denote parameters that have been set to null (as
   * opposed to not set).
   *
   * <p>Not a valid value for a parameter.
   *
   * <p>As an enum, it is serializable by Jackson. */
  private enum Dummy {
    INSTANCE
  }
}

// End AvaticaSite.java
