// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <pybind11/pybind11.h>

#ifdef _MSC_VER
    // Warning occurred at the junction of pybind11 
    // and the templates inside ov::Any.
    // Generated by operator `==` inside pybind::handle.
    #pragma warning( push )
    #pragma warning( disable: 4996 )
#elif defined(__GNUC__)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "openvino/core/any.hpp"
#ifdef _MSC_VER
    #pragma warning( pop )
#elif defined(__GNUC__)
    #pragma GCC diagnostic pop
#endif

#include "openvino/core/type/element_type.hpp"
#include "openvino/runtime/properties.hpp"
#include "openvino/runtime/auto/properties.hpp"
#include "openvino/pass/serialize.hpp"

namespace py = pybind11;

namespace Common {
namespace utils {
    enum class PY_TYPE : int { UNKNOWN = 0, STR, INT, FLOAT, BOOL, PARTIAL_SHAPE };

    struct EmptyList {};

    PY_TYPE check_list_element_type(const py::list& list);

    py::object from_ov_any_no_leaves(const ov::Any& any);

    py::object from_ov_any_map_no_leaves(const ov::Any& almost_map);

    py::object from_ov_any_map(const ov::AnyMap& map);

    py::object from_ov_any(const ov::Any& any);

    std::map<std::string, ov::Any> properties_to_any_map(const std::map<std::string, py::object>& properties);

    std::string convert_path_to_string(const py::object& path);

    void deprecation_warning(const std::string& function_name, const std::string& version = std::string(), const std::string& message = std::string(), int stacklevel=2);

    void raise_not_implemented();

    bool py_object_is_any_map(const py::object& py_obj);

    ov::AnyMap py_object_to_any_map(const py::object& py_obj);

    ov::Any py_object_to_any(const py::object& py_obj);

    ov::pass::Serialize::Version convert_to_version(const std::string& version);

    std::shared_ptr<py::function> wrap_pyfunction(py::function f_callback);

}; // namespace utils
}; // namespace Common

namespace pybind11 {
namespace ov_extension {
    void conditional_keep_alive_impl(size_t Nurse, size_t Patient, size_t Condition, detail::function_call &call, handle ret);

    // Keep patient alive while nurse lives
    template <size_t Nurse, size_t Patient, size_t Condition>
    struct conditional_keep_alive {};

}; // namespace ov_extension

    // Process a conditional_keep_alive call policy -- invokes conditional_keep_alive_impl during the the pre-call handler
    template <size_t Nurse, size_t Patient, size_t Condition>
    struct detail::process_attribute<ov_extension::conditional_keep_alive<Nurse, Patient, Condition>>
        : public detail::process_attribute_default<ov_extension::conditional_keep_alive<Nurse, Patient, Condition>> {
        static void precall(function_call &call) {
            ov_extension::conditional_keep_alive_impl(Nurse, Patient, Condition, call, handle());
        }
    };

}; // namespace pybind11
