// 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/table_function/vexplode_numbers.h"

#include <glog/logging.h>

#include <ostream>

#include "common/status.h"
#include "core/assert_cast.h"
#include "core/block/block.h"
#include "core/block/column_with_type_and_name.h"
#include "core/column/column.h"
#include "core/column/column_const.h"
#include "core/column/column_nullable.h"
#include "core/string_ref.h"
#include "exprs/vexpr.h"
#include "exprs/vexpr_context.h"
#include "runtime/runtime_state.h"

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

VExplodeNumbersTableFunction::VExplodeNumbersTableFunction() {
    _fn_name = "vexplode_numbers";
}

Status VExplodeNumbersTableFunction::process_init(Block* block, RuntimeState* state) {
    CHECK(_expr_context->root()->children().size() == 1)
            << "VExplodeNumbersTableFunction must be have 1 children but have "
            << _expr_context->root()->children().size();

    RETURN_IF_ERROR(_expr_context->root()->children()[0]->execute_column(
            _expr_context.get(), block, nullptr, block->rows(), _value_column));
    if (is_column_const(*_value_column)) {
        _cur_size = 0;

        // the argument columns -> Int32
        const auto& column_nested =
                assert_cast<const ColumnConst&>(*_value_column).get_data_column_ptr();
        if (column_nested->is_nullable()) {
            if (!column_nested->is_null_at(0)) {
                _cur_size = assert_cast<const ColumnInt32*>(
                                    assert_cast<const ColumnNullable*>(column_nested.get())
                                            ->get_nested_column_ptr()
                                            .get())
                                    ->get_element(0);
            }
        } else {
            _cur_size = assert_cast<const ColumnInt32*>(column_nested.get())->get_element(0);
        }

        ((ColumnInt32*)_elements_column.get())->clear();
        //_cur_size may be a negative number
        _cur_size = std::max(static_cast<int64_t>(0L), _cur_size);
        if (_cur_size &&
            _cur_size <= state->batch_size()) { // avoid elements_column too big or empty
            _is_const = true;                   // use const optimize
            for (int i = 0; i < _cur_size; i++) {
                ((ColumnInt32*)_elements_column.get())->insert_value(i);
            }
        }
    }
    return Status::OK();
}

void VExplodeNumbersTableFunction::process_row(size_t row_idx) {
    TableFunction::process_row(row_idx);
    if (_is_const) {
        return;
    }

    StringRef value = _value_column->get_data_at(row_idx);
    if (value.data != nullptr) {
        _cur_size = std::max(0, *reinterpret_cast<const int*>(value.data));
    }
}

void VExplodeNumbersTableFunction::process_close() {
    _value_column = nullptr;
}

void VExplodeNumbersTableFunction::get_same_many_values(MutableColumnPtr& column, int length) {
    if (current_empty()) {
        column->insert_many_defaults(length);
    } else {
        // for explode numbers, the argument is int32. so cast is safe.
        if (_is_nullable) {
            assert_cast<ColumnInt32*>(
                    assert_cast<ColumnNullable*>(column.get())->get_nested_column_ptr().get())
                    ->insert_many_vals(static_cast<int32_t>(_cur_offset), length);
            assert_cast<ColumnUInt8*>(
                    assert_cast<ColumnNullable*>(column.get())->get_null_map_column_ptr().get())
                    ->insert_many_defaults(length);
        } else {
            assert_cast<ColumnInt32*>(column.get())
                    ->insert_many_vals(static_cast<int32_t>(_cur_offset), length);
        }
    }
}

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