/*
 * 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.druid.math.expr;

import com.google.common.primitives.Doubles;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.common.guava.GuavaUtils;
import org.apache.druid.java.util.common.IAE;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.UOE;

import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * Generic result holder for evaluated {@link Expr} containing the value and {@link ExprType} of the value to allow
 */
public abstract class ExprEval<T>
{
  private static final int NULL_LENGTH = -1;

  /**
   * Deserialize an expression stored in a bytebuffer, e.g. for an agg.
   *
   * This should be refactored to be consolidated with some of the standard type handling of aggregators probably
   */
  public static ExprEval deserialize(ByteBuffer buffer, int position)
  {
    final ExprType type = ExprType.fromByte(buffer.get(position));
    return deserialize(buffer, position + 1, type);
  }

  /**
   * Deserialize an expression stored in a bytebuffer, e.g. for an agg.
   *
   * This should be refactored to be consolidated with some of the standard type handling of aggregators probably
   */
  public static ExprEval deserialize(ByteBuffer buffer, int offset, ExprType type)
  {
    // | expression bytes |
    switch (type) {
      case LONG:
        // | expression type (byte) | is null (byte) | long bytes |
        if (buffer.get(offset++) == NullHandling.IS_NOT_NULL_BYTE) {
          return of(buffer.getLong(offset));
        }
        return ofLong(null);
      case DOUBLE:
        // | expression type (byte) | is null (byte) | double bytes |
        if (buffer.get(offset++) == NullHandling.IS_NOT_NULL_BYTE) {
          return of(buffer.getDouble(offset));
        }
        return ofDouble(null);
      case STRING:
        // | expression type (byte) | string length (int) | string bytes |
        final int length = buffer.getInt(offset);
        if (length < 0) {
          return of(null);
        }
        final byte[] stringBytes = new byte[length];
        final int oldPosition = buffer.position();
        buffer.position(offset + Integer.BYTES);
        buffer.get(stringBytes, 0, length);
        buffer.position(oldPosition);
        return of(StringUtils.fromUtf8(stringBytes));
      case LONG_ARRAY:
        // | expression type (byte) | array length (int) | array bytes |
        final int longArrayLength = buffer.getInt(offset);
        offset += Integer.BYTES;
        if (longArrayLength < 0) {
          return ofLongArray(null);
        }
        final Long[] longs = new Long[longArrayLength];
        for (int i = 0; i < longArrayLength; i++) {
          final byte isNull = buffer.get(offset);
          offset += Byte.BYTES;
          if (isNull == NullHandling.IS_NOT_NULL_BYTE) {
            // | is null (byte) | long bytes |
            longs[i] = buffer.getLong(offset);
            offset += Long.BYTES;
          } else {
            // | is null (byte) |
            longs[i] = null;
          }
        }
        return ofLongArray(longs);
      case DOUBLE_ARRAY:
        // | expression type (byte) | array length (int) | array bytes |
        final int doubleArrayLength = buffer.getInt(offset);
        offset += Integer.BYTES;
        if (doubleArrayLength < 0) {
          return ofDoubleArray(null);
        }
        final Double[] doubles = new Double[doubleArrayLength];
        for (int i = 0; i < doubleArrayLength; i++) {
          final byte isNull = buffer.get(offset);
          offset += Byte.BYTES;
          if (isNull == NullHandling.IS_NOT_NULL_BYTE) {
            // | is null (byte) | double bytes |
            doubles[i] = buffer.getDouble(offset);
            offset += Double.BYTES;
          } else {
            // | is null (byte) |
            doubles[i] = null;
          }
        }
        return ofDoubleArray(doubles);
      case STRING_ARRAY:
        // | expression type (byte) | array length (int) | array bytes |
        final int stringArrayLength = buffer.getInt(offset);
        offset += Integer.BYTES;
        if (stringArrayLength < 0) {
          return ofStringArray(null);
        }
        final String[] stringArray = new String[stringArrayLength];
        for (int i = 0; i < stringArrayLength; i++) {
          final int stringElementLength = buffer.getInt(offset);
          offset += Integer.BYTES;
          if (stringElementLength < 0) {
            // | string length (int) |
            stringArray[i] = null;
          } else {
            // | string length (int) | string bytes |
            final byte[] stringElementBytes = new byte[stringElementLength];
            final int oldPosition2 = buffer.position();
            buffer.position(offset);
            buffer.get(stringElementBytes, 0, stringElementLength);
            buffer.position(oldPosition2);
            stringArray[i] = StringUtils.fromUtf8(stringElementBytes);
            offset += stringElementLength;
          }
        }
        return ofStringArray(stringArray);
      default:
        throw new UOE("how can this be?");
    }
  }

