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

std::string get_time_value(const Field& field) {
    using ValueType = typename PrimitiveTypeTraits<TYPE_TIMEV2>::CppType;
    ValueType value = field.get<ValueType>();
    return cast_to_string<TYPE_TIMEV2, ValueType>(value, 0);
}

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

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

    _nulls_first = nulls_first;
    _is_asc = is_asc;
    // 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
    // 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_constructor = is_asc ? create_comparison_predicate<PredicateType::LE>
                               : create_comparison_predicate<PredicateType::GE>;
    _col_name = col_name;

    // set get value function
    switch (type) {
    case PrimitiveType::TYPE_BOOLEAN: {
        _get_value_fn = get_normal_value<TYPE_BOOLEAN>;
        break;
    }
    case PrimitiveType::TYPE_TINYINT: {
        _get_value_fn = get_normal_value<TYPE_TINYINT>;
        break;
    }
    case PrimitiveType::TYPE_SMALLINT: {
        _get_value_fn = get_normal_value<TYPE_SMALLINT>;
        break;
    }
    case PrimitiveType::TYPE_INT: {
        _get_value_fn = get_normal_value<TYPE_INT>;
        break;
    }
    case PrimitiveType::TYPE_BIGINT: {
        _get_value_fn = get_normal_value<TYPE_BIGINT>;
        break;
    }
    case PrimitiveType::TYPE_LARGEINT: {
        _get_value_fn = get_normal_value<TYPE_LARGEINT>;
        break;
    }
    case PrimitiveType::TYPE_CHAR:
    case PrimitiveType::TYPE_VARCHAR:
    case PrimitiveType::TYPE_STRING: {
        _get_value_fn = [](const Field& field) { return field.get<String>(); };
        break;
    }
    case PrimitiveType::TYPE_DATEV2: {
        _get_value_fn = get_normal_value<TYPE_DATEV2>;
        break;
    }
    case PrimitiveType::TYPE_DATETIMEV2: {
        _get_value_fn = get_normal_value<TYPE_DATETIMEV2>;
        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_TIMEV2: {
        _get_value_fn = get_time_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL32: {
        _get_value_fn = get_decimal_value<TYPE_DECIMAL32>;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL64: {
        _get_value_fn = get_decimal_value<TYPE_DECIMAL64>;
        break;
    }
    case PrimitiveType::TYPE_DECIMALV2: {
        _get_value_fn = get_decimalv2_value;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL128I: {
        _get_value_fn = get_decimal_value<TYPE_DECIMAL128I>;
        break;
    }
    case PrimitiveType::TYPE_DECIMAL256: {
        _get_value_fn = get_decimal_value<TYPE_DECIMAL256>;
        break;
    }
    case PrimitiveType::TYPE_IPV4: {
        _get_value_fn = get_normal_value<TYPE_IPV4>;
        break;
    }
    case PrimitiveType::TYPE_IPV6: {
        _get_value_fn = get_normal_value<TYPE_IPV6>;
        break;
    }
    default:
        return Status::InvalidArgument("unsupported runtime predicate type {}", type);
    }

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

Status RuntimePredicate::update(const Field& value) {
    std::unique_lock<std::shared_mutex> wlock(_rwlock);
    // skip null value
    if (value.is_null() || !_inited || !_tablet_schema) {
        return Status::OK();
    }

    bool updated = false;

    if (UNLIKELY(_orderby_extrem.is_null())) {
        _orderby_extrem = value;
        updated = true;
    } else {
        if ((_is_asc && value < _orderby_extrem) || (!_is_asc && value > _orderby_extrem)) {
            _orderby_extrem = value;
            updated = true;
        }
    }

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

    std::unique_ptr<ColumnPredicate> pred {
            _pred_constructor(_tablet_schema->column(_col_name), _predicate->column_id(),
                              _get_value_fn(_orderby_extrem), false, &_predicate_arena)};
    // 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());
    }

    ((SharedPredicate*)_predicate.get())->set_nested(pred.release());

    return Status::OK();
}

} // namespace doris::vectorized
