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

from __future__ import absolute_import

from cproton import pn_incref, pn_decref, \
    pn_py2void, pn_void2py, \
    pn_record_get, pn_record_def, pn_record_set, \
    PN_PYREF

from ._exceptions import ProtonException


class EmptyAttrs:

    def __contains__(self, name):
        return False

    def __getitem__(self, name):
        raise KeyError(name)

    def __setitem__(self, name, value):
        raise TypeError("does not support item assignment")


EMPTY_ATTRS = EmptyAttrs()


class Wrapper(object):
    """ Wrapper for python objects that need to be stored in event contexts and be retrived again from them
        Quick note on how this works:
        The actual *python* object has only 3 attributes which redirect into the wrapped C objects:
        _impl   The wrapped C object itself
        _attrs  This is a special pn_record_t holding a PYCTX which is a python dict
                every attribute in the python object is actually looked up here
        _record This is the C record itself (so actually identical to _attrs really but
                a different python type

        Because the objects actual attributes are stored away they must be initialised *after* the wrapping
        is set up. This is the purpose of the _init method in the wrapped  object. Wrapper.__init__ will call
        eht subclass _init to initialise attributes. So they *must not* be initialised in the subclass __init__
        before calling the superclass (Wrapper) __init__ or they will not be accessible from the wrapper at all.

    """

    def __init__(self, impl_or_constructor, get_context=None):
        init = False
        if callable(impl_or_constructor):
            # we are constructing a new object
            impl = impl_or_constructor()
            if impl is None:
                self.__dict__["_impl"] = impl
                self.__dict__["_attrs"] = EMPTY_ATTRS
                self.__dict__["_record"] = None
                raise ProtonException(
                    "Wrapper failed to create wrapped object. Check for file descriptor or memory exhaustion.")
            init = True
        else:
            # we are wrapping an existing object
            impl = impl_or_constructor
            pn_incref(impl)

        if get_context:
            record = get_context(impl)
            attrs = pn_void2py(pn_record_get(record, PYCTX))
            if attrs is None:
                attrs = {}
                pn_record_def(record, PYCTX, PN_PYREF)
                pn_record_set(record, PYCTX, pn_py2void(attrs))
                init = True
        else:
            attrs = EMPTY_ATTRS
            init = False
            record = None
        self.__dict__["_impl"] = impl
        self.__dict__["_attrs"] = attrs
        self.__dict__["_record"] = record
        if init:
            self._init()

    def __getattr__(self, name):
        attrs = self.__dict__["_attrs"]
        if name in attrs:
            return attrs[name]
        else:
            raise AttributeError(name + " not in _attrs")

    def __setattr__(self, name, value):
        if hasattr(self.__class__, name):
            object.__setattr__(self, name, value)
        else:
            attrs = self.__dict__["_attrs"]
            attrs[name] = value

    def __delattr__(self, name):
        attrs = self.__dict__["_attrs"]
        if attrs:
            del attrs[name]

    def __hash__(self):
        return hash(addressof(self._impl))

    def __eq__(self, other):
        if isinstance(other, Wrapper):
            return addressof(self._impl) == addressof(other._impl)
        return False

    def __ne__(self, other):
        if isinstance(other, Wrapper):
            return addressof(self._impl) != addressof(other._impl)
        return True

    def __del__(self):
        pn_decref(self._impl)

    def __repr__(self):
        return '<%s.%s 0x%x ~ 0x%x>' % (self.__class__.__module__,
                                        self.__class__.__name__,
                                        id(self), addressof(self._impl))


PYCTX = int(pn_py2void(Wrapper))
addressof = int