  /**
   * Write an expression result to a bytebuffer, throwing an {@link ISE} if the data exceeds a maximum size. Primitive
   * numeric types are not validated to be lower than max size, so it is expected to be at least 10 bytes. Callers
   * of this method should enforce this themselves (instead of doing it here, which might be done every row)
   *
   * This should be refactored to be consolidated with some of the standard type handling of aggregators probably
   */
  public static void serialize(ByteBuffer buffer, int position, ExprEval<?> eval, int maxSizeBytes)
  {
    int offset = position;
    buffer.put(offset++, eval.type().getId());
    switch (eval.type()) {
      case LONG:
        if (eval.isNumericNull()) {
          buffer.put(offset, NullHandling.IS_NULL_BYTE);
        } else {
          buffer.put(offset++, NullHandling.IS_NOT_NULL_BYTE);
          buffer.putLong(offset, eval.asLong());
        }
        break;
      case DOUBLE:
        if (eval.isNumericNull()) {
          buffer.put(offset, NullHandling.IS_NULL_BYTE);
        } else {
          buffer.put(offset++, NullHandling.IS_NOT_NULL_BYTE);
          buffer.putDouble(offset, eval.asDouble());
        }
        break;
      case STRING:
        final byte[] stringBytes = StringUtils.toUtf8Nullable(eval.asString());
        if (stringBytes != null) {
          // | expression type (byte) | string length (int) | string bytes |
          checkMaxBytes(eval.type(), 1 + Integer.BYTES + stringBytes.length, maxSizeBytes);
          buffer.putInt(offset, stringBytes.length);
          offset += Integer.BYTES;
          final int oldPosition = buffer.position();
          buffer.position(offset);
          buffer.put(stringBytes, 0, stringBytes.length);
          buffer.position(oldPosition);
        } else {
          checkMaxBytes(eval.type(), 1 + Integer.BYTES, maxSizeBytes);
          buffer.putInt(offset, NULL_LENGTH);
        }
        break;
      case LONG_ARRAY:
        Long[] longs = eval.asLongArray();
        if (longs == null) {
          // | expression type (byte) | array length (int) |
          checkMaxBytes(eval.type(), 1 + Integer.BYTES, maxSizeBytes);
          buffer.putInt(offset, NULL_LENGTH);
        } else {
          // | expression type (byte) | array length (int) | array bytes |
          final int sizeBytes = 1 + Integer.BYTES + (Long.BYTES * longs.length);
          checkMaxBytes(eval.type(), sizeBytes, maxSizeBytes);
          buffer.putInt(offset, longs.length);
          offset += Integer.BYTES;
          for (Long aLong : longs) {
            if (aLong != null) {
              buffer.put(offset, NullHandling.IS_NOT_NULL_BYTE);
              offset++;
              buffer.putLong(offset, aLong);
              offset += Long.BYTES;
            } else {
              buffer.put(offset++, NullHandling.IS_NULL_BYTE);
            }
          }
        }
        break;
      case DOUBLE_ARRAY:
        Double[] doubles = eval.asDoubleArray();
        if (doubles == null) {
          // | expression type (byte) | array length (int) |
          checkMaxBytes(eval.type(), 1 + Integer.BYTES, maxSizeBytes);
          buffer.putInt(offset, NULL_LENGTH);
        } else {
          // | expression type (byte) | array length (int) | array bytes |
          final int sizeBytes = 1 + Integer.BYTES + (Double.BYTES * doubles.length);
          checkMaxBytes(eval.type(), sizeBytes, maxSizeBytes);
          buffer.putInt(offset, doubles.length);
          offset += Integer.BYTES;

          for (Double aDouble : doubles) {
            if (aDouble != null) {
              buffer.put(offset, NullHandling.IS_NOT_NULL_BYTE);
              offset++;
              buffer.putDouble(offset, aDouble);
              offset += Long.BYTES;
            } else {
              buffer.put(offset++, NullHandling.IS_NULL_BYTE);
            }
          }
        }
        break;
      case STRING_ARRAY:
        String[] strings = eval.asStringArray();
        if (strings == null) {
          // | expression type (byte) | array length (int) |
          checkMaxBytes(eval.type(), 1 + Integer.BYTES, maxSizeBytes);
          buffer.putInt(offset, NULL_LENGTH);
        } else {
          // | expression type (byte) | array length (int) | array bytes |
          buffer.putInt(offset, strings.length);
          offset += Integer.BYTES;
          int sizeBytes = 1 + Integer.BYTES;
          for (String string : strings) {
            if (string == null) {
              // | string length (int) |
              sizeBytes += Integer.BYTES;
              checkMaxBytes(eval.type(), sizeBytes, maxSizeBytes);
              buffer.putInt(offset, NULL_LENGTH);
              offset += Integer.BYTES;
            } else {
              // | string length (int) | string bytes |
              final byte[] stringElementBytes = StringUtils.toUtf8(string);
              sizeBytes += Integer.BYTES + stringElementBytes.length;
              checkMaxBytes(eval.type(), sizeBytes, maxSizeBytes);
              buffer.putInt(offset, stringElementBytes.length);
              offset += Integer.BYTES;
              final int oldPosition = buffer.position();
              buffer.position(offset);
              buffer.put(stringElementBytes, 0, stringElementBytes.length);
              buffer.position(oldPosition);
              offset += stringElementBytes.length;
            }
          }
        }
        break;
      default:
        throw new UOE("how can this be?");
    }
  }

