
from pybindgen.typehandlers.base import Parameter, ReturnValue, \
    join_ctype_and_name, CodeGenerationError, \
    param_type_matcher, return_type_matcher, CodegenErrorBase, \
    DeclarationsScope, CodeBlock, NotSupportedError, ForwardWrapperBase, ReverseWrapperBase, \
    TypeConfigurationError

from pybindgen.cppclass import ReferenceCountingMethodsPolicy, CppClass, CppClassParameterBase, CppClassReturnValueBase, common_shared_object_return

class Ns3PtrMemoryPolicy(ReferenceCountingMethodsPolicy):
    def __init__(self, class_name):
        """
        Create a memory policy for using ns3::Ptr<> to manage instances of this object.

        :param class_name: the full name of the class, e.g. foo::Bar
        """
        super(Ns3PtrMemoryPolicy, self).__init__('Ref', 'Unref', 'GetReferenceCount')

        self.class_name = class_name
        self.pointer_template = 'ns3::Ptr< %s >'

    def get_pointer_name(self, class_name):
        return self.pointer_template % (class_name,)

    def get_delete_code(self, cpp_class):
        return "self->obj.~Ptr< %s >();" % (cpp_class.full_name,)

    def get_pointer_type(self, class_full_name):
        return self.get_pointer_name(class_full_name) + ' '

    def get_pointer_to_void_name(self, object_name):
        return "::ns3::PeekPointer(%s)" % object_name

    def get_instance_creation_function(self):
        return ns3_ptr_instance_creation_function

    def get_pystruct_init_code(self, cpp_class, obj):
        return "new(&%s->obj) %s;" % (obj, self.get_pointer_name(cpp_class.full_name),)

    def register_ptr_parameter_and_return(self, cls, name):
        class ThisClassNs3PtrParameter(CppClassNs3PtrParameter):
            """Register this C++ class as pass-by-pointer parameter"""
            CTYPES = []
            cpp_class = cls
        cls.ThisClassNs3PtrParameter = ThisClassNs3PtrParameter
        try:
            param_type_matcher.register(self.get_pointer_name(cls.full_name), cls.ThisClassNs3PtrParameter)
        except ValueError:
            pass

        class ThisClassNs3PtrReturn(CppClassNs3PtrReturnValue):
            """Register this C++ class as pointer return"""
            CTYPES = []
            cpp_class = cls
        cls.ThisClassNs3PtrReturn = ThisClassNs3PtrReturn
        try:
            return_type_matcher.register(self.get_pointer_name(cls.full_name), cls.ThisClassNs3PtrReturn)
        except ValueError:
            pass

    def register_ptr_alias_parameter_and_return(self, cls, alias):
        alias_ptr = '::ns3::Ptr< %s >' % alias
        cls.ThisClassNs3PtrParameter.CTYPES.append(alias_ptr)
        try:
            param_type_matcher.register(alias_ptr, cls.ThisClassNs3PtrParameter)
        except ValueError: pass

        cls.ThisClassNs3PtrReturn.CTYPES.append(alias_ptr)
        try:
            return_type_matcher.register(alias_ptr, cls.ThisClassNs3PtrReturn)
        except ValueError: pass

def ns3_ptr_instance_creation_function(cpp_class, code_block, lvalue,
                                       parameters, construct_type_name):
    """
    ns3::Ptr "instance creation function"; it is called whenever a new
    C++ class instance needs to be created

    :param cpp_class: the CppClass object whose instance is to be created
    :param code_block: CodeBlock object on which the instance creation code should be generated
    :param lvalue: lvalue expression that should hold the result in the end
    :param parameters: stringified list of parameters
    :param construct_type_name: actual name of type to be constructed (it is
                          not always the class name, sometimes it's
                          the python helper class)
    """
    assert lvalue
    assert not lvalue.startswith('None')
    if cpp_class.incomplete_type:
        raise CodeGenerationError("%s cannot be constructed (incomplete type)"
                                  % cpp_class.full_name)
    code_block.write_code(
        "%s = ::ns3::Create<%s>(%s);" % (lvalue, construct_type_name, parameters))

