// 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 "vec/exprs/vbitmap_predicate.h"

#include <cstddef>
#include <utility>

#include "exprs/bitmapfilter_predicate.h"
#include "vec/columns/column.h"
#include "vec/columns/column_nullable.h"
#include "vec/columns/column_vector.h"
#include "vec/common/string_ref.h"
#include "vec/core/block.h"
#include "vec/core/column_numbers.h"
#include "vec/core/column_with_type_and_name.h"
#include "vec/core/columns_with_type_and_name.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type.h"

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

} // namespace doris

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

class VExprContext;

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

doris::Status vectorized::VBitmapPredicate::prepare(doris::RuntimeState* state,
                                                    const RowDescriptor& desc,
                                                    vectorized::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 vectorized::VBitmapPredicate::open(doris::RuntimeState* state,
                                                 vectorized::VExprContext* context,
                                                 FunctionContext::FunctionStateScope scope) {
    DCHECK(_prepare_finished);
    RETURN_IF_ERROR(VExpr::open(state, context, scope));
    _open_finished = true;
    return Status::OK();
}

Status VBitmapPredicate::execute_column(VExprContext* context, const Block* block, size_t count,
                                        ColumnPtr& result_column) const {
    DCHECK(_open_finished || block == nullptr);
    DCHECK_EQ(_children.size(), 1);

    ColumnPtr argument_column;
    RETURN_IF_ERROR(_children[0]->execute_column(context, block, 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);
    } else {
        _filter->find_batch(argument_column->get_raw_data().data, nullptr, sz, ptr);
    }

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

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

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

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

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