import os, sys

try:
    import ctypeslib.h2xml as h2xml
    import ctypeslib.xml2py as xml2py
    import ctypeslib.codegen as codegen
except:
    print ('Error: required Python ctypeslib module not installed!')
    sys.exit(-1)

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup
    from distutils.core import Command

src_path = os.path.dirname(os.path.realpath(__file__)) + '/'
try:
    obj_path = sys.argv[sys.argv.index('--build-base') + 1] + '/'
except:
    obj_path = src_path

c_h_file   = src_path + '../mark5access/mark5_stream.h'
c_lib_file = obj_path + '../mark5access/.libs/libmark5access.so'
c_lib_obj  = 'libmark5access.so'
ctypes_xml_file = 'mark5access_api.xml'
ctypes_api_file = 'mark5access/mark5access.py'
check_for_func  = 'new_mark5_format'

# Ctypeslib generator invocations based on "reference" examples at
# https://github.com/piranna/cusepy/blob/master/setup.py
# http://s3ql.googlecode.com/hg-history/release-0.20/setup.py
def build_ctypes():

    # Step 1: Remove old files
    try:
        os.remove(ctypes_xml_file)
    except:
        pass
    try:
        os.remove(ctypes_api_file)
    except:
        pass

    # Configure ctypeslib
    codegen.ASSUME_STRINGS = False
    codegen.CDLL_SET_ERRNO = False
    codegen.PREFIX = ('# Code autogenerated by ctypeslib. Any changes will be lost!\n\n'
        '#pylint: disable-all\n'
        '#@PydevCodeAnalysisIgnore\n\n')

    # Modify a copy of mark5access headers
    # By design h2xml is using C++ to convert headers.
    # There are issues with C++ <complex> and the Python conversion.
    # We create a copy of 'mark5_stream.h' to force C-only headers
    # and the C <complex.h> definition of complex numbers
    c_h_file_tmp = 'mark5_stream_tmp.h'
    with open(c_h_file_tmp, 'w') as fout:
        with open(c_h_file, 'r') as fin:
            fout.write('#undef __cplusplus\n')
            for line in fin:
                if not('complex' in line):
                    fout.write(line)

    # Generate XML file from C/C++ header file
    h2xml_args = ['h2xml.py', c_h_file_tmp, '-o',ctypes_xml_file, '-I',src_path]
    h2xml.main(h2xml_args)
    os.remove(c_h_file_tmp)

    # Generate Python bindings from XML file
    # Note 1: to get -r <regex> to work correctly in xml2py.py v0.5.6 a patch is necessary (see README)
    # Note 2: uses libvdifio.so from the C/C++ build tree because 'make install' may not have been done yet
    print ('creating bindings %s ...' % (ctypes_api_file))
    xml2py_flags = ['-o',ctypes_api_file+'.tmp']
    xml2py_flags.extend(['-k','esf'])                   # standard flags
    xml2py_flags.extend(['-s','Mark5Format'])           # the enums to include in wrapper
    xml2py_flags.extend(['-s','Mark5Blanker'])
    xml2py_flags.extend(['-s','mark5_stream'])          # structs to include in wrapper
    xml2py_flags.extend(['-s','mark5_stream_generic', '-s','mark5_format_generic', '-s','mark5_format'])
    xml2py_flags.extend(['-r','mark5'])                 # functions to include in wrapper
    xml2py_flags.extend(['-l',c_lib_file])
    xml2py_args = ['xml2py.py', ctypes_xml_file]
    xml2py_args.extend(xml2py_flags)
    xml2py.main(xml2py_args)

    # Rename
    try:
        with open(ctypes_api_file, 'w') as fout:
            with open(ctypes_api_file+'.tmp', 'r') as fin:
                for line in fin:
                    fout.write(line.replace(c_lib_file, c_lib_obj))
        os.remove(ctypes_api_file+'.tmp')
    except:
        pass

    # Make sure the generated .py seems okay -- regexp to select mark5* functions was ok?
    func_found = False
    with open(ctypes_api_file, 'r') as fin:
        for line in fin:
            if check_for_func in line:
                func_found = True
    if not func_found:
        print ('Error: ctypeslib did not extract function names. For old ctypeslib might need a patch.')
        sys.exit(-1)

if 'build' in sys.argv:
    build_ctypes()

setup(
    name = 'mark5access',
    packages=['mark5access'],
    version = '1.5.3',
    description = ('A ctypes-based Python wrapper to the mark5access C/C++ library'),
    long_description=open('README').read(),
    license = 'LICENSE',
    # install_requires = 'ctypes>=1.1.0',
    requires = 'ctypes',
    # cmdclass={'build_ctypes': build_ctypes},
)
