from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers

def register_types(module):
    root_module = module.get_root()
    
    module.add_class('AbstractBaseClass', allow_subclassing=True)
    module.add_class('AbstractBaseClass2', allow_subclassing=True)
    module.add_class('AbstractBaseClassImpl', parent=root_module['AbstractBaseClass'])
    module.add_class('AbstractXpto', allow_subclassing=True)
    module.add_class('AbstractXptoImpl', parent=root_module['AbstractXpto'])
    module.add_class('Box')
    module.add_class('CannotBeConstructed')
    module.add_class('ClassThatTakesFoo')
    module.add_class('ClassThatThrows', allow_subclassing=True)
    module.add_exception('Error')
    module.add_class('Foo', automatic_type_narrowing=True)
    module.add_class('Foobar', allow_subclassing=True)
    module.add_class('InterfaceId')
    module.add_class('Bar', parent=root_module['Foo'])
    module.add_exception('DomainError', parent=root_module['Error'])
    module.add_container('std::vector< std::string >', 'std::string', container_type='vector')
    typehandlers.add_type_alias('void ( * ) (  ) *', 'Callback')
    typehandlers.add_type_alias('void ( * ) (  ) **', 'Callback*')
    typehandlers.add_type_alias('void ( * ) (  ) *&', 'Callback&')
    
    ## Register a nested module for the namespace TopNs
    
    nested_module = module.add_cpp_namespace('TopNs')
    register_types_TopNs(nested_module)
    
    
    ## Register a nested module for the namespace std
    
    nested_module = module.add_cpp_namespace('std')
    register_types_std(nested_module)
    
    
    ## Register a nested module for the namespace xpto
    
    nested_module = module.add_cpp_namespace('xpto')
    register_types_xpto(nested_module)
    

def register_types_TopNs(module):
    root_module = module.get_root()
    
    
    ## Register a nested module for the namespace PrefixBottomNs
    
    nested_module = module.add_cpp_namespace('PrefixBottomNs')
    register_types_TopNs_PrefixBottomNs(nested_module)
    

def register_types_TopNs_PrefixBottomNs(module):
    root_module = module.get_root()
    

def register_types_std(module):
    root_module = module.get_root()
    

def register_types_xpto(module):
    root_module = module.get_root()
    
    module.add_enum('FooType', ['FOO_TYPE_AAA', 'FOO_TYPE_BBB', 'FOO_TYPE_CCC'])
    typehandlers.add_type_alias('Foo', 'xpto::FooXpto')
    typehandlers.add_type_alias('Foo*', 'xpto::FooXpto*')
    typehandlers.add_type_alias('Foo&', 'xpto::FooXpto&')
    module.add_typedef(root_module['Foo'], 'FooXpto')
    typehandlers.add_type_alias('uint32_t', 'xpto::FlowId')
    typehandlers.add_type_alias('uint32_t*', 'xpto::FlowId*')
    typehandlers.add_type_alias('uint32_t&', 'xpto::FlowId&')

def register_methods(root_module):
    register_AbstractBaseClass_methods(root_module, root_module['AbstractBaseClass'])
    register_AbstractBaseClass2_methods(root_module, root_module['AbstractBaseClass2'])
    register_AbstractBaseClassImpl_methods(root_module, root_module['AbstractBaseClassImpl'])
    register_AbstractXpto_methods(root_module, root_module['AbstractXpto'])
    register_AbstractXptoImpl_methods(root_module, root_module['AbstractXptoImpl'])
    register_Box_methods(root_module, root_module['Box'])
    register_CannotBeConstructed_methods(root_module, root_module['CannotBeConstructed'])
    register_ClassThatTakesFoo_methods(root_module, root_module['ClassThatTakesFoo'])
    register_ClassThatThrows_methods(root_module, root_module['ClassThatThrows'])
    register_Foo_methods(root_module, root_module['Foo'])
    register_Foobar_methods(root_module, root_module['Foobar'])
    register_InterfaceId_methods(root_module, root_module['InterfaceId'])
    register_Bar_methods(root_module, root_module['Bar'])
    return

def register_AbstractBaseClass_methods(root_module, cls):
    cls.add_constructor([param('AbstractBaseClass const &', 'arg0')])
    cls.add_constructor([], 
                        visibility='protected')
    cls.add_method('do_something', 
                   'void', 
                   [param('char * * * *', 'arg0')], 
                   is_pure_virtual=True, visibility='protected', is_virtual=True)
    return