  public static void checkMaxBytes(ExprType type, int sizeBytes, int maxSizeBytes)
  {
    if (sizeBytes > maxSizeBytes) {
      throw new ISE("Unable to serialize [%s], size [%s] is larger than max [%s]", type, sizeBytes, maxSizeBytes);
    }
  }

  /**
   * Used to estimate the size in bytes to {@link #serialize} the {@link ExprEval} value, checking against a maximum
   * size and failing with an {@link ISE} if the estimate is over the maximum.
   */
  public static void estimateAndCheckMaxBytes(ExprEval eval, int maxSizeBytes)
  {
    final int estimated;
    switch (eval.type()) {
      case STRING:
        String stringValue = eval.asString();
        estimated = 1 + Integer.BYTES + (stringValue == null ? 0 : StringUtils.estimatedBinaryLengthAsUTF8(stringValue));
        break;
      case LONG:
      case DOUBLE:
        estimated = 1 + (NullHandling.sqlCompatible() ? 1 + Long.BYTES : Long.BYTES);
        break;
      case STRING_ARRAY:
        String[] stringArray = eval.asStringArray();
        if (stringArray == null) {
          estimated = 1 + Integer.BYTES;
        } else {
          final int elementsSize = Arrays.stream(stringArray)
                                         .filter(Objects::nonNull)
                                         .mapToInt(StringUtils::estimatedBinaryLengthAsUTF8)
                                         .sum();
          // since each value is variably sized, there is an integer per element
          estimated = 1 + Integer.BYTES + (Integer.BYTES * stringArray.length) + elementsSize;
        }
        break;
      case LONG_ARRAY:
        Long[] longArray = eval.asLongArray();
        if (longArray == null) {
          estimated = 1 + Integer.BYTES;
        } else {
          final int elementsSize = Arrays.stream(longArray)
                                         .filter(Objects::nonNull)
                                         .mapToInt(x -> Long.BYTES)
                                         .sum();
          estimated = 1 + Integer.BYTES + (NullHandling.sqlCompatible() ? longArray.length : 0) + elementsSize;
        }
        break;
      case DOUBLE_ARRAY:
        Double[] doubleArray = eval.asDoubleArray();
        if (doubleArray == null) {
          estimated = 1 + Integer.BYTES;
        } else {
          final int elementsSize = Arrays.stream(doubleArray)
                                         .filter(Objects::nonNull)
                                         .mapToInt(x -> Long.BYTES)
                                         .sum();
          estimated = 1 + Integer.BYTES + (NullHandling.sqlCompatible() ? doubleArray.length : 0) + elementsSize;
        }
        break;
      default:
        throw new IllegalStateException("impossible");
    }
    checkMaxBytes(eval.type(), estimated, maxSizeBytes);
  }

  /**
   * Converts a List to an appropriate array type, optionally doing some conversion to make multi-valued strings
   * consistent across selector types, which are not consistent in treatment of null, [], and [null].
   *
   * If homogenizeMultiValueStrings is true, null and [] will be converted to [null], otherwise they will retain
   */
  @Nullable
  public static Object coerceListToArray(@Nullable List<?> val, boolean homogenizeMultiValueStrings)
  {
    // if value is not null and has at least 1 element, conversion is unambigous regardless of the selector
    if (val != null && val.size() > 0) {
      Class<?> coercedType = null;

      for (Object elem : val) {
        if (elem != null) {
          coercedType = convertType(coercedType, elem.getClass());
        }
      }

      if (coercedType == Long.class || coercedType == Integer.class) {
        return val.stream().map(x -> x != null ? ((Number) x).longValue() : null).toArray(Long[]::new);
      }
      if (coercedType == Float.class || coercedType == Double.class) {
        return val.stream().map(x -> x != null ? ((Number) x).doubleValue() : null).toArray(Double[]::new);
      }
      // default to string
      return val.stream().map(x -> x != null ? x.toString() : null).toArray(String[]::new);
    }
    if (homogenizeMultiValueStrings) {
      return new String[]{null};
    } else {
      if (val != null) {
        return new String[0];
      }
      return null;
    }
  }

