#
# 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
#

"""Interface between python and libqpid-dispatch.so.

This module contains python ctypes definitions to directly call functions in the
libqpid-dispatch.so library from python.

The C library also adds the following C extension types to this module:

- LogAdapter: Logs to the C logging system.
- IoAdapter: Receives messages from the router into python.

This module also prevents the proton python module from being accidentally loaded.
"""
import builtins
import ctypes
import sys
from ctypes import c_char_p, c_long, py_object


class CError(Exception):
    """Exception raised if there is an error in a C call"""
    pass


class QdDll(ctypes.PyDLL):
    """
    Load the library, set up function prototypes.

    NOTE: We use the python calling convention because the C library
    internally makes python calls.
    """

    def __init__(self, handle):
        super(QdDll, self).__init__("qpid-dispatch", handle=handle)

        # Types
        self.qd_dispatch_p = ctypes.c_void_p

        # No check on qd_error_* functions, it would be recursive
        self._prototype(self.qd_error_code, c_long, [], check=False)
        self._prototype(self.qd_error_message, c_char_p, [], check=False)
        self._prototype(self.qd_log_entity, c_long, [py_object])
        self._prototype(self.qd_dispatch_configure_router, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_prepare, None, [self.qd_dispatch_p])
        self._prototype(self.qd_dispatch_configure_listener, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_connector, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_ssl_profile, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_sasl_plugin, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_tcp_listener, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_tcp_connector, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_http_listener, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_http_connector, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_delete_tcp_listener, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_dispatch_delete_tcp_connector, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_dispatch_delete_http_listener, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_dispatch_delete_http_connector, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_connection_manager_delete_listener, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_connection_manager_delete_connector, None, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_connection_manager_delete_ssl_profile, ctypes.c_bool, [self.qd_dispatch_p, ctypes.c_void_p])
        self._prototype(self.qd_connection_manager_delete_sasl_plugin, ctypes.c_bool, [self.qd_dispatch_p, ctypes.c_void_p])

        self._prototype(self.qd_dispatch_configure_address, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_link_route, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_auto_link, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_exchange, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_configure_binding, None, [self.qd_dispatch_p, py_object])

        self._prototype(self.qd_dispatch_configure_policy, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_register_policy_manager, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_policy_c_counts_alloc, c_long, [], check=False)
        self._prototype(self.qd_dispatch_policy_c_counts_free, None, [c_long], check=False)
        self._prototype(self.qd_dispatch_policy_c_counts_refresh, None, [c_long, py_object])
        self._prototype(self.qd_dispatch_policy_host_pattern_add, ctypes.c_bool, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_policy_host_pattern_remove, None, [self.qd_dispatch_p, py_object])
        self._prototype(self.qd_dispatch_policy_host_pattern_lookup, c_char_p, [self.qd_dispatch_p, py_object])

        self._prototype(self.qd_dispatch_register_display_name_service, None, [self.qd_dispatch_p, py_object])

        self._prototype(self.qd_dispatch_set_agent, None, [self.qd_dispatch_p, py_object])

        self._prototype(self.qd_router_setup_late, None, [self.qd_dispatch_p])

        self._prototype(self.qd_dispatch_router_lock, None, [self.qd_dispatch_p])
        self._prototype(self.qd_dispatch_router_unlock, None, [self.qd_dispatch_p])

        self._prototype(self.qd_connection_manager_start, None, [self.qd_dispatch_p])
        self._prototype(self.qd_entity_refresh_begin, c_long, [py_object])
        self._prototype(self.qd_entity_refresh_end, None, [])

        self._prototype(self.qd_log_recent_py, py_object, [c_long])

    def _prototype(self, f, restype, argtypes, check=True):
        """Set up the return and argument types and the error checker for a
        ctypes function"""

        def _do_check(result, func, args):
            if check and self.qd_error_code():
                raise CError(self.qd_error_message())
            if restype is c_char_p and result:
                # in python3 c_char_p returns a byte type for the error
                # message. We need to convert that to a string
                result = result.decode('utf-8')
            return result

        f.restype = restype
        f.argtypes = argtypes
        f.errcheck = _do_check
        return f

    def function(self, fname, restype, argtypes, check=True):
        return self._prototype(getattr(self, fname), restype, argtypes, check)


# Prevent accidental loading of the proton python module inside dispatch.
# The proton-C library is linked with the dispatch C library, loading the proton
# python module loads a second copy of the library and mayhem ensues.
#
# Note the FORBIDDEN list is over-written to disable this tests in mock python
# testing code.
FORBIDDEN = ["proton"]


def check_forbidden():
    bad = set(FORBIDDEN) & set(sys.modules)
    if bad:
        raise ImportError("Forbidden modules loaded: '%s'." % "', '".join(bad))


def import_check(name, *args, **kw):
    if name in FORBIDDEN:
        raise ImportError("Python code running inside a dispatch router cannot import '%s', use the 'dispatch' module for internal messaging" % name)
    return builtin_import(name, *args, **kw)


check_forbidden()

builtin_import = builtins.__import__
builtins.__import__ = import_check
