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

#include "common/cast_set.h"
#include "common/status.h"
#include "pipeline/local_exchange/local_exchange_sink_operator.h"
#include "runtime/thread_context.h"
#include "vec/columns/column_const.h"
#include "vec/sink/vdata_stream_sender.h"

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

template <typename ChannelIds>
Status Crc32HashPartitioner<ChannelIds>::do_partitioning(RuntimeState* state, Block* block,
                                                         bool eos, bool* already_sent) const {
    size_t rows = block->rows();

    if (rows > 0) {
        auto column_to_keep = block->columns();

        int result_size = cast_set<int>(_partition_expr_ctxs.size());
        std::vector<int> result(result_size);

        _initialize_hash_vals(rows);
        auto* __restrict hashes = _hash_vals.data();
        RETURN_IF_ERROR(_get_partition_column_result(block, result));
        for (int j = 0; j < result_size; ++j) {
            const auto& [col, is_const] = unpack_if_const(block->get_by_position(result[j]).column);
            if (is_const) {
                continue;
            }
            _do_hash(col, hashes, j);
        }

        for (size_t i = 0; i < rows; i++) {
            hashes[i] = ChannelIds()(hashes[i], _partition_count);
        }

        Block::erase_useless_column(block, column_to_keep);
    }
    return Status::OK();
}

template <typename ChannelIds>
void Crc32HashPartitioner<ChannelIds>::_do_hash(const ColumnPtr& column,
                                                uint32_t* __restrict result, int idx) const {
    column->update_crcs_with_value(
            result, _partition_expr_ctxs[idx]->root()->data_type()->get_primitive_type(),
            cast_set<uint32_t>(column->size()));
}

template <typename ChannelIds>
Status Crc32HashPartitioner<ChannelIds>::clone(RuntimeState* state,
                                               std::unique_ptr<PartitionerBase>& partitioner) {
    auto* new_partitioner = new Crc32HashPartitioner<ChannelIds>(cast_set<int>(_partition_count));
    partitioner.reset(new_partitioner);
    return _clone_expr_ctxs(state, new_partitioner->_partition_expr_ctxs);
}

void Crc32CHashPartitioner::_do_hash(const ColumnPtr& column, uint32_t* __restrict result,
                                     int idx) const {
    column->update_crc32c_batch(result, nullptr);
}

Status Crc32CHashPartitioner::clone(RuntimeState* state,
                                    std::unique_ptr<PartitionerBase>& partitioner) {
    auto* new_partitioner = new Crc32CHashPartitioner(cast_set<int>(_partition_count));
    partitioner.reset(new_partitioner);
    return _clone_expr_ctxs(state, new_partitioner->_partition_expr_ctxs);
}

template class Crc32HashPartitioner<ShuffleChannelIds>;
template class Crc32HashPartitioner<SpillPartitionChannelIds>;

} // namespace doris::vectorized