  /**
   * Find the common type to use between 2 types, useful for choosing the appropriate type for an array given a set
   * of objects with unknown type, following rules similar to Java, our own native Expr, and SQL implicit type
   * conversions. This is used to assist in preparing native java objects for {@link Expr.ObjectBinding} which will
   * later be wrapped in {@link ExprEval} when evaluating {@link IdentifierExpr}.
   *
   * If any type is string, then the result will be string because everything can be converted to a string, but a string
   * cannot be converted to everything.
   *
   * For numbers, integer is the most restrictive type, only chosen if both types are integers. Longs win over integers,
   * floats over longs and integers, and doubles win over everything.
   */
  private static Class convertType(@Nullable Class existing, Class next)
  {
    if (Number.class.isAssignableFrom(next) || next == String.class) {
      if (existing == null) {
        return next;
      }
      // string wins everything
      if (existing == String.class) {
        return existing;
      }
      if (next == String.class) {
        return next;
      }
      // all numbers win over Integer
      if (existing == Integer.class) {
        return next;
      }
      if (existing == Float.class) {
        // doubles win over floats
        if (next == Double.class) {
          return next;
        }
        return existing;
      }
      if (existing == Long.class) {
        if (next == Integer.class) {
          // long beats int
          return existing;
        }
        // double and float win over longs
        return next;
      }
      // otherwise double
      return Double.class;
    }
    throw new UOE("Invalid array expression type: %s", next);
  }

  public static ExprEval of(long longValue)
  {
    return new LongExprEval(longValue);
  }

  public static ExprEval of(double doubleValue)
  {
    return new DoubleExprEval(doubleValue);
  }

  public static ExprEval of(@Nullable String stringValue)
  {
    if (stringValue == null) {
      return StringExprEval.OF_NULL;
    }
    return new StringExprEval(stringValue);
  }

  public static ExprEval ofLong(@Nullable Number longValue)
  {
    if (longValue == null) {
      return LongExprEval.OF_NULL;
    }
    return new LongExprEval(longValue);
  }

  public static ExprEval ofDouble(@Nullable Number doubleValue)
  {
    if (doubleValue == null) {
      return DoubleExprEval.OF_NULL;
    }
    return new DoubleExprEval(doubleValue);
  }

  public static ExprEval ofLongArray(@Nullable Long[] longValue)
  {
    if (longValue == null) {
      return LongArrayExprEval.OF_NULL;
    }
    return new LongArrayExprEval(longValue);
  }

  public static ExprEval ofDoubleArray(@Nullable Double[] doubleValue)
  {
    if (doubleValue == null) {
      return DoubleArrayExprEval.OF_NULL;
    }
    return new DoubleArrayExprEval(doubleValue);
  }

  public static ExprEval ofStringArray(@Nullable String[] stringValue)
  {
    if (stringValue == null) {
      return StringArrayExprEval.OF_NULL;
    }
    return new StringArrayExprEval(stringValue);
  }

  /**
   * Convert a boolean back into native expression type
   */
  public static ExprEval ofBoolean(boolean value, ExprType type)
  {
    switch (type) {
      case DOUBLE:
        return ExprEval.of(Evals.asDouble(value));
      case LONG:
        return ExprEval.of(Evals.asLong(value));
      case STRING:
        return ExprEval.of(String.valueOf(value));
      default:
        throw new IllegalArgumentException("invalid type " + type);
    }
  }

  /**
   * Convert a boolean into a long expression type
   */
  public static ExprEval ofLongBoolean(boolean value)
  {
    return ExprEval.of(Evals.asLong(value));
  }

  /**
   * Examine java type to find most appropriate expression type
   */
  public static ExprEval bestEffortOf(@Nullable Object val)
  {
    if (val instanceof ExprEval) {
      return (ExprEval) val;
    }
    if (val instanceof Number) {
      if (val instanceof Float || val instanceof Double) {
        return new DoubleExprEval((Number) val);
      }
      return new LongExprEval((Number) val);
    }
    if (val instanceof Long[]) {
      return new LongArrayExprEval((Long[]) val);
    }
    if (val instanceof Double[]) {
      return new DoubleArrayExprEval((Double[]) val);
    }
    if (val instanceof Float[]) {
      return new DoubleArrayExprEval(Arrays.stream((Float[]) val).map(Float::doubleValue).toArray(Double[]::new));
    }
    if (val instanceof String[]) {
      return new StringArrayExprEval((String[]) val);
    }

    if (val instanceof List) {
      // do not convert empty lists to arrays with a single null element here, because that should have been done
      // by the selectors preparing their ObjectBindings if necessary. If we get to this point it was legitimately
      // empty
      return bestEffortOf(coerceListToArray((List<?>) val, false));
    }

    return new StringExprEval(val == null ? null : String.valueOf(val));
  }

  @Nullable
  public static Number computeNumber(@Nullable String value)
  {
    if (value == null) {
      return null;
    }
    Number rv;
    Long v = GuavaUtils.tryParseLong(value);
    // Do NOT use ternary operator here, because it makes Java to convert Long to Double
    if (v != null) {
      rv = v;
    } else {
      rv = Doubles.tryParse(value);
    }
    return rv;
  }

  // Cached String values
  private boolean stringValueCached = false;
  @Nullable
  private String stringValue;

  @Nullable
  final T value;

  private ExprEval(@Nullable T value)
  {
    this.value = value;
  }

