// 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 "core/data_type/data_type_number.h"
#include "core/data_type/primitive_type.h"
#include "exprs/function/simple_function_factory.h"
#include "util/jsonb_document.h"

namespace doris {

void json_hash(const JsonbValue* jsonb_value, size_t& hash_value) {
    auto update_hash = [&hash_value](const void* data, size_t size) {
        hash_value = HashUtil::hash64(data, (uint32_t)size, hash_value);
    };

    if (jsonb_value->isObject()) {
        hash_value ^= (size_t)JsonbType::T_Object;
        const auto* obj_val = jsonb_value->unpack<ObjectVal>();
        const auto ordered = obj_val->get_ordered_key_value_pairs();
        for (const auto& [key, value] : ordered) {
            update_hash(key.data, key.size);
            json_hash(value, hash_value);
        }
    } else if (jsonb_value->isArray()) {
        hash_value ^= (size_t)JsonbType::T_Array;
        const auto* array_val = jsonb_value->unpack<ArrayVal>();
        for (auto it = array_val->begin(); it != array_val->end(); ++it) {
            json_hash(&*it, hash_value);
        }
    } else {
        // Similar to the code below
        // bool writeValue(const JsonbValue* value) {
        // ...
        //         os_->write((char*)value, value->numPackedBytes());
        // ...
        // }
        // The hash value of the whole structure is directly calculated here, and the Type of Jsonb is included.
        update_hash((const char*)jsonb_value, jsonb_value->numPackedBytes());
    }
}

class FunctionJsonHash : public IFunction {
public:
    static constexpr auto name = "json_hash";

    static FunctionPtr create() { return std::make_shared<FunctionJsonHash>(); }

    String get_name() const override { return name; }

    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
        return std::make_shared<DataTypeInt64>();
    }

    size_t get_number_of_arguments() const override { return 1; }

    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                        uint32_t result, size_t size) const override {
        auto input_column = block.get_by_position(arguments[0]).column;
        auto to_column = ColumnInt64::create(size);
        auto& to_column_data = to_column->get_data();

        const auto& input_jsonb_column = assert_cast<const ColumnString&>(*input_column);

        for (size_t i = 0; i < size; ++i) {
            StringRef val = input_jsonb_column.get_data_at(i);
            const JsonbDocument* doc = nullptr;
            auto st = JsonbDocument::checkAndCreateDocument(val.data, val.size, &doc);
            if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] {
                // mayby be invalid jsonb, just insert default
                // invalid jsonb value may be caused by the default null processing
                continue;
            }

            size_t hash_value = 0;
            json_hash(doc->getValue(), hash_value);

            to_column_data[i] = static_cast<int64_t>(hash_value);
        }
        block.get_by_position(result).column = std::move(to_column);
        return Status::OK();
    }
};

void register_function_json_hash(SimpleFunctionFactory& factory) {
    factory.register_function<FunctionJsonHash>();

    factory.register_alias(FunctionJsonHash::name, "jsonb_hash");
}

} // namespace doris
