// 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.

#pragma once

#include <memory>
#include <string>
#include <unordered_set>
#include <vector>

#include "gandiva/dex_visitor.h"
#include "gandiva/field_descriptor.h"
#include "gandiva/func_descriptor.h"
#include "gandiva/function_holder.h"
#include "gandiva/gandiva_aliases.h"
#include "gandiva/in_holder.h"
#include "gandiva/literal_holder.h"
#include "gandiva/native_function.h"
#include "gandiva/value_validity_pair.h"
#include "gandiva/visibility.h"

namespace gandiva {

/// \brief Decomposed expression : the validity and value are separated.
class GANDIVA_EXPORT Dex {
 public:
  /// Derived classes should simply invoke the Visit api of the visitor.
  virtual void Accept(DexVisitor& visitor) = 0;
  virtual ~Dex() = default;
};

/// Base class for other Vector related Dex.
class GANDIVA_EXPORT VectorReadBaseDex : public Dex {
 public:
  explicit VectorReadBaseDex(FieldDescriptorPtr field_desc) : field_desc_(field_desc) {}

  const std::string& FieldName() const { return field_desc_->Name(); }

  DataTypePtr FieldType() const { return field_desc_->Type(); }

  FieldPtr Field() const { return field_desc_->field(); }

 protected:
  FieldDescriptorPtr field_desc_;
};

/// validity component of a ValueVector
class GANDIVA_EXPORT VectorReadValidityDex : public VectorReadBaseDex {
 public:
  explicit VectorReadValidityDex(FieldDescriptorPtr field_desc)
      : VectorReadBaseDex(field_desc) {}

  int ValidityIdx() const { return field_desc_->validity_idx(); }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// value component of a fixed-len ValueVector
class GANDIVA_EXPORT VectorReadFixedLenValueDex : public VectorReadBaseDex {
 public:
  explicit VectorReadFixedLenValueDex(FieldDescriptorPtr field_desc)
      : VectorReadBaseDex(field_desc) {}

  int DataIdx() const { return field_desc_->data_idx(); }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// value component of a variable-len ValueVector
class GANDIVA_EXPORT VectorReadVarLenValueDex : public VectorReadBaseDex {
 public:
  explicit VectorReadVarLenValueDex(FieldDescriptorPtr field_desc)
      : VectorReadBaseDex(field_desc) {}

  int DataIdx() const { return field_desc_->data_idx(); }

  int OffsetsIdx() const { return field_desc_->offsets_idx(); }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// validity based on a local bitmap.
class GANDIVA_EXPORT LocalBitMapValidityDex : public Dex {
 public:
  explicit LocalBitMapValidityDex(int local_bitmap_idx)
      : local_bitmap_idx_(local_bitmap_idx) {}

  int local_bitmap_idx() const { return local_bitmap_idx_; }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

 private:
  int local_bitmap_idx_;
};

/// base function expression
class GANDIVA_EXPORT FuncDex : public Dex {
 public:
  FuncDex(FuncDescriptorPtr func_descriptor, const NativeFunction* native_function,
          FunctionHolderPtr function_holder, int function_holder_idx,
          const ValueValidityPairVector& args)
      : func_descriptor_(func_descriptor),
        native_function_(native_function),
        function_holder_(function_holder),
        function_holder_idx_(function_holder_idx),
        args_(args) {}

  FuncDescriptorPtr func_descriptor() const { return func_descriptor_; }

  const NativeFunction* native_function() const { return native_function_; }

  int get_holder_idx() const { return function_holder_idx_; }

  const ValueValidityPairVector& args() const { return args_; }

