// 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 <cstddef>
#include <limits>
#include <type_traits>

#include "common/exception.h"
#include "common/status.h"
#include "core/column/column_const.h"
#include "core/column/column_vector.h"
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_number.h"
#include "core/data_type/data_type_string.h"
#include "core/data_type/primitive_type.h"
#include "core/types.h"
#include "exprs/function/function.h"
#include "exprs/function/function_helpers.h"
#include "exprs/function/simple_function_factory.h"
#include "util/simd/reverse_copy_bytes.h"

namespace doris {

struct EncodeAsSmallInt {
    static constexpr auto name = "encode_as_smallint";
};

struct EncodeAsInt {
    static constexpr auto name = "encode_as_int";
};

struct EncodeAsBigInt {
    static constexpr auto name = "encode_as_bigint";
};

struct EncodeAsLargeInt {
    static constexpr auto name = "encode_as_largeint";
};

template <typename Name, PrimitiveType ReturnType>
class FunctionEncodeVarchar : public IFunction {
public:
    static constexpr auto name = Name::name;
    static FunctionPtr create() { return std::make_shared<FunctionEncodeVarchar>(); }

    String get_name() const override { return name; }

    size_t get_number_of_arguments() const override { return 1; }

    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
        return std::make_shared<typename PrimitiveTypeTraits<ReturnType>::DataType>();
    }

    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                        uint32_t result, size_t input_rows_count) const override {
        const ColumnString* col_str =
                assert_cast<const ColumnString*>(block.get_by_position(arguments[0]).column.get());

        // max_row_byte_size = size of string + size of offset value
        size_t max_str_size = col_str->get_max_row_byte_size() - sizeof(UInt32);

        if (max_str_size > sizeof(typename PrimitiveTypeTraits<ReturnType>::CppType) - 1) {
            return Status::InternalError(
                    "String is too long to encode, input string size {}, max valid string "
                    "size for {} is {}",
                    max_str_size, name,
                    sizeof(typename PrimitiveTypeTraits<ReturnType>::CppType) - 1);
        }

        auto col_res = PrimitiveTypeTraits<ReturnType>::ColumnType::create(input_rows_count, 0);
        auto& col_res_data = col_res->get_data();

        for (size_t i = 0; i < input_rows_count; ++i) {
            const char* str_ptr = col_str->get_data_at(i).data;
            auto str_size = static_cast<UInt8>(col_str->get_data_at(i).size);
            auto* res = &col_res_data[i];
            auto* __restrict ui8_ptr = reinterpret_cast<UInt8*>(res);

            // "reverse" the order of string on little endian machine.
            simd::reverse_copy_bytes(ui8_ptr,
                                     sizeof(typename PrimitiveTypeTraits<ReturnType>::CppType),
                                     str_ptr, str_size);
            // Lowest byte of Integer stores the size of the string, bit left shiflted by 1 so that we can get
            // correct size after right shifting by 1
            memset(ui8_ptr, str_size << 1, 1);
            *res >>= 1;
            // operator &= can not be applied to Int128
            *res = *res &
                   std::numeric_limits<typename PrimitiveTypeTraits<ReturnType>::CppType>::max();
        }

        block.get_by_position(result).column = std::move(col_res);

        return Status::OK();
    }
};

void register_function_encode_varchar(SimpleFunctionFactory& factory) {
    factory.register_function<FunctionEncodeVarchar<EncodeAsSmallInt, TYPE_SMALLINT>>();
    factory.register_function<FunctionEncodeVarchar<EncodeAsInt, TYPE_INT>>();
    factory.register_function<FunctionEncodeVarchar<EncodeAsBigInt, TYPE_BIGINT>>();
    factory.register_function<FunctionEncodeVarchar<EncodeAsLargeInt, TYPE_LARGEINT>>();
}

} // namespace doris
