/*
 * 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.drill.exec.store.base.filter;

import java.math.BigDecimal;

import org.apache.drill.common.PlanStringBuilder;
import org.apache.drill.common.types.TypeProtos.MinorType;
import com.google.common.base.Preconditions;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

/**
 * Description of a constant argument of an expression.
 * Each constant is a (type, value) pair.
 */

@JsonPropertyOrder({"type", "value"})
public class ConstantHolder implements Comparable<ConstantHolder> {
  @JsonProperty("type")
  public final MinorType type;
  @JsonProperty("value")
  public final Object value;

  @JsonCreator
  public ConstantHolder(
      @JsonProperty("type") MinorType type,
      @JsonProperty("value") Object value) {
    this.type = type;
    this.value = value;
  }

  public static ConstantHolder bitValue(boolean value) {
    return new ConstantHolder(MinorType.BIT, value);
  }

  public static ConstantHolder smallIntValue(int value) {
    return new ConstantHolder(MinorType.SMALLINT, (short) value);
  }

  public static ConstantHolder intValue(int value) {
    return new ConstantHolder(MinorType.INT, value);
  }

  public static ConstantHolder bigIntValue(long value) {
    return new ConstantHolder(MinorType.BIGINT, value);
  }

  public static ConstantHolder float4Value(float value) {
    return new ConstantHolder(MinorType.FLOAT4, value);
  }

  public static ConstantHolder float8Value(double value) {
    return new ConstantHolder(MinorType.FLOAT8, value);
  }

  public static ConstantHolder decimalValue(BigDecimal value) {
    return new ConstantHolder(MinorType.VARDECIMAL, value);
  }

  public static ConstantHolder varcharValue(String value) {
    return new ConstantHolder(MinorType.VARCHAR, value);
  }

  /**
   * Convert a constant to the given type. Conversion is defined only for
   * some types (where conversion makes sense) and only for some values
   * (only those that would result in a valid conversion.)
   *
   * @param toType the target type
   * @return a constant of the requested type
   * @throws RuntimeException if the conversion is not legal
   * @see {@link #normalize(MinorType)} for a "save" version of this
   * method
   */
  public ConstantHolder convertTo(MinorType toType) {
    if (type == toType) {
      return this;
    }
    switch (toType) {
    case INT:
      return toInt();
    case BIGINT:
      return toBigInt();
    case TIMESTAMP:
      return toTimestamp(null);
    case VARCHAR:
      return toVarChar();
    case FLOAT4:
      return toFloat();
    case FLOAT8:
      return toDouble();
    case VARDECIMAL:
      return toDecimal();
    default:
      throw conversionError(toType);
    }
  }

  /**
   * Normalize the constant to the given type. Return null if the constant
   * cannot be converted. Use this test to determine if the constant is of
   * a form that can be pushed down when push-down only supports certain
   * types. In such a case, the query will likely fail at execution time
   * when Drill tries to compare the remaining filter with an incompatible
   * column type.
   *
   * @param toType the target type
   * @return a constant of the requested type or null if the conversion
   * is not defined or is not legal for the given value
   */
  public ConstantHolder normalize(MinorType toType) {
    try {
      return convertTo(toType);
    } catch (Throwable e) {
      return null;
    }
  }