 private:
  FuncDescriptorPtr func_descriptor_;
  const NativeFunction* native_function_;
  FunctionHolderPtr function_holder_;
  int function_holder_idx_;
  ValueValidityPairVector args_;
};

/// A function expression that only deals with non-null inputs, and generates non-null
/// outputs.
class GANDIVA_EXPORT NonNullableFuncDex : public FuncDex {
 public:
  NonNullableFuncDex(FuncDescriptorPtr func_descriptor,
                     const NativeFunction* native_function,
                     FunctionHolderPtr function_holder, int function_holder_idx,
                     const ValueValidityPairVector& args)
      : FuncDex(func_descriptor, native_function, function_holder, function_holder_idx,
                args) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// A function expression that deals with nullable inputs, but generates non-null
/// outputs.
class GANDIVA_EXPORT NullableNeverFuncDex : public FuncDex {
 public:
  NullableNeverFuncDex(FuncDescriptorPtr func_descriptor,
                       const NativeFunction* native_function,
                       FunctionHolderPtr function_holder, int function_holder_idx,
                       const ValueValidityPairVector& args)
      : FuncDex(func_descriptor, native_function, function_holder, function_holder_idx,
                args) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// A function expression that deals with nullable inputs, and
/// nullable outputs.
class GANDIVA_EXPORT NullableInternalFuncDex : public FuncDex {
 public:
  NullableInternalFuncDex(FuncDescriptorPtr func_descriptor,
                          const NativeFunction* native_function,
                          FunctionHolderPtr function_holder, int function_holder_idx,
                          const ValueValidityPairVector& args, int local_bitmap_idx)
      : FuncDex(func_descriptor, native_function, function_holder, function_holder_idx,
                args),
        local_bitmap_idx_(local_bitmap_idx) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

  /// The validity of the function result is saved in this bitmap.
  int local_bitmap_idx() const { return local_bitmap_idx_; }

 private:
  int local_bitmap_idx_;
};

/// special validity type that always returns true.
class GANDIVA_EXPORT TrueDex : public Dex {
  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// special validity type that always returns false.
class GANDIVA_EXPORT FalseDex : public Dex {
  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// decomposed expression for a literal.
class GANDIVA_EXPORT LiteralDex : public Dex {
 public:
  LiteralDex(DataTypePtr type, const LiteralHolder& holder)
      : type_(type), holder_(holder) {}

  const DataTypePtr& type() const { return type_; }

  const LiteralHolder& holder() const { return holder_; }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

 private:
  DataTypePtr type_;
  LiteralHolder holder_;
};

/// decomposed if-else expression.
class GANDIVA_EXPORT IfDex : public Dex {
 public:
  IfDex(ValueValidityPairPtr condition_vv, ValueValidityPairPtr then_vv,
        ValueValidityPairPtr else_vv, DataTypePtr result_type, int local_bitmap_idx,
        bool is_terminal_else)
      : condition_vv_(condition_vv),
        then_vv_(then_vv),
        else_vv_(else_vv),
        result_type_(result_type),
        local_bitmap_idx_(local_bitmap_idx),
        is_terminal_else_(is_terminal_else) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

  const ValueValidityPair& condition_vv() const { return *condition_vv_; }
  const ValueValidityPair& then_vv() const { return *then_vv_; }
  const ValueValidityPair& else_vv() const { return *else_vv_; }

  /// The validity of the result is saved in this bitmap.
  int local_bitmap_idx() const { return local_bitmap_idx_; }

  /// is this a terminal else ? i.e no nested if-else underneath.
  bool is_terminal_else() const { return is_terminal_else_; }

  const DataTypePtr& result_type() const { return result_type_; }

 private:
  ValueValidityPairPtr condition_vv_;
  ValueValidityPairPtr then_vv_;
  ValueValidityPairPtr else_vv_;
  DataTypePtr result_type_;
  int local_bitmap_idx_;
  bool is_terminal_else_;
};

// decomposed boolean expression.
class GANDIVA_EXPORT BooleanDex : public Dex {
 public:
  BooleanDex(const ValueValidityPairVector& args, int local_bitmap_idx)
      : args_(args), local_bitmap_idx_(local_bitmap_idx) {}

  const ValueValidityPairVector& args() const { return args_; }

  /// The validity of the result is saved in this bitmap.
  int local_bitmap_idx() const { return local_bitmap_idx_; }

 private:
  ValueValidityPairVector args_;
  int local_bitmap_idx_;
};

/// Boolean-AND expression
class GANDIVA_EXPORT BooleanAndDex : public BooleanDex {
 public:
  BooleanAndDex(const ValueValidityPairVector& args, int local_bitmap_idx)
      : BooleanDex(args, local_bitmap_idx) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

/// Boolean-OR expression
class GANDIVA_EXPORT BooleanOrDex : public BooleanDex {
 public:
  BooleanOrDex(const ValueValidityPairVector& args, int local_bitmap_idx)
      : BooleanDex(args, local_bitmap_idx) {}

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }
};

// decomposed in expression.
template <typename Type>
class InExprDex;

template <typename Type>
class InExprDexBase : public Dex {
 public:
  InExprDexBase(const ValueValidityPairVector& args,
                const std::unordered_set<Type>& values)
      : args_(args) {
    in_holder_.reset(new InHolder<Type>(values));
  }

