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

#ifndef QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_
#define QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "expressions/table_generator/GeneratorFunctionHandle.hpp"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "types/containers/ColumnVector.hpp"
#include "types/containers/ColumnVectorsValueAccessor.hpp"
#include "utility/Macros.hpp"

#include "glog/logging.h"

namespace quickstep {

/** \addtogroup Expressions
 *  @{
 */

/**
 * @brief Handle for the instantiated GenerateSeries function.
 */
class GenerateSeriesHandle : public GeneratorFunctionHandle {
 public:
  ~GenerateSeriesHandle() override {};

  int getNumberOfOutputColumns() const override {
    return 1;
  }

  const std::string getOutputColumnName(int index) const override {
    if (index > 0) {
      LOG(FATAL) << "generate_series function has only 1 output column";
    }
    // Use the function name as the column name.
    return getName();
  }

  const Type& getOutputColumnType(int index) const override {
    if (index > 0) {
      LOG(FATAL) << "generate_series function has only 1 output column";
    }
    return type_;
  }

  std::size_t getEstimatedCardinality() const override {
    switch (type_.getTypeID()) {
      case TypeID::kInt: {
        return estimateCardinality<int>();
      }
      case TypeID::kLong: {
        return estimateCardinality<std::int64_t>();
      }
      case TypeID::kFloat: {
        return estimateCardinality<float>();
      }
      case TypeID::kDouble: {
        return estimateCardinality<double>();
      }
      default:
        LOG(FATAL) << "GenerateSeries cannot handle arguments with type "
                   << type_.getName();
    }
    return 0;
  }

  void populateColumns(ColumnVectorsValueAccessor *results) const override {
    DCHECK(results != nullptr);

    // Generate the output column.
    NativeColumnVector *result_vec;
    switch (type_.getTypeID()) {
      case TypeID::kInt: {
        result_vec = generateColumn<int>();
        break;
      }
      case TypeID::kLong: {
        result_vec = generateColumn<std::int64_t>();
        break;
      }
      case TypeID::kFloat: {
        result_vec = generateColumn<float>();
        break;
      }
      case TypeID::kDouble: {
        result_vec = generateColumn<double>();
        break;
      }
      default:
        // Should not reach here -- type checking should be done inside
        // GenerateSeries::createHandle() at query compile time.
        LOG(FATAL) << "GenerateSeries cannot handle arguments with type "
                   << type_.getName();
    }
    // Add the output column into the ColumnVectorsValueAccessor container.
    results->addColumn(result_vec);
  }

 private:
  /**
   * @brief Constructor. A GenerateSeriesHandle object should only be
   *        instantiated inside method GenerateSeries::createHandle().
   *
   * @param func_name The registered name of the GenerateSeries function.
   * @param orig_args The original constant arguments to this function
   * @param type The unified type for the arguments.
   * @param start The start value. Its type should equal unified_type.
   * @param end The end value. Its type should equal unified_type.
   * @param step The step size. Its type should equal unified_type.
   */
  GenerateSeriesHandle(const std::string &func_name,
                       const std::vector<TypedValue> &orig_args,
                       const Type &unified_type,
                       const TypedValue &start,
                       const TypedValue &end,
                       const TypedValue &step)
      : GeneratorFunctionHandle(func_name, orig_args),
        type_(unified_type),
        start_(start),
        end_(end),
        step_(step) {
  }

  template <typename T>
  NativeColumnVector* generateColumn() const {
    T start = start_.getLiteral<T>();
    T end = end_.getLiteral<T>();
    T step = step_.getLiteral<T>();

    DCHECK_NE(step, static_cast<T>(0));
    std::size_t length = static_cast<std::size_t>((end - start) / step + 1);
    DCHECK_GE(length, static_cast<std::size_t>(0));

    NativeColumnVector *result_vec = new NativeColumnVector(type_, length);
    T value = start;
    for (std::size_t i = 0; i < length; ++i) {
      result_vec->appendUntypedValue(&value);
      value += step;
    }
    return result_vec;
  }

  template <typename T>
  std::size_t estimateCardinality() const {
    T step = step_.getLiteral<T>();
    DCHECK_NE(step, static_cast<T>(0));
    return static_cast<std::size_t>(
        (end_.getLiteral<T>() - start_.getLiteral<T>()) / step + 1);
  }

  const Type &type_;
  const TypedValue start_;
  const TypedValue end_;
  const TypedValue step_;

  friend class GenerateSeries;

  DISALLOW_COPY_AND_ASSIGN(GenerateSeriesHandle);
};

/** @} */

}  // namespace quickstep

#endif /* QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_ */
