// 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 "runtime/runtime_predicate.h"

#include <stdint.h>

#include <memory>

#include "common/compiler_util.h" // IWYU pragma: keep
#include "olap/accept_null_predicate.h"
#include "olap/column_predicate.h"
#include "olap/predicate_creator.h"

namespace doris {

namespace vectorized {

Status RuntimePredicate::init(const PrimitiveType type, const bool nulls_first) {
    std::unique_lock<std::shared_mutex> wlock(_rwlock);

    if (_inited) {
        return Status::OK();
    }

    _nulls_first = nulls_first;

    _predicate_arena.reset(new Arena());

    // set get value function
    switch (type) {
    case PrimitiveType::TYPE_BOOLEAN: {
        _get_value_fn = get_bool_value;
        break;
    }
    case PrimitiveType::TYPE_TINYINT: {
        _get_value_fn = get_tinyint_value;
        break;
    }
    case PrimitiveType::TYPE_SMALLINT: {
        _get_value_fn = get_smallint_value;
        break;
    }
    case PrimitiveType::TYPE_INT: {
        _get_value_fn = get_int_value;
        break;
    }
    case PrimitiveType::TYPE_BIGINT: {
        _get_value_fn = get_bigint_value;
        break;
    }
    case PrimitiveType::TYPE_LARGEINT: {
        _get_value_fn = get_largeint_value;
        break;
    }
    case PrimitiveType::TYPE_FLOAT: {
        _get_value_fn = get_float_value;
        break;
    }
    case PrimitiveType::TYPE_DOUBLE: {
        _get_value_fn = get_double_value;
        break;
    }
    case PrimitiveType::TYPE_STRING: {
        _get_value_fn = get_string_value;
        break;
    }
    case PrimitiveType::TYPE_DATEV2: {
        _get_value_fn = get_datev2_value;
        break;
    }
    case PrimitiveType::TYPE_DATETIMEV2: {
        _get_value_fn = get_datetimev2_value;
        break;
    }
    case PrimitiveType::TYPE_DATE: {
        _get_value_fn = get_date_value;
        break;
    }
    case PrimitiveType::TYPE_DATETIME: {
        _get_value_fn = get_datetime_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL32: {
        _get_value_fn = get_decimal32_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL64: {
        _get_value_fn = get_decimal64_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMALV2: {
        _get_value_fn = get_decimalv2_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL128I: {
        _get_value_fn = get_decimal128_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL256: {
        _get_value_fn = get_decimal256_value;
        break;
    }
    case PrimitiveType::TYPE_IPV4: {
        _get_value_fn = get_ipv4_value;
        break;
    }
    case PrimitiveType::TYPE_IPV6: {
        _get_value_fn = get_ipv6_value;
        break;
    }
    default:
        return Status::InvalidArgument("unsupported runtime predicate type {}", type);
    }

    _inited = true;
    return Status::OK();
}

Status RuntimePredicate::update(const Field& value, const String& col_name, bool is_reverse) {
    // skip null value
    if (value.is_null()) {
        return Status::OK();
    }

    if (!_inited) {
        return Status::OK();
    }

    std::unique_lock<std::shared_mutex> wlock(_rwlock);

    bool updated = false;

    if (UNLIKELY(_orderby_extrem.is_null())) {
        _orderby_extrem = value;
        updated = true;
    } else if (is_reverse) {
        if (value > _orderby_extrem) {
            _orderby_extrem = value;
            updated = true;
        }
    } else {
        if (value < _orderby_extrem) {
            _orderby_extrem = value;
            updated = true;
        }
    }

    if (!updated) {
        return Status::OK();
    }

    // TODO defensive code
    if (!_tablet_schema || !_tablet_schema->have_column(col_name)) {
        return Status::OK();
    }
    // update _predictate
    int32_t col_unique_id = _tablet_schema->column(col_name).unique_id();
    const TabletColumn& column = _tablet_schema->column_by_uid(col_unique_id);
    uint32_t index = _tablet_schema->field_index(col_unique_id);
    auto val = _get_value_fn(_orderby_extrem);
    std::unique_ptr<ColumnPredicate> pred {nullptr};
    if (is_reverse) {
        // For DESC sort, create runtime predicate col_name >= min_top_value
        // since values that < min_top_value are less than any value in current topn values
        pred.reset(create_comparison_predicate<PredicateType::GE>(column, index, val, false,
                                                                  _predicate_arena.get()));
    } else {
        // For ASC  sort, create runtime predicate col_name <= max_top_value
        // since values that > min_top_value are large than any value in current topn values
        pred.reset(create_comparison_predicate<PredicateType::LE>(column, index, val, false,
                                                                  _predicate_arena.get()));
    }

    // For NULLS FIRST, wrap a AcceptNullPredicate to return true for NULL
    // since ORDER BY ASC/DESC should get NULL first but pred returns NULL
    // and NULL in where predicate will be treated as FALSE
    if (_nulls_first) {
        pred = AcceptNullPredicate::create_unique(pred.release());
    }
    _predictate.reset(pred.release());

    return Status::OK();
}

} // namespace vectorized
} // namespace doris
