// 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.impala.catalog;

import com.google.common.base.Preconditions;
import org.apache.impala.analysis.LiteralExpr;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.common.ImpalaRuntimeException;
import org.apache.impala.thrift.TColumn;
import org.apache.impala.util.KuduUtil;

import org.apache.kudu.ColumnSchema.CompressionAlgorithm;
import org.apache.kudu.ColumnSchema.Encoding;
import org.apache.kudu.ColumnSchema;

/**
 *  Represents a Kudu column.
 *
 *  This class extends Column with Kudu-specific information:
 *  - primary key
 *  - nullability constraint
 *  - encoding
 *  - compression
 *  - default value
 *  - desired block size
 */
public class KuduColumn extends Column {
  // The name of the column as it appears in Kudu, i.e. not converted to lower case.
  private final String kuduName_;
  private final boolean isKey_;
  private final boolean isNullable_;
  private final Encoding encoding_;
  private final CompressionAlgorithm compression_;
  private final int blockSize_;

  // Default value for this column. The expr is a literal of the target column type
  // post-analysis. For TIMESTAMPs those are BIGINT values storing the unix time in
  // microseconds. Code that references this may need to handle TIMESTAMP specially.
  // For that reason, this isn't exposed publicly, e.g. getDefaultValueSql() is used
  // to hide this complexity externally.
  private final LiteralExpr defaultValue_;

  private KuduColumn(String name, Type type, boolean isKey, boolean isNullable,
      Encoding encoding, CompressionAlgorithm compression, LiteralExpr defaultValue,
      int blockSize, String comment, int position) {
    super(name.toLowerCase(), type, comment, position);
    Preconditions.checkArgument(defaultValue == null || type == defaultValue.getType()
        || (type.isTimestamp() && defaultValue.getType().isIntegerType()));
    kuduName_ = name;
    isKey_ = isKey;
    isNullable_ = isNullable;
    encoding_ = encoding;
    compression_ = compression;
    defaultValue_ = defaultValue;
    blockSize_ = blockSize;
  }

  public static KuduColumn fromColumnSchema(ColumnSchema colSchema, int position)
      throws ImpalaRuntimeException {
    Type type = KuduUtil.toImpalaType(colSchema.getType(), colSchema.getTypeAttributes());
    Object defaultValue = colSchema.getDefaultValue();
    LiteralExpr defaultValueExpr = null;
    if (defaultValue != null) {
      Type defaultValueType = type.isTimestamp() ? Type.BIGINT : type;
      try {
        defaultValueExpr = LiteralExpr.create(defaultValue.toString(), defaultValueType);
      } catch (AnalysisException e) {
        throw new ImpalaRuntimeException(String.format("Error parsing default value: " +
            "'%s'", defaultValue), e);
      }
      Preconditions.checkNotNull(defaultValueExpr);
    }
    String comment = !colSchema.getComment().isEmpty() ? colSchema.getComment() : null;
    return new KuduColumn(colSchema.getName(), type, colSchema.isKey(),
        colSchema.isNullable(), colSchema.getEncoding(),
        colSchema.getCompressionAlgorithm(), defaultValueExpr,
        colSchema.getDesiredBlockSize(), comment, position);
  }

  public static KuduColumn fromThrift(TColumn column, int position)
      throws ImpalaRuntimeException {
    Preconditions.checkState(column.isSetIs_key());
    Preconditions.checkState(column.isSetIs_nullable());
    Type columnType = Type.fromThrift(column.getColumnType());
    Encoding encoding = null;
    if (column.isSetEncoding()) encoding = KuduUtil.fromThrift(column.getEncoding());
    CompressionAlgorithm compression = null;
    if (column.isSetCompression()) {
      compression = KuduUtil.fromThrift(column.getCompression());
    }
    LiteralExpr defaultValue = null;
    if (column.isSetDefault_value()) {
      Type defaultValueType = columnType.isTimestamp() ? Type.BIGINT : columnType;
      defaultValue =
          LiteralExpr.fromThrift(column.getDefault_value().getNodes().get(0),
              defaultValueType);
    }
    int blockSize = 0;
    if (column.isSetBlock_size()) blockSize = column.getBlock_size();
    String comment = (column.isSetComment() && !column.getComment().isEmpty()) ?
        column.getComment() : null;
    return new KuduColumn(column.getKudu_column_name(), columnType, column.isIs_key(),
        column.isIs_nullable(), encoding, compression, defaultValue, blockSize, comment,
        position);
  }

  public String getKuduName() { return kuduName_; }
  public boolean isKey() { return isKey_; }
  public boolean isNullable() { return isNullable_; }
  public Encoding getEncoding() { return encoding_; }
  public CompressionAlgorithm getCompression() { return compression_; }
  public int getBlockSize() { return blockSize_; }
  public boolean hasDefaultValue() { return defaultValue_ != null; }

  /**
   * Returns a SQL string representation of the default value. Similar to calling
   * LiteralExpr.toSql(), but this handles TIMESTAMPs specially because
   * TIMESTAMP default values are stored as BIGINTs representing unix time in
   * microseconds. For TIMESTAMP columns, the returned string is the function to
   * convert unix times in microseconds to TIMESTAMPs with the value as its parameter.
   */
  public String getDefaultValueSql() {
    if (!hasDefaultValue()) return null;
    if (!type_.isTimestamp()) return defaultValue_.toSql();
    return "unix_micros_to_utc_timestamp(" + defaultValue_.getStringValue() + ")";
  }

  /**
   * Returns a string representation of the default value. This calls getStringValue()
   * but is exposed so defaultValue_ can be encapsulated as it has special handling for
   * TIMESTAMP column types.
   */
  public String getDefaultValueString() {
    if (!hasDefaultValue()) return null;
    return defaultValue_.getStringValue();
  }

  @Override
  public TColumn toThrift() {
    TColumn colDesc = new TColumn(name_, type_.toThrift());
    KuduUtil.setColumnOptions(colDesc, isKey_, isNullable_, encoding_, compression_,
        defaultValue_, blockSize_, kuduName_);
    if (comment_ != null) colDesc.setComment(comment_);
    colDesc.setCol_stats(getStats().toThrift());
    colDesc.setPosition(position_);
    colDesc.setIs_kudu_column(true);
    return colDesc;
  }
}
