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

import static org.apache.drill.exec.planner.logical.DrillOptiq.isLiteralNull;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.core.Values;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.util.NlsString;
import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.util.GuavaUtils;
import org.apache.drill.common.util.JacksonUtils;
import org.apache.drill.exec.vector.complex.fn.BasicJsonOutput;
import org.apache.drill.exec.vector.complex.fn.JsonOutput;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Period;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.TokenBuffer;

/**
 * Base class for logical and physical Values implemented in Drill.
 */
public abstract class DrillValuesRelBase extends Values implements DrillRelNode {

  private static final ObjectMapper MAPPER = JacksonUtils.createObjectMapper();

  protected final String content;

  public DrillValuesRelBase(RelOptCluster cluster, RelDataType rowType, List<? extends List<RexLiteral>> tuples, RelTraitSet traits) {
    this(cluster, rowType, tuples, traits, convertToJsonOptions(rowType, tuples));
  }

  /**
   * This constructor helps to avoid unnecessary tuples parsing into json options
   * during copying or logical to physical values conversion.
   */
  public DrillValuesRelBase(RelOptCluster cluster,
                            RelDataType rowType,
                            List<? extends List<RexLiteral>> tuples,
                            RelTraitSet traits,
                            String content) {
    super(cluster, rowType, GuavaUtils.convertToNestedUnshadedImmutableList(tuples), traits);
    this.content = content;
  }

  /**
   * @return values content represented as json string
   */
  public String getContent() {
    return content;
  }

  /**
   * Converts tuples into json representation taking into account row type.
   * Example: [['A']] -> [{"EXPR$0":"A"}], [[1]] -> [{"EXPR$0":{"$numberLong":1}}]
   *
   * @param rowType row type
   * @param tuples list of constant values in a row-expression
   * @return json representation of tuples
   */
  private static String convertToJsonOptions(RelDataType rowType, List<? extends List<RexLiteral>> tuples) {
    try {
      return MAPPER.writeValueAsString(convertToJsonNode(rowType, tuples));
    } catch (IOException e) {
      throw new DrillRuntimeException("Failure while attempting to encode Values in JSON.", e);
    }
  }

  private static JsonNode convertToJsonNode(RelDataType rowType, List<? extends List<RexLiteral>> tuples) throws IOException {
    TokenBuffer out = new TokenBuffer(MAPPER.getFactory().getCodec(), false);
    JsonOutput json = new BasicJsonOutput(out);
    json.writeStartArray();
    String[] fields = rowType.getFieldNames().toArray(new String[rowType.getFieldCount()]);

    for (List<RexLiteral> row : tuples) {
      json.writeStartObject();
      int i = 0;
      for (RexLiteral field : row) {
        json.writeFieldName(fields[i]);
        writeLiteral(field, json);
        i++;
      }
      json.writeEndObject();
    }
    json.writeEndArray();
    json.flush();
    return out.asParser().readValueAsTree();
  }