def register_AbstractBaseClass2_methods(root_module, cls):
    cls.add_method('invoke_private_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_const=True)
    cls.add_method('invoke_protected_pure_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_const=True)
    cls.add_method('invoke_protected_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_const=True)
    cls.add_constructor([], 
                        visibility='protected')
    cls.add_method('protected_pure_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_pure_virtual=True, is_const=True, visibility='protected', is_virtual=True)
    cls.add_method('protected_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_const=True, visibility='protected', is_virtual=True)
    cls.add_method('private_virtual', 
                   'int', 
                   [param('int', 'x')], 
                   is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
    return

def register_AbstractBaseClassImpl_methods(root_module, cls):
    cls.add_constructor([param('AbstractBaseClassImpl const &', 'arg0')])
    cls.add_method('get_abstract_base_class_ptr1', 
                   retval('AbstractBaseClass *', caller_owns_return=True), 
                   [], 
                   is_static=True)
    cls.add_method('get_abstract_base_class_ptr2', 
                   retval('AbstractBaseClass *', caller_owns_return=False), 
                   [], 
                   is_static=True)
    cls.add_constructor([], 
                        visibility='protected')
    cls.add_method('do_something', 
                   'void', 
                   [param('char * * * *', 'arg0')], 
                   visibility='protected', is_virtual=True)
    return

def register_AbstractXpto_methods(root_module, cls):
    cls.add_constructor([param('AbstractXpto const &', 'arg0')])
    cls.add_constructor([])
    cls.add_method('something', 
                   'void', 
                   [param('int', 'x')], 
                   is_pure_virtual=True, is_const=True, is_virtual=True)
    return

def register_AbstractXptoImpl_methods(root_module, cls):
    cls.add_constructor([param('AbstractXptoImpl const &', 'arg0')])
    cls.add_constructor([])
    cls.add_method('something', 
                   'void', 
                   [param('int', 'x')], 
                   is_const=True, is_virtual=True)
    return

def register_Box_methods(root_module, cls):
    cls.add_static_attribute('instance_count', 'int', is_const=False)
    cls.add_instance_attribute('m_internalFoobar', retval('Foobar *', return_internal_reference=True), is_const=False)
    cls.add_constructor([])
    cls.add_method('getFoobarInternalPtr', 
                   retval('Foobar *', reference_existing_object=True), 
                   [])
    cls.add_method('getFoobarInternalRef', 
                   retval('Foobar &', reference_existing_object=True), 
                   [])
    cls.add_method('getFoobarInternalPtr2', 
                   retval('Foobar *', return_internal_reference=True), 
                   [])
    cls.add_method('getFoobarInternalRef2', 
                   retval('Foobar &', return_internal_reference=True), 
                   [])
    return

def register_CannotBeConstructed_methods(root_module, cls):
    cls.add_constructor([param('CannotBeConstructed const &', 'arg0')])
    cls.add_method('get_ptr', 
                   retval('CannotBeConstructed *', caller_owns_return=True), 
                   [], 
                   is_static=True)
    cls.add_method('get_value', 
                   'CannotBeConstructed', 
                   [], 
                   is_static=True)
    return

def register_ClassThatTakesFoo_methods(root_module, cls):
    cls.add_constructor([param('ClassThatTakesFoo const &', 'arg0')])
    cls.add_constructor([param('Foo', 'foo')])
    cls.add_method('get_foo', 
                   'Foo', 
                   [], 
                   is_const=True)
    return

def register_ClassThatThrows_methods(root_module, cls):
    cls.add_constructor([param('ClassThatThrows const &', 'arg0')])
    cls.add_constructor([param('double', 'x')], 
                        throw=[root_module['DomainError']])
    cls.add_method('my_inverse_method', 
                   'double', 
                   [param('double', 'x')], 
                   throw=[root_module['DomainError']])
    cls.add_method('my_inverse_method2', 
                   'double', 
                   [param('double', 'x')], 
                   throw=[root_module['std::exception']])
    cls.add_method('throw_error', 
                   'int', 
                   [], 
                   is_const=True, throw=[root_module['std::exception']], is_virtual=True)
    return

def register_Foo_methods(root_module, cls):
    cls.add_output_stream_operator()
    cls.add_constructor([])
    cls.add_constructor([param('int', 'xpto')])
    cls.add_constructor([param('std::string const &', 'datum')])
    cls.add_constructor([param('Foo const &', 'other')])
    cls.add_method('add_sub', 
                   'int', 
                   [param('int', 'a'), param('int', 'b', default_value='3'), param('bool', 'subtract', default_value='false')], 
                   is_static=True)
    cls.add_method('get_datum', 
                   'std::string const', 
                   [], 
                   is_const=True)
    cls.add_method('get_datum_deprecated', 
                   'std::string', 
                   [], 
                   is_const=True)
    cls.add_method('initialize', 
                   'void', 
                   [])
    cls.add_method('is_initialized', 
                   'bool', 
                   [], 
                   is_const=True)
    cls.add_static_attribute('instance_count', 'int', is_const=False)
    return

def register_Foobar_methods(root_module, cls):
    cls.add_static_attribute('instance_count', 'int', is_const=False)
    cls.add_constructor([])
    return

def register_InterfaceId_methods(root_module, cls):
    cls.add_constructor([param('InterfaceId const &', 'arg0')])
    return

def register_Bar_methods(root_module, cls):
    cls.add_constructor([])
    cls.add_constructor([param('Bar const &', 'arg0')])
    cls.add_method('Hooray', 
                   'std::string', 
                   [], 
                   is_static=True)
    return

def register_functions(root_module):
    module = root_module
    module.add_function('create_new_foobar', 
                        retval('Foobar *', caller_owns_return=True), 
                        [])
    module.add_function('delete_some_object', 
                        'void', 
                        [])
    module.add_function('delete_stored_zbr', 
                        'void', 
                        [])
    module.add_function('function_that_returns_foo', 
                        'Foo', 
                        [])
    module.add_function('function_that_takes_callback', 
                        'void', 
                        [param('Callback', 'cb')])
    module.add_function('function_that_takes_foo', 
                        'void', 
                        [param('Foo', 'foo')])
    module.add_function('get_abstract_base_class_ptr1', 
                        retval('AbstractBaseClass *', caller_owns_return=True), 
                        [])
    module.add_function('get_abstract_base_class_ptr2', 
                        retval('AbstractBaseClass *', caller_owns_return=False), 
                        [])
    module.add_function('get_cannot_be_constructed_ptr', 
                        retval('CannotBeConstructed *', caller_owns_return=True), 
                        [])
    module.add_function('get_cannot_be_constructed_value', 
                        'CannotBeConstructed', 
                        [])
    module.add_function('get_foobar_with_other_as_custodian', 
                        retval('Foobar *', custodian=1, reference_existing_object=True), 
                        [param('SomeObject *', 'other', transfer_ownership=False)])
    module.add_function('get_hidden_subclass_pointer', 
                        retval('Foo *', caller_owns_return=True), 
                        [])
    module.add_function('get_int_from_float', 
                        'int', 
                        [param('double', 'from_float'), param('int', 'multiplier', default_value='1')], 
                        custom_name='get_int')
    module.add_function('get_int_from_string', 
                        'int', 
                        [param('char const *', 'from_string'), param('int', 'multiplier', default_value='1')], 
                        custom_name='get_int')
    module.add_function('get_map', 
                        'std::map< std::string, int >', 
                        [])
    module.add_function('get_set', 
                        'std::set< unsigned int >', 
                        [])
    module.add_function('get_simple_list', 
                        'SimpleStructList', 
                        [])
    module.add_function('invoke_some_object_get_prefix', 
                        'std::string', 
                        [])
    module.add_function('invoke_zbr', 
                        'int', 
                        [param('int', 'x')])
    register_functions_TopNs(module.get_submodule('TopNs'), root_module)
    register_functions_std(module.get_submodule('std'), root_module)
    register_functions_xpto(module.get_submodule('xpto'), root_module)
    return

def register_functions_TopNs(module, root_module):
    register_functions_TopNs_PrefixBottomNs(module.get_submodule('PrefixBottomNs'), root_module)
    return

def register_functions_TopNs_PrefixBottomNs(module, root_module):
    return

def register_functions_std(module, root_module):
    return

def register_functions_xpto(module, root_module):
    module.add_function('get_flow_id', 
                        'xpto::FlowId', 
                        [param('xpto::FlowId', 'flowId')])
    module.add_function('get_foo_datum', 
                        'std::string', 
                        [param('xpto::FooXpto const &', 'foo')])
    module.add_function('get_foo_type', 
                        'xpto::FooType', 
                        [])
    return

