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

#include "exprs/vbitmap_predicate.h"

#include <cstddef>
#include <utility>

#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/column/column_vector.h"
#include "core/data_type/data_type.h"
#include "core/string_ref.h"
#include "core/types.h"
#include "exprs/bitmapfilter_predicate.h"

namespace doris {
class RowDescriptor;
class RuntimeState;
class TExprNode;

} // namespace doris

namespace doris {
#include "common/compile_check_begin.h"

class VExprContext;

VBitmapPredicate::VBitmapPredicate(const TExprNode& node) : VExpr(node), _filter(nullptr) {}

doris::Status VBitmapPredicate::prepare(doris::RuntimeState* state, const RowDescriptor& desc,
                                        VExprContext* context) {
    RETURN_IF_ERROR_OR_PREPARED(VExpr::prepare(state, desc, context));

    if (_children.size() != 1) {
        return Status::InternalError("Invalid argument for VBitmapPredicate.");
    }

    ColumnsWithTypeAndName argument_template;
    argument_template.reserve(_children.size());
    for (auto child : _children) {
        auto column = child->data_type()->create_column();
        argument_template.emplace_back(std::move(column), child->data_type(), child->expr_name());
    }
    _prepare_finished = true;
    return Status::OK();
}

doris::Status VBitmapPredicate::open(doris::RuntimeState* state, VExprContext* context,
                                     FunctionContext::FunctionStateScope scope) {
    DCHECK(_prepare_finished);
    RETURN_IF_ERROR(VExpr::open(state, context, scope));
    _open_finished = true;
    return Status::OK();
}

Status VBitmapPredicate::_do_execute(VExprContext* context, const Block* block,
                                     const uint8_t* __restrict filter, Selector* selector,
                                     size_t count, ColumnPtr& result_column) const {
    DCHECK(_open_finished || block == nullptr);
    DCHECK(!(filter != nullptr && selector != nullptr))
            << "filter and selector can not be both set";
    DCHECK_EQ(_children.size(), 1);

    ColumnPtr argument_column;
    RETURN_IF_ERROR(_children[0]->execute_column(context, block, selector, count, argument_column));
    argument_column = argument_column->convert_to_full_column_if_const();

    size_t sz = argument_column->size();
    auto res_data_column = ColumnUInt8::create(sz);
    res_data_column->resize(sz);
    auto* ptr = res_data_column->get_data().data();

    if (argument_column->is_nullable()) {
        auto column_nested =
                assert_cast<const ColumnNullable*>(argument_column.get())->get_nested_column_ptr();
        auto column_nullmap = assert_cast<const ColumnNullable*>(argument_column.get())
                                      ->get_null_map_column_ptr();
        _filter->find_batch(column_nested->get_raw_data().data,
                            (uint8_t*)column_nullmap->get_raw_data().data, sz, ptr, filter);
    } else {
        _filter->find_batch(argument_column->get_raw_data().data, nullptr, sz, ptr, filter);
    }

    result_column = std::move(res_data_column);
    DCHECK_EQ(result_column->size(), count);
    return Status::OK();
}

Status VBitmapPredicate::execute_column(VExprContext* context, const Block* block,
                                        Selector* selector, size_t count,
                                        ColumnPtr& result_column) const {
    return _do_execute(context, block, nullptr, selector, count, result_column);
}

Status VBitmapPredicate::execute_runtime_filter(VExprContext* context, const Block* block,
                                                const uint8_t* __restrict filter, size_t count,
                                                ColumnPtr& result_column,
                                                ColumnPtr* arg_column) const {
    return _do_execute(context, block, filter, nullptr, count, result_column);
}

void VBitmapPredicate::close(VExprContext* context, FunctionContext::FunctionStateScope scope) {
    VExpr::close(context, scope);
}

const std::string& VBitmapPredicate::expr_name() const {
    return EXPR_NAME;
}

void VBitmapPredicate::set_filter(std::shared_ptr<BitmapFilterFuncBase> filter) {
    _filter = filter;
}

#include "common/compile_check_end.h"
} // namespace doris
