// 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/Ifnull.h
// and modified by Doris

#pragma once

#include <stddef.h>

#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
#include <memory>

#include "common/status.h"
#include "core/block/block.h"
#include "core/block/column_numbers.h"
#include "core/block/column_with_type_and_name.h"
#include "core/block/columns_with_type_and_name.h"
#include "core/column/column.h"
#include "core/column/column_nullable.h"
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_nullable.h"
#include "core/data_type/data_type_number.h"
#include "core/types.h"
#include "exprs/aggregate/aggregate_function.h"
#include "exprs/function/function.h"
#include "exprs/function/simple_function_factory.h"
#include "runtime/runtime_state.h"

namespace doris {
class FunctionContext;
} // namespace doris

namespace doris {
class FunctionIfNull : public IFunction {
public:
    static constexpr auto name = "ifnull";

    static FunctionPtr create() { return std::make_shared<FunctionIfNull>(); }

    String get_name() const override { return name; }

    size_t get_number_of_arguments() const override { return 2; }

    // be compatible with fe code
    /* 
        if (fn.functionName().equalsIgnoreCase("ifnull") || fn.functionName().equalsIgnoreCase("nvl")) {
            Preconditions.checkState(children.size() == 2);
            if (children.get(0).isNullable()) {
                return children.get(1).isNullable();
            }
            return false;
        }
    */
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
        if (arguments[0]->is_nullable()) {
            return arguments[1];
        }
        return arguments[0];
    }

    bool use_default_implementation_for_nulls() const override { return false; }

    // ifnull(col_left, col_right) == if(isnull(col_left), col_right, col_left)
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                        uint32_t result, size_t input_rows_count) const override {
        ColumnWithTypeAndName& col_left = block.get_by_position(arguments[0]);
        if (col_left.column->only_null()) {
            // Here we need to use convert_to_full_column_if_const because only_null() is a runtime function.
            // If the second parameter is constant, it will cause the execution to rely on runtime information to determine whether it is constant.
            block.get_by_position(result).column =
                    block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
            return Status::OK();
        }

        ColumnWithTypeAndName null_column_arg0 {nullptr, std::make_shared<DataTypeUInt8>(), ""};
        ColumnWithTypeAndName nested_column_arg0 {nullptr, col_left.type, ""};

        col_left.column = col_left.column->convert_to_full_column_if_const();

        /// implement isnull(col_left) logic
        if (auto* nullable = check_and_get_column<ColumnNullable>(*col_left.column)) {
            null_column_arg0.column = nullable->get_null_map_column_ptr();
            nested_column_arg0.column = nullable->get_nested_column_ptr();
            nested_column_arg0.type =
                    reinterpret_cast<const DataTypeNullable*>(nested_column_arg0.type.get())
                            ->get_nested_type();
        } else {
            block.get_by_position(result).column = col_left.column;
            return Status::OK();
        }
        const ColumnsWithTypeAndName if_columns {
                null_column_arg0, block.get_by_position(arguments[1]), nested_column_arg0};

        // see get_return_type_impl
        // if result is nullable, means both then and else column are nullable, we use original col_left to keep nullable info
        // if result is not nullable, means both then and else column are not nullable, we use nested_column_arg0 to remove nullable info
        bool result_nullable = block.get_by_position(result).type->is_nullable();
        Block temporary_block({
                null_column_arg0,
                block.get_by_position(arguments[1]),
                result_nullable
                        ? col_left
                        : nested_column_arg0, // if result is nullable, we need pass the original col_left else pass nested_column_arg0
                block.get_by_position(result),
        });

        auto func_if = SimpleFunctionFactory::instance().get_function(
                "if", if_columns, block.get_by_position(result).type, {});
        RETURN_IF_ERROR(func_if->execute(context, temporary_block, {0, 1, 2}, 3, input_rows_count));
        block.get_by_position(result).column = temporary_block.get_by_position(3).column;
        return Status::OK();
    }
};
} // namespace doris