  public abstract ExprType type();

  @Nullable
  public T value()
  {
    return value;
  }

  void cacheStringValue(@Nullable String value)
  {
    stringValue = value;
    stringValueCached = true;
  }

  @Nullable
  String getCachedStringValue()
  {
    assert stringValueCached;
    return stringValue;
  }

  boolean isStringValueCached()
  {
    return stringValueCached;
  }

  @Nullable
  public String asString()
  {
    if (!stringValueCached) {
      if (value == null) {
        stringValue = null;
      } else {
        stringValue = String.valueOf(value);
      }

      stringValueCached = true;
    }

    return stringValue;
  }

  /**
   * The method returns true if numeric primitive value for this {@link ExprEval} is null, otherwise false.
   *
   * If this method returns false, then the values returned by {@link #asLong()}, {@link #asDouble()},
   * and {@link #asInt()} are "valid", since this method is primarily used during {@link Expr} evaluation to decide
   * if primitive numbers can be fetched to use.
   *
   * If a type cannot sanely convert into a primitive numeric value, then this method should always return true so that
   * these primitive numeric getters are not called, since returning false is assumed to mean these values are valid.
   *
   * Note that all types must still return values for {@link #asInt()}, {@link #asLong()}}, and {@link #asDouble()},
   * since this can still happen if {@link NullHandling#sqlCompatible()} is false, but it should be assumed that this
   * can only happen in that mode and 0s are typical and expected for values that would otherwise be null.
   */
  public abstract boolean isNumericNull();

  public boolean isArray()
  {
    return false;
  }

  /**
   * Get the primtive integer value. Callers should check {@link #isNumericNull()} prior to calling this method,
   * otherwise it may improperly return placeholder a value (typically zero, which is expected if
   * {@link NullHandling#sqlCompatible()} is false)
   */
  public abstract int asInt();

  /**
   * Get the primtive long value. Callers should check {@link #isNumericNull()} prior to calling this method,
   * otherwise it may improperly return a placeholder value (typically zero, which is expected if
   * {@link NullHandling#sqlCompatible()} is false)
   */
  public abstract long asLong();

  /**
   * Get the primtive double value. Callers should check {@link #isNumericNull()} prior to calling this method,
   * otherwise it may improperly return a placeholder value (typically zero, which is expected if
   * {@link NullHandling#sqlCompatible()} is false)
   */
  public abstract double asDouble();

  public abstract boolean asBoolean();

  @Nullable
  public abstract Object[] asArray();

  @Nullable
  public abstract String[] asStringArray();

  @Nullable
  public abstract Long[] asLongArray();

  @Nullable
  public abstract Double[] asDoubleArray();

  public abstract ExprEval castTo(ExprType castTo);

  public abstract Expr toExpr();

  private abstract static class NumericExprEval extends ExprEval<Number>
  {
    private NumericExprEval(@Nullable Number value)
    {
      super(value);
    }

    @Override
    public final int asInt()
    {
      return value.intValue();
    }

    @Override
    public final long asLong()
    {
      return value.longValue();
    }

    @Override
    public final double asDouble()
    {
      return value.doubleValue();
    }

    @Nullable
    @Override
    public String[] asStringArray()
    {
      return isNumericNull() ? null : new String[] {value.toString()};
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      return isNumericNull() ? null : new Long[] {value.longValue()};
    }

    @Nullable
    @Override
    public Double[] asDoubleArray()
    {
      return isNumericNull() ? null : new Double[] {value.doubleValue()};
    }

    @Override
    public boolean isNumericNull()
    {
      return value == null;
    }
  }

  private static class DoubleExprEval extends NumericExprEval
  {
    private static final DoubleExprEval OF_NULL = new DoubleExprEval(null);

    private DoubleExprEval(@Nullable Number value)
    {
      super(value == null ? NullHandling.defaultDoubleValue() : (Double) value.doubleValue());
    }

    @Override
    public final ExprType type()
    {
      return ExprType.DOUBLE;
    }

    @Override
    public final boolean asBoolean()
    {
      return Evals.asBoolean(asDouble());
    }

    @Nullable
    @Override
    public Object[] asArray()
    {
      return asDoubleArray();
    }

    @Override
    public final ExprEval castTo(ExprType castTo)
    {
      switch (castTo) {
        case DOUBLE:
          return this;
        case LONG:
          if (value == null) {
            return ExprEval.ofLong(null);
          } else {
            return ExprEval.of(asLong());
          }
        case STRING:
          return ExprEval.of(asString());
        case DOUBLE_ARRAY:
          return ExprEval.ofDoubleArray(asDoubleArray());
        case LONG_ARRAY:
          return ExprEval.ofLongArray(asLongArray());
        case STRING_ARRAY:
          return ExprEval.ofStringArray(asStringArray());
      }
      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      if (isNumericNull()) {
        return new NullDoubleExpr();
      }
      return new DoubleExpr(value.doubleValue());
    }
  }