  private static void writeLiteral(RexLiteral literal, JsonOutput out) throws IOException {
    switch (literal.getType().getSqlTypeName()) {
      case BIGINT:
        if (isLiteralNull(literal)) {
          out.writeBigIntNull();
        } else {
          out.writeBigInt((((BigDecimal) literal.getValue()).setScale(0, RoundingMode.HALF_UP)).longValue());
        }
        return;

      case BOOLEAN:
        if (isLiteralNull(literal)) {
          out.writeBooleanNull();
        } else {
          out.writeBoolean((Boolean) literal.getValue());
        }
        return;

      case CHAR:
        if (isLiteralNull(literal)) {
          out.writeVarcharNull();
        } else {
          // Since Calcite treats string literals as fixed char and adds trailing spaces to the strings to make them the
          // same length, here we do an rtrim() to get the string without the trailing spaces. If we don't rtrim, the comparison
          // with Drill's varchar column values would not return a match.
          // TODO: However, note that if the user had explicitly added spaces in the string literals then even those would get
          // trimmed, so this exposes another issue that needs to be resolved.
          out.writeVarChar(((NlsString) literal.getValue()).rtrim().getValue());
        }
        return;

      case DOUBLE:
        if (isLiteralNull(literal)) {
          out.writeDoubleNull();
        } else {
          out.writeDouble(((BigDecimal) literal.getValue()).doubleValue());
        }
        return;

      case FLOAT:
        if (isLiteralNull(literal)) {
          out.writeFloatNull();
        } else {
          out.writeFloat(((BigDecimal) literal.getValue()).floatValue());
        }
        return;

      case INTEGER:
        if (isLiteralNull(literal)) {
          out.writeIntNull();
        } else {
          out.writeInt((((BigDecimal) literal.getValue()).setScale(0, RoundingMode.HALF_UP)).intValue());
        }
        return;

      case DECIMAL:
        // Converting exact decimal into double since values in the list may have different scales
        // so the resulting scale wouldn't be calculated correctly
        if (isLiteralNull(literal)) {
          out.writeDoubleNull();
        } else {
          out.writeDouble(((BigDecimal) literal.getValue()).doubleValue());
        }
        return;

      case VARCHAR:
        if (isLiteralNull(literal)) {
          out.writeVarcharNull();
        } else {
          out.writeVarChar(((NlsString) literal.getValue()).getValue());
        }
        return;

      case SYMBOL:
        if (isLiteralNull(literal)) {
          out.writeVarcharNull();
        } else {
          out.writeVarChar(literal.getValue().toString());
        }
        return;

      case DATE:
        if (isLiteralNull(literal)) {
          out.writeDateNull();
        } else {
          out.writeDate(LocalDateTime.ofInstant(Instant.ofEpochMilli(new DateTime(literal.getValue()).getMillis()), ZoneOffset.UTC).toLocalDate());
        }
        return;

      case TIME:
        if (isLiteralNull(literal)) {
          out.writeTimeNull();
        } else {
          out.writeTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(new DateTime(literal.getValue()).getMillis()), ZoneOffset.UTC).toLocalTime());
        }
        return;

      case TIMESTAMP:
        if (isLiteralNull(literal)) {
          out.writeTimestampNull();
        } else {
          out.writeTimestamp(LocalDateTime.ofInstant(Instant.ofEpochMilli(new DateTime(literal.getValue()).getMillis()), ZoneOffset.UTC));
        }
        return;

      case INTERVAL_YEAR:
      case INTERVAL_YEAR_MONTH:
      case INTERVAL_MONTH:
        if (isLiteralNull(literal)) {
          out.writeIntervalNull();
        } else {
          int months = ((BigDecimal) (literal.getValue())).intValue();
          out.writeInterval(new Period().plusMonths(months));
        }
        return;

      case INTERVAL_DAY:
      case INTERVAL_DAY_HOUR:
      case INTERVAL_DAY_MINUTE:
      case INTERVAL_DAY_SECOND:
      case INTERVAL_HOUR:
      case INTERVAL_HOUR_MINUTE:
      case INTERVAL_HOUR_SECOND:
      case INTERVAL_MINUTE:
      case INTERVAL_MINUTE_SECOND:
      case INTERVAL_SECOND:
        if (isLiteralNull(literal)) {
          out.writeIntervalNull();
        } else {
          long millis = ((BigDecimal) (literal.getValue())).longValue();
          long days = millis / DateTimeConstants.MILLIS_PER_DAY;
          millis = millis - (days * DateTimeConstants.MILLIS_PER_DAY);
          out.writeInterval(new Period().plusDays((int) days).plusMillis((int) millis));
        }
        return;

      case NULL:
        out.writeUntypedNull();
        return;

      case ANY:
      default:
        throw new UnsupportedOperationException(
            String.format("Unable to convert the value of %s and type %s to a Drill constant expression.",
                literal, literal.getType().getSqlTypeName()));
    }
  }

}
