// 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.

#pragma once

#include <fmt/format.h>
#include <gen_cpp/Types_types.h>
#include <stddef.h>

#include <memory>
#include <string>
#include <vector>

#include "common/status.h"
#include "core/block/block.h"
#include "core/block/column_numbers.h"
#include "core/block/column_with_type_and_name.h"
#include "core/block/columns_with_type_and_name.h"
#include "core/data_type/data_type.h"
#include "core/types.h"
#include "exprs/function/function.h"
#include "exprs/function_context.h"

namespace doris {
class PFunctionCallRequest;
class PFunctionService_Stub;
class PValues;
} // namespace doris

namespace doris {

class RPCFnImpl {
public:
    RPCFnImpl(const TFunction& fn);
    ~RPCFnImpl() = default;
    Status vec_call(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                    uint32_t result, size_t input_rows_count);
    bool available() { return _client != nullptr; }

private:
    Status _convert_block_to_proto(Block& block, const ColumnNumbers& arguments,
                                   size_t input_rows_count, PFunctionCallRequest* request);
    Status _convert_to_block(Block& block, const PValues& result, size_t pos);

    std::shared_ptr<PFunctionService_Stub> _client;
    std::string _function_name;
    std::string _server_addr;
    std::string _signature;
    TFunction _fn;
};

class RPCPreparedFunction : public IPreparedFunction {
public:
    ~RPCPreparedFunction() override = default;

    /// Get the main function name.
    String get_name() const override { return "RPCPreparedFunction: "; }

    Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                   uint32_t result, size_t input_rows_count) const override {
        auto* fn = reinterpret_cast<RPCFnImpl*>(
                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
        return fn->vec_call(context, block, arguments, result, input_rows_count);
    }
};

class FunctionRPC : public IFunctionBase {
public:
    FunctionRPC(const TFunction& fn, const DataTypes& argument_types,
                const DataTypePtr& return_type);

    static FunctionBasePtr create(const TFunction& fn, const ColumnsWithTypeAndName& argument_types,
                                  const DataTypePtr& return_type) {
        DataTypes data_types(argument_types.size());
        for (size_t i = 0; i < argument_types.size(); ++i) {
            data_types[i] = argument_types[i].type;
        }
        return std::make_shared<FunctionRPC>(fn, data_types, return_type);
    }

    /// Get the main function name.
    String get_name() const override {
        return fmt::format("{}: [{}/{}]", _tfn.name.function_name, _tfn.hdfs_location,
                           _tfn.scalar_fn.symbol);
    }

    const DataTypes& get_argument_types() const override { return _argument_types; }
    const DataTypePtr& get_return_type() const override { return _return_type; }

    PreparedFunctionPtr prepare(FunctionContext* context, const Block& sample_block,
                                const ColumnNumbers& arguments, uint32_t result) const override {
        return std::make_shared<RPCPreparedFunction>();
    }

    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override;

    bool is_use_default_implementation_for_constants() const override { return true; }

private:
    DataTypes _argument_types;
    DataTypePtr _return_type;
    TFunction _tfn;
};

} // namespace doris