  private static class LongExprEval extends NumericExprEval
  {
    private static final LongExprEval OF_NULL = new LongExprEval(null);

    private LongExprEval(@Nullable Number value)
    {
      super(value == null ? NullHandling.defaultLongValue() : (Long) value.longValue());
    }

    @Override
    public final ExprType type()
    {
      return ExprType.LONG;
    }

    @Override
    public final boolean asBoolean()
    {
      return Evals.asBoolean(asLong());
    }

    @Nullable
    @Override
    public Object[] asArray()
    {
      return asLongArray();
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      return isNumericNull() ? null : new Long[]{value.longValue()};
    }

    @Override
    public final ExprEval castTo(ExprType castTo)
    {
      switch (castTo) {
        case DOUBLE:
          if (value == null) {
            return ExprEval.ofDouble(null);
          } else {
            return ExprEval.of(asDouble());
          }
        case LONG:
          return this;
        case STRING:
          return ExprEval.of(asString());
        case DOUBLE_ARRAY:
          return ExprEval.ofDoubleArray(asDoubleArray());
        case LONG_ARRAY:
          return ExprEval.ofLongArray(asLongArray());
        case STRING_ARRAY:
          return ExprEval.ofStringArray(asStringArray());
      }
      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      if (isNumericNull()) {
        return new NullLongExpr();
      }
      return new LongExpr(value.longValue());
    }
  }

  private static class StringExprEval extends ExprEval<String>
  {
    private static final StringExprEval OF_NULL = new StringExprEval(null);

    // Cached primitive values.
    private boolean intValueValid = false;
    private boolean longValueValid = false;
    private boolean doubleValueValid = false;
    private boolean booleanValueValid = false;
    private int intValue;
    private long longValue;
    private double doubleValue;
    private boolean booleanValue;

    @Nullable
    private Number numericVal;

    private StringExprEval(@Nullable String value)
    {
      super(NullHandling.emptyToNullIfNeeded(value));
    }

    @Override
    public final ExprType type()
    {
      return ExprType.STRING;
    }

    @Override
    public int asInt()
    {
      if (!intValueValid) {
        intValue = computeInt();
        intValueValid = true;
      }

      return intValue;
    }

    @Override
    public long asLong()
    {
      if (!longValueValid) {
        longValue = computeLong();
        longValueValid = true;
      }

      return longValue;
    }

    @Override
    public double asDouble()
    {
      if (!doubleValueValid) {
        doubleValue = computeDouble();
        doubleValueValid = true;
      }

      return doubleValue;
    }

    @Nullable
    @Override
    public String asString()
    {
      return value;
    }

    @Nullable
    @Override
    public Object[] asArray()
    {
      return asStringArray();
    }

    private int computeInt()
    {
      Number number = computeNumber();
      if (number == null) {
        assert NullHandling.replaceWithDefault();
        return 0;
      }
      return number.intValue();
    }

    private long computeLong()
    {
      Number number = computeNumber();
      if (number == null) {
        assert NullHandling.replaceWithDefault();
        return 0L;
      }
      return number.longValue();
    }

    private double computeDouble()
    {
      Number number = computeNumber();
      if (number == null) {
        assert NullHandling.replaceWithDefault();
        return 0.0d;
      }
      return number.doubleValue();
    }

    @Nullable
    Number computeNumber()
    {
      if (value == null) {
        return null;
      }
      if (numericVal != null) {
        // Optimization for non-null case.
        return numericVal;
      }
      numericVal = computeNumber(value);
      return numericVal;
    }

    @Override
    public boolean isNumericNull()
    {
      return computeNumber() == null;
    }

    @Override
    public final boolean asBoolean()
    {
      if (!booleanValueValid) {
        booleanValue = Evals.asBoolean(value);
        booleanValueValid = true;
      }

      return booleanValue;
    }

    @Nullable
    @Override
    public String[] asStringArray()
    {
      return value == null ? null : new String[] {value};
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      return value == null ? null : new Long[] {computeLong()};
    }

    @Nullable
    @Override
    public Double[] asDoubleArray()
    {
      return value == null ? null : new Double[] {computeDouble()};
    }

    @Override
    public final ExprEval castTo(ExprType castTo)
    {
      switch (castTo) {
        case DOUBLE:
          return ExprEval.ofDouble(computeNumber());
        case LONG:
          return ExprEval.ofLong(computeNumber());
        case STRING:
          return this;
        case DOUBLE_ARRAY:
          return ExprEval.ofDoubleArray(asDoubleArray());
        case LONG_ARRAY:
          return ExprEval.ofLongArray(asLongArray());
        case STRING_ARRAY:
          return ExprEval.ofStringArray(asStringArray());
      }
      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      return new StringExpr(value);
    }
  }

  abstract static class ArrayExprEval<T> extends ExprEval<T[]>
  {
    private ArrayExprEval(@Nullable T[] value)
    {
      super(value);
    }