class CppClassNs3PtrParameter(CppClassParameterBase):
    "Class* handlers"
    CTYPES = []
    cpp_class = None #cppclass.CppClass('dummy') # CppClass instance
    DIRECTIONS = [Parameter.DIRECTION_IN,
                  Parameter.DIRECTION_OUT,
                  Parameter.DIRECTION_INOUT]
    SUPPORTS_TRANSFORMATIONS = False

    def __init__(self, ctype, name, direction=Parameter.DIRECTION_IN, is_const=False,
                 null_ok=False, default_value=None):
        super(CppClassNs3PtrParameter, self).__init__(
            ctype, name, direction, is_const, default_value)
        self.null_ok = null_ok


    def convert_python_to_c(self, wrapper):
        "parses python args to get C++ value"
        assert isinstance(wrapper, ForwardWrapperBase)
        assert isinstance(self.cpp_class, CppClass)

        self.py_name = wrapper.declarations.declare_variable(
            self.cpp_class.pystruct+'*', self.name,
            initializer=(self.default_value and 'NULL' or None))

        value_ptr = wrapper.declarations.declare_variable(
            self.cpp_class.memory_policy.get_pointer_name(self.cpp_class.full_name), "%s_ptr" % self.name)

        if self.null_ok:
            num = wrapper.parse_params.add_parameter('O', ['&'+self.py_name], self.name, optional=bool(self.default_value))

            wrapper.before_call.write_error_check(

                "%s && ((PyObject *) %s != Py_None) && !PyObject_IsInstance((PyObject *) %s, (PyObject *) &%s)"
                % (self.py_name, self.py_name, self.py_name, self.cpp_class.pytypestruct),

                'PyErr_SetString(PyExc_TypeError, "Parameter %i must be of type %s");' % (num, self.cpp_class.name))

            wrapper.before_call.write_code("if (%(PYNAME)s) {\n"
                                           "    if ((PyObject *) %(PYNAME)s == Py_None)\n"
                                           "        %(VALUE)s = NULL;\n"
                                           "    else\n"
                                           "        %(VALUE)s = %(PYNAME)s->obj;\n"
                                           "} else {\n"
                                           "    %(VALUE)s = NULL;\n"
                                           "}" % dict(PYNAME=self.py_name, VALUE=value_ptr))

        else:

            wrapper.parse_params.add_parameter(
                'O!', ['&'+self.cpp_class.pytypestruct, '&'+self.py_name], self.name, optional=bool(self.default_value))
            wrapper.before_call.write_code("if (%s) { %s = %s->obj; }" % (self.py_name, value_ptr, self.py_name))

        wrapper.call_params.append(value_ptr)



    def convert_c_to_python(self, wrapper):
        """foo"""

        ## Value transformations
        value = self.transformation.untransform(
            self, wrapper.declarations, wrapper.after_call, self.value)

        ## declare wrapper variable
        py_name = wrapper.declarations.declare_variable(
            self.cpp_class.pystruct+'*', 'py_'+self.cpp_class.name)
        self.py_name = py_name

        def write_create_new_wrapper():
            """Code path that creates a new wrapper for the parameter"""

            ## Find out what Python wrapper to use, in case
            ## automatic_type_narrowing is active and we are not forced to
            ## make a copy of the object
            if self.cpp_class.automatic_type_narrowing:

                typeid_map_name = self.cpp_class.get_type_narrowing_root().typeid_map_name
                wrapper_type = wrapper.declarations.declare_variable(
                    'PyTypeObject*', 'wrapper_type', '0')
                wrapper.before_call.write_code(
                    '%s = %s.lookup_wrapper(typeid(*%s), &%s);'
                    % (wrapper_type, typeid_map_name, value, self.cpp_class.memory_policy.get_pointer_to_void_name(self.cpp_class.pytypestruct)))
            else:
                wrapper_type = '&'+self.cpp_class.pytypestruct

            ## Create the Python wrapper object
            self.cpp_class.write_allocate_pystruct(wrapper.before_call, py_name, wrapper_type)
            self.py_name = py_name

            wrapper.before_call.write_code("%s->flags = PYBINDGEN_WRAPPER_FLAG_NONE;" % py_name)

            ## Assign the C++ value to the Python wrapper
            wrapper.before_call.write_code("%s->obj = %s;" % (py_name, value))

        if self.cpp_class.helper_class is None:
            try:
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
                    wrapper.before_call, self.cpp_class.pystruct, py_name, value)
            except NotSupportedError:
                write_create_new_wrapper()
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
                                                                           "%s->obj" % py_name)
            else:
                wrapper.before_call.write_code("if (%s == NULL)\n{" % py_name)
                wrapper.before_call.indent()
                write_create_new_wrapper()
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
                                                                           "%s->obj" % py_name)
                wrapper.before_call.unindent()
                wrapper.before_call.write_code('}')
            wrapper.build_params.add_parameter("N", [py_name])
        else:
            wrapper.before_call.write_code("if (typeid(*(%s)).name() == typeid(%s).name())\n{"
                                          % (value, self.cpp_class.helper_class.name))
            wrapper.before_call.indent()

            if self.type_traits.target_is_const:
                wrapper.before_call.write_code(
                    "%s = (%s*) (((%s*) ((%s*) %s))->m_pyself);"
                    % (py_name, self.cpp_class.pystruct,
                       self.cpp_class.helper_class.name, self.cpp_class.full_name, value))
                wrapper.before_call.write_code("%s->obj =  (%s*) (%s);" %
                                               (py_name, self.cpp_class.full_name, value))
            else:
                wrapper.before_call.write_code(
                    "%s = (%s*) (((%s*) %s)->m_pyself);"
                    % (py_name, self.cpp_class.pystruct,
                       self.cpp_class.helper_class.name, value))
                wrapper.before_call.write_code("%s->obj = %s;" % (py_name, value))
            wrapper.before_call.write_code("Py_INCREF(%s);" % py_name)
            wrapper.before_call.unindent()
            wrapper.before_call.write_code("} else {")
            wrapper.before_call.indent()

            try:
                self.cpp_class.wrapper_registry.write_lookup_wrapper(
                    wrapper.before_call, self.cpp_class.pystruct, py_name, value)
            except NotSupportedError:
                write_create_new_wrapper()
                self.cpp_class.wrapper_registry.write_register_new_wrapper(
                    wrapper.before_call, py_name, "%s->obj" % py_name)
            else:
                wrapper.before_call.write_code("if (%s == NULL)\n{" % py_name)
                wrapper.before_call.indent()
                write_create_new_wrapper()
                self.cpp_class.wrapper_registry.write_register_new_wrapper(wrapper.before_call, py_name,
                                                                           "%s->obj" % py_name)
                wrapper.before_call.unindent()
                wrapper.before_call.write_code('}') # closes if (%s == NULL)

            wrapper.before_call.unindent()
            wrapper.before_call.write_code("}") # closes if (typeid(*(%s)) == typeid(%s))\n{
            wrapper.build_params.add_parameter("N", [py_name])




