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

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, const 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_impl(VExprContext* context, const Block* block,
                                             const 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;
}

} // namespace doris