    @Override
    @Nullable
    public String asString()
    {
      if (!isStringValueCached()) {
        if (value == null) {
          cacheStringValue(null);
        } else if (value.length == 1) {
          if (value[0] == null) {
            cacheStringValue(null);
          } else {
            cacheStringValue(String.valueOf(value[0]));
          }
        } else {
          cacheStringValue(Arrays.toString(value));
        }
      }

      return getCachedStringValue();
    }

    @Override
    public boolean isNumericNull()
    {
      if (isScalar()) {
        return getScalarValue() == null;
      }

      return true;
    }

    @Override
    public boolean isArray()
    {
      return true;
    }

    @Override
    public int asInt()
    {
      return 0;
    }

    @Override
    public long asLong()
    {
      return 0;
    }

    @Override
    public double asDouble()
    {
      return 0;
    }

    @Override
    public boolean asBoolean()
    {
      return false;
    }

    @Nullable
    @Override
    public T[] asArray()
    {
      return value;
    }

    @Nullable
    public T getIndex(int index)
    {
      return value == null ? null : value[index];
    }

    protected boolean isScalar()
    {
      return value != null && value.length == 1;
    }

    @Nullable
    protected T getScalarValue()
    {
      assert value != null && value.length == 1;
      return value[0];
    }
  }

  private static class LongArrayExprEval extends ArrayExprEval<Long>
  {
    private static final LongArrayExprEval OF_NULL = new LongArrayExprEval(null);

    private LongArrayExprEval(@Nullable Long[] value)
    {
      super(value);
    }

    @Override
    public ExprType type()
    {
      return ExprType.LONG_ARRAY;
    }