  public ConstantHolder toInt() {
    int intValue;
    switch (type) {
      case SMALLINT:
        intValue = (Short) value;
        break;
      case INT:
        return this;
      case BIGINT: {
        long value = (long) this.value;
        if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
          throw conversionError(MinorType.INT);
        }
        intValue = (int) value;
        break;
      }
      case VARCHAR:
        try {
          intValue = Integer.parseInt((String) value);
        } catch (NumberFormatException e) {
          throw conversionError(MinorType.INT);
        }
        break;
      case VARDECIMAL:
        try {
          intValue = ((BigDecimal) value).intValueExact();
        } catch (NumberFormatException e) {
          throw conversionError(MinorType.INT);
        }
        break;
      default:
        throw conversionError(MinorType.INT);
    }
    return new ConstantHolder(MinorType.INT, intValue);
  }

  public ConstantHolder toBigInt() {
    long longValue;
    switch (type) {
      case SMALLINT:
        longValue = (Short) value;
        break;
      case INT:
        longValue = (Integer) value;
        break;
      case BIGINT:
        return this;
      case VARCHAR:
        try {
          longValue = Long.parseLong((String) value);
        } catch (NumberFormatException e) {
          throw conversionError(MinorType.BIGINT);
        }
        break;
      case VARDECIMAL:
        try {
          longValue = ((BigDecimal) value).longValueExact();
        } catch (NumberFormatException e) {
          throw conversionError(MinorType.INT);
        }
        break;
      default:
        throw conversionError(MinorType.BIGINT);
    }
    return new ConstantHolder(MinorType.BIGINT, longValue);
  }

  public ConstantHolder toTimestamp(String tz) {
    long longValue;
    switch (type) {
      case TIMESTAMP:
        return this;
      case INT:
        longValue = (Integer) value;
        break;
      case BIGINT:
        longValue = (Long) value;
        break;
      case VARCHAR: {
        DateTimeFormatter format = ISODateTimeFormat.dateTimeNoMillis();
        if (tz != null) {
          format = format.withZone(DateTimeZone.forID(tz));
        }
        try {
          longValue = format.parseDateTime((String) value).getMillis();
        } catch (Exception e) {
          throw conversionError(MinorType.TIMESTAMP);
        }
        break;
      }
      default:
        throw conversionError(MinorType.TIMESTAMP);
    }
    return new ConstantHolder(MinorType.TIMESTAMP, longValue);
  }

  /**
   * Convert the value to a String. Consider this as a debug tool as
   * no attempt is made to format values in any particular way. Date, time,
   * interval and bit values will appear as numbers, which is probably
   * not what most target systems expect.
   * @return the value as a string using the {@code toString()} method
   * on the value
   */
  public ConstantHolder toVarChar() {
    if (type == MinorType.VARCHAR) {
      return this;
    } else {
      return new ConstantHolder(MinorType.VARCHAR, value.toString());
    }
  }

  public ConstantHolder toFloat() {
    float floatValue;
    switch (type) {
    case BIGINT:
      floatValue = (Long) value;
      break;
    case INT:
      floatValue = (Integer) value;
      break;
    case FLOAT4:
      return this;
    case VARCHAR:
      try {
        floatValue = Float.parseFloat((String) value);
      } catch (Exception e) {
        throw conversionError(MinorType.FLOAT8);
      }
      break;
    case VARDECIMAL:
      floatValue = ((BigDecimal) value).floatValue();
      break;
    default:
      throw conversionError(MinorType.FLOAT4);
    }
    return new ConstantHolder(MinorType.FLOAT4, floatValue);
  }

  public ConstantHolder toDouble() {
    double doubleValue;
    switch (type) {
    case SMALLINT:
      doubleValue = (Short) value;
      break;
    case INT:
      doubleValue = (Integer) value;
      break;
    case BIGINT:
      doubleValue = (Long) value;
      break;
    case FLOAT4:
      doubleValue = (Float) value;
      break;
    case FLOAT8:
      return this;
    case VARCHAR:
      try {
        doubleValue = Double.parseDouble((String) value);
      } catch (Exception e) {
        throw conversionError(MinorType.FLOAT8);
      }
      break;
    case VARDECIMAL:
      doubleValue = ((BigDecimal) value).doubleValue();
      break;
    default:
      throw conversionError(MinorType.FLOAT8);
    }
    return new ConstantHolder(MinorType.FLOAT8, doubleValue);
  }

  public ConstantHolder toDecimal() {
    BigDecimal decimalValue;
    switch (type) {
    case SMALLINT:
      decimalValue = BigDecimal.valueOf((Short) value);
      break;
    case INT:
      decimalValue = BigDecimal.valueOf((Integer) value);
      break;
    case BIGINT:
      decimalValue = BigDecimal.valueOf((Long) value);
      break;
    case FLOAT4:
      decimalValue = BigDecimal.valueOf((Float) value);
      break;
    case FLOAT8:
      decimalValue = BigDecimal.valueOf((Double) value);
      break;
    case VARCHAR:
      try {
        decimalValue = new BigDecimal((String) value);
      } catch (Exception e) {
        throw conversionError(MinorType.VARDECIMAL);
      }
      break;
    case VARDECIMAL:
      return this;
    default:
      throw conversionError(MinorType.VARDECIMAL);
    }
    return new ConstantHolder(MinorType.VARDECIMAL, decimalValue);
  }

  public RuntimeException conversionError(MinorType toType) {
    return new IllegalStateException(String.format(
        "Cannot convert a constant %s of type %s to type %s",
        value.toString(), type.name(), toType.name()));
  }

  @Override
  public String toString() {
    return new PlanStringBuilder("Constant")
      .field("type", type.name())
      .field("value", value)
      .toString();
  }

  @Override
  public int compareTo(ConstantHolder other) {
    Preconditions.checkArgument(type == other.type);
    switch (type) {
    case BIGINT:
      return Long.compare((Long) value, (Long) other.value);
    case BIT:
      return Boolean.compare((Boolean) value, (Boolean) other.value);
    case FLOAT4:
      return Float.compare((Float) value, (Float) other.value);
    case FLOAT8:
      return Double.compare((Double) value, (Double) other.value);
    case INT:
      return Integer.compare((Integer) value, (Integer) other.value);
    case VARCHAR:
      return ((String) value).compareTo((String) other.value);
    case VARDECIMAL:
      return ((BigDecimal) value).compareTo((BigDecimal) other.value);
    default:
      throw new UnsupportedOperationException(
          String.format(
              "Unsupported comparison between types %s and %s. Convert values first.",
              type.name(), other.type.name()));
    }
  }
}
