// 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 "storage/predicate/null_predicate.h"

#include <string.h>

#include <roaring/roaring.hh>

#include "core/column/column.h"
#include "core/column/column_nullable.h"
#include "core/value/vdatetime_value.h"
#include "storage/index/inverted/inverted_index_cache.h"
#include "storage/index/inverted/inverted_index_reader.h"

using namespace doris;

namespace doris {

NullPredicate::NullPredicate(uint32_t column_id, std::string col_name, bool is_null,
                             PrimitiveType type, bool opposite)
        : ColumnPredicate(column_id, col_name, type), _is_null(opposite != is_null) {}

PredicateType NullPredicate::type() const {
    return _is_null ? PredicateType::IS_NULL : PredicateType::IS_NOT_NULL;
}

Status NullPredicate::evaluate(const IndexFieldNameAndTypePair& name_with_type,
                               IndexIterator* iterator, uint32_t num_rows,
                               roaring::Roaring* bitmap) const {
    if (iterator->has_null()) {
        InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
        RETURN_IF_ERROR(iterator->read_null_bitmap(&null_bitmap_cache_handle));
        std::shared_ptr<roaring::Roaring> null_bitmap = null_bitmap_cache_handle.get_bitmap();

        if (null_bitmap) {
            if (_is_null) {
                *bitmap &= *null_bitmap; // Keep only nulls in bitmap if _is_null is true
            } else {
                *bitmap -= *null_bitmap; // Remove nulls from bitmap if _is_null is false
            }
        } else if (_is_null) {
            *bitmap = roaring::Roaring(); // Reset bitmap to an empty bitmap
        }
    } else if (_is_null) {
        *bitmap = roaring::Roaring(); // Reset bitmap to an empty bitmap
    }

    return Status::OK();
}

uint16_t NullPredicate::_evaluate_inner(const IColumn& column, uint16_t* sel, uint16_t size) const {
    uint16_t new_size = 0;
    if (auto* nullable = check_and_get_column<ColumnNullable>(column)) {
        if (!nullable->has_null()) {
            return _is_null ? 0 : size;
        }
        auto& pred_col = nullable->get_null_map_data();
        constexpr bool is_nullable = true;
        auto with_null = [&](uint16_t idx) { return pred_col[idx] == _is_null; };
        auto without_null = [](uint16_t) { return true; };
        evaluate_by_selector<is_nullable>(pred_col, size, sel, new_size, with_null, without_null);
        return new_size;
    } else {
        if (_is_null) return 0;
    }
    return size;
}

void NullPredicate::evaluate_or(const IColumn& column, const uint16_t* sel, uint16_t size,
                                bool* flags) const {
    if (auto* nullable = check_and_get_column<ColumnNullable>(column)) {
        if (!nullable->has_null()) {
            if (!_is_null) {
                memset(flags, true, size);
            }
        } else {
            auto& null_map = nullable->get_null_map_data();
            for (uint16_t i = 0; i < size; ++i) {
                if (flags[i]) continue;
                uint16_t idx = sel[i];
                flags[i] |= (null_map[idx] == _is_null);
            }
        }
    } else {
        if (!_is_null) memset(flags, true, size);
    }
}

void NullPredicate::evaluate_and(const IColumn& column, const uint16_t* sel, uint16_t size,
                                 bool* flags) const {
    if (auto* nullable = check_and_get_column<ColumnNullable>(column)) {
        if (!nullable->has_null()) {
            if (_is_null) {
                memset(flags, false, size);
            }
        } else {
            auto& null_map = nullable->get_null_map_data();
            for (uint16_t i = 0; i < size; ++i) {
                if (flags[i]) continue;
                uint16_t idx = sel[i];
                flags[i] &= (null_map[idx] == _is_null);
            }
        }
    } else {
        if (_is_null) memset(flags, false, size);
    }
}

void NullPredicate::evaluate_vec(const IColumn& column, uint16_t size, bool* flags) const {
    if (auto* nullable = check_and_get_column<ColumnNullable>(column)) {
        if (!nullable->has_null()) {
            memset(flags, !_is_null, size);
        }
        auto& null_map = nullable->get_null_map_data();
        for (uint16_t i = 0; i < size; ++i) {
            flags[i] = (null_map[i] == _is_null);
        }
    } else {
        if (_is_null) memset(flags, false, size);
    }
}

} //namespace doris