  const ValueValidityPairVector& args() const { return args_; }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

  const std::string& runtime_function() const { return runtime_function_; }

  const std::shared_ptr<InHolder<Type>>& in_holder() const { return in_holder_; }

  void set_holder_idx(int holder_idx) { holder_idx_ = holder_idx; }

  int get_holder_idx() const { return holder_idx_; }

 protected:
  ValueValidityPairVector args_;
  std::string runtime_function_;
  std::shared_ptr<InHolder<Type>> in_holder_;
  int holder_idx_;
};

template <>
class InExprDexBase<gandiva::DecimalScalar128> : public Dex {
 public:
  InExprDexBase(const ValueValidityPairVector& args,
                const std::unordered_set<gandiva::DecimalScalar128>& values,
                int32_t precision, int32_t scale)
      : args_(args), precision_(precision), scale_(scale) {
    in_holder_.reset(new InHolder<gandiva::DecimalScalar128>(values));
  }

  int32_t get_precision() const { return precision_; }

  int32_t get_scale() const { return scale_; }

  const ValueValidityPairVector& args() const { return args_; }

  void Accept(DexVisitor& visitor) override { visitor.Visit(*this); }

  const std::string& runtime_function() const { return runtime_function_; }

  const std::shared_ptr<InHolder<gandiva::DecimalScalar128>>& in_holder() const {
    return in_holder_;
  }

  void set_holder_idx(int holder_idx) { holder_idx_ = holder_idx; }

  int get_holder_idx() const { return holder_idx_; }

 protected:
  ValueValidityPairVector args_;
  std::string runtime_function_;
  std::shared_ptr<InHolder<gandiva::DecimalScalar128>> in_holder_;
  int32_t precision_, scale_;
  int holder_idx_;
};

template <>
class InExprDex<int32_t> : public InExprDexBase<int32_t> {
 public:
  InExprDex(const ValueValidityPairVector& args,
            const std::unordered_set<int32_t>& values)
      : InExprDexBase(args, values) {
    runtime_function_ = "gdv_fn_in_expr_lookup_int32";
  }
};

template <>
class InExprDex<int64_t> : public InExprDexBase<int64_t> {
 public:
  InExprDex(const ValueValidityPairVector& args,
            const std::unordered_set<int64_t>& values)
      : InExprDexBase(args, values) {
    runtime_function_ = "gdv_fn_in_expr_lookup_int64";
  }
};

template <>
class InExprDex<float> : public InExprDexBase<float> {
 public:
  InExprDex(const ValueValidityPairVector& args, const std::unordered_set<float>& values)
      : InExprDexBase(args, values) {
    runtime_function_ = "gdv_fn_in_expr_lookup_float";
  }
};

template <>
class InExprDex<double> : public InExprDexBase<double> {
 public:
  InExprDex(const ValueValidityPairVector& args, const std::unordered_set<double>& values)
      : InExprDexBase(args, values) {
    runtime_function_ = "gdv_fn_in_expr_lookup_double";
  }
};

template <>
class InExprDex<gandiva::DecimalScalar128>
    : public InExprDexBase<gandiva::DecimalScalar128> {
 public:
  InExprDex(const ValueValidityPairVector& args,
            const std::unordered_set<gandiva::DecimalScalar128>& values,
            int32_t precision, int32_t scale)
      : InExprDexBase<gandiva::DecimalScalar128>(args, values, precision, scale) {
    runtime_function_ = "gdv_fn_in_expr_lookup_decimal";
  }
};

template <>
class InExprDex<std::string> : public InExprDexBase<std::string> {
 public:
  InExprDex(const ValueValidityPairVector& args,
            const std::unordered_set<std::string>& values)
      : InExprDexBase(args, values) {
    runtime_function_ = "gdv_fn_in_expr_lookup_utf8";
  }
};

}  // namespace gandiva
