// 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.
// This file is copied from
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionHelpers.h
// and modified by Doris

#pragma once

#include <cstddef>
#include <tuple>

#include "core/assert_cast.h"
#include "core/block/block.h"
#include "core/block/column_numbers.h"
#include "core/column/column.h"
#include "core/column/column_const.h"
#include "core/data_type/data_type.h"
#include "core/field.h"
#include "core/typeid_cast.h"
#include "core/types.h"

namespace doris {

class IFunction;

/// Methods, that helps dispatching over real column types.

template <typename... Type>
bool check_data_type(const IDataType* data_type) {
    return ((typeid_cast<const Type*>(data_type)) || ...);
}

template <typename Type>
const Type* check_and_get_data_type(const IDataType* data_type) {
    return typeid_cast<const Type*>(data_type);
}

template <typename Type>
const ColumnConst* check_and_get_column_const(const IColumn* column) {
    if (!column || !is_column_const(*column)) {
        return nullptr;
    }

    const auto* res = assert_cast<const ColumnConst*, TypeCheckOnRelease::DISABLE>(column);

    if (!is_column<Type>(&res->get_data_column())) {
        return nullptr;
    }

    return res;
}

template <typename Type>
const Type* check_and_get_column_constData(const IColumn* column) {
    const ColumnConst* res = check_and_get_column_const<Type>(column);

    if (!res) {
        return nullptr;
    }

    return static_cast<const Type*>(&res->get_data_column());
}

template <typename Type>
bool check_column_const(const IColumn* column) {
    return check_and_get_column_const<Type>(column);
}

/// Returns non-nullptr if column is ColumnConst with ColumnString or ColumnFixedString inside.
const ColumnConst* check_and_get_column_const_string_or_fixedstring(const IColumn* column);

/// Transform anything to Field.
template <PrimitiveType T>
    requires(!is_decimal(T))
Field to_field(const typename PrimitiveTypeTraits<T>::CppType& x) {
    return Field::create_field<T>(typename PrimitiveTypeTraits<T>::CppType(x));
}

template <PrimitiveType T>
    requires(is_decimal(T))
Field to_field(const typename PrimitiveTypeTraits<T>::CppType& x, UInt32 scale) {
    return Field::create_field<T>(typename PrimitiveTypeTraits<T>::CppType(x, scale));
}

Columns convert_const_tuple_to_constant_elements(const ColumnConst& column);

/// Returns the copy of a tmp block and temp args order same as args
/// in which only args column each column specified in the "arguments"
/// parameter is replaced with its respective nested column if it is nullable.
std::tuple<Block, ColumnNumbers> create_block_with_nested_columns(const Block& block,
                                                                  const ColumnNumbers& args,
                                                                  const bool need_check_same);

// Same as above and return the new_res loc in tuple
std::tuple<Block, ColumnNumbers, size_t> create_block_with_nested_columns(const Block& block,
                                                                          const ColumnNumbers& args,
                                                                          uint32_t result);

/// Checks argument type at specified index with predicate.
/// throws if there is no argument at specified index or if predicate returns false.
void validate_argument_type(const IFunction& func, const DataTypes& arguments,
                            size_t argument_index, bool (*validator_func)(const IDataType&),
                            const char* expected_type_description);

} // namespace doris