class CppClassNs3PtrReturnValue(CppClassReturnValueBase):
    "Class* return handler"
    CTYPES = []
    SUPPORTS_TRANSFORMATIONS = True
    cpp_class = None #cppclass.CppClass('dummy') # CppClass instance

    def __init__(self, ctype, is_const=False):
        super(CppClassNs3PtrReturnValue, self).__init__(ctype, is_const=is_const)

    def get_c_error_return(self): # only used in reverse wrappers
        """See ReturnValue.get_c_error_return"""
        return "return NULL;"

    def convert_c_to_python(self, wrapper):
        """See ReturnValue.convert_c_to_python"""

        ## Value transformations
        value = self.transformation.untransform(
            self, wrapper.declarations, wrapper.after_call, self.value)

        # if value is NULL, return None
        wrapper.after_call.write_code("if (!(%s)) {\n"
                                      "    Py_INCREF(Py_None);\n"
                                      "    return Py_None;\n"
                                      "}" % value)

        ## declare wrapper variable
        py_name = wrapper.declarations.declare_variable(
            self.cpp_class.pystruct+'*', 'py_'+self.cpp_class.name)
        self.py_name = py_name

        common_shared_object_return(value, py_name, self.cpp_class, wrapper.after_call,
                                    self.type_traits, caller_owns_return=True,
                                    reference_existing_object=False,
                                    type_is_pointer=True)

        # return the value
        wrapper.build_params.add_parameter("N", [py_name], prepend=True)


    def convert_python_to_c(self, wrapper):
        """See ReturnValue.convert_python_to_c"""
        name = wrapper.declarations.declare_variable(
            self.cpp_class.pystruct+'*', "tmp_%s" % self.cpp_class.name)
        wrapper.parse_params.add_parameter(
            'O!', ['&'+self.cpp_class.pytypestruct, '&'+name])

        value = self.transformation.transform(
            self, wrapper.declarations, wrapper.after_call, "%s->obj" % name)

        # caller gets a shared pointer
        wrapper.after_call.write_code("%s = %s;" % (self.value, value))