    @Override
    public int asInt()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.intValue();
      }
      return super.asInt();
    }

    @Override
    public long asLong()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.longValue();
      }
      return super.asLong();
    }

    @Override
    public double asDouble()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.doubleValue();
      }
      return super.asDouble();
    }

    @Override
    public boolean asBoolean()
    {
      if (isScalar()) {
        Number scalarValue = getScalarValue();
        if (scalarValue == null) {
          assert NullHandling.replaceWithDefault();
          return false;
        }
        return Evals.asBoolean(scalarValue.longValue());
      }
      return super.asBoolean();
    }

    @Nullable
    @Override
    public String[] asStringArray()
    {
      return value == null ? null : Arrays.stream(value).map(x -> x != null ? x.toString() : null).toArray(String[]::new);
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      return value;
    }

    @Nullable
    @Override
    public Double[] asDoubleArray()
    {
      return value == null ? null : Arrays.stream(value).map(Long::doubleValue).toArray(Double[]::new);
    }

    @Override
    public ExprEval castTo(ExprType castTo)
    {
      if (value == null) {
        return StringExprEval.OF_NULL;
      }
      switch (castTo) {
        case STRING:
          if (value.length == 1) {
            return ExprEval.of(asString());
          }
          break;
        case LONG:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofLong(null) : ExprEval.ofLong(asLong());
          }
          break;
        case DOUBLE:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofDouble(null) : ExprEval.ofDouble(asDouble());
          }
          break;
        case LONG_ARRAY:
          return this;
        case DOUBLE_ARRAY:
          return ExprEval.ofDoubleArray(asDoubleArray());
        case STRING_ARRAY:
          return ExprEval.ofStringArray(asStringArray());
      }

      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      return new LongArrayExpr(value);
    }
  }

  private static class DoubleArrayExprEval extends ArrayExprEval<Double>
  {
    private static final DoubleArrayExprEval OF_NULL = new DoubleArrayExprEval(null);

    private DoubleArrayExprEval(@Nullable Double[] value)
    {
      super(value);
    }

    @Override
    public ExprType type()
    {
      return ExprType.DOUBLE_ARRAY;
    }

    @Override
    public int asInt()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.intValue();
      }
      return super.asInt();
    }

    @Override
    public long asLong()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.longValue();
      }
      return super.asLong();
    }

    @Override
    public double asDouble()
    {
      if (isScalar()) {
        Number scalar = getScalarValue();
        if (scalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return scalar.doubleValue();
      }
      return super.asDouble();
    }

    @Override
    public boolean asBoolean()
    {
      if (isScalar()) {
        Number scalarValue = getScalarValue();
        if (scalarValue == null) {
          assert NullHandling.replaceWithDefault();
          return false;
        }
        return Evals.asBoolean(scalarValue.longValue());
      }
      return super.asBoolean();
    }

    @Nullable
    @Override
    public String[] asStringArray()
    {
      return value == null
             ? null
             : Arrays.stream(value).map(x -> x != null ? x.toString() : null).toArray(String[]::new);
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      return value == null ? null : Arrays.stream(value).map(Double::longValue).toArray(Long[]::new);
    }

    @Nullable
    @Override
    public Double[] asDoubleArray()
    {
      return value;
    }

    @Override
    public ExprEval castTo(ExprType castTo)
    {
      if (value == null) {
        return StringExprEval.OF_NULL;
      }
      switch (castTo) {
        case STRING:
          if (value.length == 1) {
            return ExprEval.of(asString());
          }
          break;
        case LONG:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofLong(null) : ExprEval.ofLong(asLong());
          }
          break;
        case DOUBLE:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofDouble(null) : ExprEval.ofDouble(asDouble());
          }
          break;
        case LONG_ARRAY:
          return ExprEval.ofLongArray(asLongArray());
        case DOUBLE_ARRAY:
          return this;
        case STRING_ARRAY:
          return ExprEval.ofStringArray(asStringArray());
      }

      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      return new DoubleArrayExpr(value);
    }
  }

  private static class StringArrayExprEval extends ArrayExprEval<String>
  {
    private static final StringArrayExprEval OF_NULL = new StringArrayExprEval(null);

    private boolean longValueValid = false;
    private boolean doubleValueValid = false;
    @Nullable
    private Long[] longValues;
    @Nullable
    private Double[] doubleValues;
    @Nullable
    private Number computedNumericScalar;
    private boolean isScalarNumberValid;

    private StringArrayExprEval(@Nullable String[] value)
    {
      super(value);
    }

    @Override
    public ExprType type()
    {
      return ExprType.STRING_ARRAY;
    }

    @Override
    public boolean isNumericNull()
    {
      if (isScalar()) {
        computeScalarNumericIfNeeded();
        return computedNumericScalar == null;
      }
      return true;
    }

    @Override
    public int asInt()
    {
      if (isScalar()) {
        computeScalarNumericIfNeeded();
        if (computedNumericScalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0;
        }
        return computedNumericScalar.intValue();
      }
      return super.asInt();
    }

    @Override
    public long asLong()
    {
      if (isScalar()) {
        computeScalarNumericIfNeeded();
        if (computedNumericScalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0L;
        }
        return computedNumericScalar.longValue();
      }
      return super.asLong();
    }

    @Override
    public double asDouble()
    {
      if (isScalar()) {
        computeScalarNumericIfNeeded();
        if (computedNumericScalar == null) {
          assert NullHandling.replaceWithDefault();
          return 0.0;
        }
        return computedNumericScalar.doubleValue();
      }
      return super.asDouble();
    }

    @Override
    public boolean asBoolean()
    {
      if (isScalar()) {
        return Evals.asBoolean(getScalarValue());
      }
      return super.asBoolean();
    }

    @Nullable
    @Override
    public String[] asStringArray()
    {
      return value;
    }

    @Nullable
    @Override
    public Long[] asLongArray()
    {
      if (!longValueValid) {
        longValues = computeLongs();
        longValueValid = true;
      }
      return longValues;
    }

    @Nullable
    @Override
    public Double[] asDoubleArray()
    {
      if (!doubleValueValid) {
        doubleValues = computeDoubles();
        doubleValueValid = true;
      }
      return doubleValues;
    }

    @Override
    public ExprEval castTo(ExprType castTo)
    {
      if (value == null) {
        return StringExprEval.OF_NULL;
      }
      switch (castTo) {
        case STRING:
          if (value.length == 1) {
            return ExprEval.of(asString());
          }
          break;
        case LONG:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofLong(null) : ExprEval.ofLong(asLong());
          }
          break;
        case DOUBLE:
          if (value.length == 1) {
            return isNumericNull() ? ExprEval.ofDouble(null) : ExprEval.ofDouble(asDouble());
          }
          break;
        case STRING_ARRAY:
          return this;
        case LONG_ARRAY:
          return ExprEval.ofLongArray(asLongArray());
        case DOUBLE_ARRAY:
          return ExprEval.ofDoubleArray(asDoubleArray());
      }
      throw new IAE("invalid type " + castTo);
    }

    @Override
    public Expr toExpr()
    {
      return new StringArrayExpr(value);
    }

    @Nullable
    private Long[] computeLongs()
    {
      if (value == null) {
        return null;
      }
      return Arrays.stream(value).map(value -> {
        if (value == null) {
          return null;
        }
        Long lv = GuavaUtils.tryParseLong(value);
        if (lv == null) {
          Double d = Doubles.tryParse(value);
          if (d != null) {
            lv = d.longValue();
          }
        }
        return lv;
      }).toArray(Long[]::new);
    }

    @Nullable
    private Double[] computeDoubles()
    {
      if (value == null) {
        return null;
      }
      return Arrays.stream(value).map(val -> {
        if (val == null) {
          return null;
        }
        return Doubles.tryParse(val);
      }).toArray(Double[]::new);
    }


    /**
     * must not be called unless array has a single element
      */
    private void computeScalarNumericIfNeeded()
    {
      if (!isScalarNumberValid) {
        computedNumericScalar = computeNumber(getScalarValue());
        isScalarNumberValid = true;
      }
    }
  }
}
