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

#include "common/status.h"
#include "core/column/column_string.h"
#include "core/column/column_vector.h"
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_decimal.h"
#include "core/data_type/data_type_number.h"
#include "exprs/function/function.h"
#include "exprs/function/function_helpers.h"

namespace doris {

template <typename ToDataType, typename Impl>
class FunctionVariadicArgumentsBase : public IFunction {
public:
    static constexpr auto name = Impl::name;
    String get_name() const override { return name; }
    static FunctionPtr create() { return std::make_shared<FunctionVariadicArgumentsBase>(); }
    bool is_variadic() const override { return true; }
    size_t get_number_of_arguments() const override { return 0; }

    DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override {
        DataTypePtr res;
        if constexpr (IsDataTypeDecimalV2<ToDataType>) {
            res = create_decimal(27, 9, true);
            if (!res) {
                throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
                                       "Something wrong with create_decimal in function {}",
                                       get_name());
                __builtin_unreachable();
            }
        } else {
            res = std::make_shared<ToDataType>();
        }
        return res;
    }

    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                        uint32_t result, size_t input_rows_count) const override {
        ToDataType to_type;
        auto column = to_type.create_column();
        column->reserve(input_rows_count);

        if (arguments.empty()) {
            RETURN_IF_ERROR(Impl::empty_apply(column->assume_mutable_ref(), input_rows_count));
        } else {
            const ColumnWithTypeAndName& first_col = block.get_by_position(arguments[0]);
            RETURN_IF_ERROR(Impl::first_apply(first_col.type.get(), first_col.column.get(),
                                              input_rows_count, column->assume_mutable_ref()));

            for (size_t i = 1; i < arguments.size(); ++i) {
                const ColumnWithTypeAndName& col = block.get_by_position(arguments[i]);
                RETURN_IF_ERROR(Impl::combine_apply(col.type.get(), col.column.get(),
                                                    input_rows_count,
                                                    column->assume_mutable_ref()));
            }
        }

        block.get_by_position(result).column = std::move(column);
        return Status::OK();
    }
};
} // namespace doris
