#

"""
setup.py: Used for building python wrappers for Simbios' OpenMM library.
"""
__author__ = "Randall J. Radmer"
__version__ = "1.0"


import os, sys, platform, glob, shutil
import struct

from distutils.core import setup

MAJOR_VERSION_NUM='1'
MINOR_VERSION_NUM='1'
BUILD_INFO='1'

def uninstall():
    save_path=sys.path[:]
    sys.path=['scripts']
    for item in save_path:
        if item!='.' and item!=os.getcwd():
            sys.path.append(item)
    import uninstallSimtkPackage as uninstall
    uninstall.main(verbose=True)
    sys.path=save_path

def fail_mac64():
    s="""
Error: You are using a 64 bit version of Python, which is not
currently supported by the NVIDIA drivers.  If you are using
Snow Leopard (where the default is 64 bit Python 2.6) you might
try building a local, 32 bit version of Python 2.6, or telling
the OS to use a 32 bit version of Python2.6 or you could use
the existing 2.5 version of Python (python2.5, which is 32 bit). 
The folder containing this script also contains a file called
README_MAC_64bit.txt with additional details
"""
    sys.stdout.write("%s\n" % s)
    sys.exit(1)


def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
                           minor_version_num=MINOR_VERSION_NUM,
                           build_info=BUILD_INFO):
    from distutils.core import Extension
    setupKeywords = {}
    setupKeywords["name"]              = "PyOpenMM"
    setupKeywords["version"]           = "%s.%s.%s" % (major_version_num,
                                                       minor_version_num,
                                                       build_info)
    setupKeywords["author"]            = "Randall J. Radmer"
    setupKeywords["author_email"]      = "radmer@stanford.edu"
    setupKeywords["license"]           = \
    "Python Software Foundation License (BSD-like)"
    setupKeywords["url"]               = "https://simtk.org/home/pyopenmm"
    setupKeywords["download_url"]      = "https://simtk.org/home/pyopenmm"
    setupKeywords["packages"]          = ["simtk",
                                          "simtk.unit",
                                          "simtk.cuda",
                                          "simtk.chem",
                                          "simtk.chem.openmm",
                                          "simtk.chem.openmm.amber",
                                          "simtk.chem.openmm.extras"]
    setupKeywords["data_files"]        = []
    setupKeywords["package_data"]      = {"simtk" : [],
                                          "simtk.unit" : [],
                                          "simtk.cuda" : [],
                                          "simtk.chem" : [],
                                          "simtk.chem.openmm" : [],
                                          "simtk.chem.openmm.amber" : [],
                                          "simtk.chem.openmm.extras" : []}
    setupKeywords["platforms"]         = ["Linux", "Mac OS X", "Windows"]
    setupKeywords["description"]       = \
    "Python wrapper for OpenMM (a C++ MD package)"
    setupKeywords["long_description"]  = \
    """OpenMM is a library which provides tools for modern molecular
    modeling simulation. As a library it can be hooked into any code,
    allowing that code to do molecular modeling with minimal extra
    coding (https://simtk.org/home/openmm).  This Python package
    gives access to the OpenMM API.
    """

    define_macros = [('MAJOR_VERSION', major_version_num),
                     ('MINOR_VERSION', minor_version_num)]

    libraries=['OpenMM', 'OpenMMFreeEnergy']
    if 'OPENMM_USE_DEBUG_LIBS' in os.environ:
        if platform.system() == "Windows":
            raise Exception("use of OpenMM debug libs not supported on Win OS")
        else:
            sys.stdout.write("WARNING: using debug libs:\n")
            for ii in range(len(libraries)):
                libraries[ii]="%s_d" % libraries[ii]
                sys.stdout.write("%s\n" % libraries[ii])
            
    openmm_include_path = os.getenv('OPENMM_INCLUDE_PATH')
    if not openmm_include_path:
        openmm_include_path = os.path.join("OpenMM", 'include')
    openmm_lib_path = os.getenv('OPENMM_LIB_PATH')
    if openmm_lib_path:
        check_for_existing_swig_lib=False
    else:
        check_for_existing_swig_lib=True

    runtime_library_dirs=[]
    extra_compile_args=[]
    extra_link_args=[]
    must_fix_mac_install_names = False
    if platform.system() == "Windows":
        libPrefix = ""
        libExtList = ["dll", "lib"]
        libExtPython = "pyd"
        if not openmm_lib_path:
            openmm_lib_path=os.path.join("OpenMM", 'win', 'OpenMM')
        define_macros.append( ('WIN32', None) )
        define_macros.append( ('_WINDOWS', None) )
        define_macros.append( (' _MSC_VER', None) )
    else:
        if platform.system() == 'Darwin':
            if struct.calcsize("P")==8:
                fail_mac64()
            macVersion = [int(x) for x in platform.mac_ver()[0].split('.')]
            if tuple(macVersion) < (10, 6):
                os.environ['MACOSX_DEPLOYMENT_TARGET']='10.5'
            extra_compile_args.append("-m32")
            extra_link_args.append('-Wl,-rpath,@loader_path/OpenMM')
            libPrefix = "lib"
            libExtList = ["dylib"]
            libExtPython = "so"
            if openmm_lib_path:
                must_fix_mac_install_names = True
            else:
                openmm_lib_path=os.path.join("OpenMM", 'leopard', 'OpenMM')
        else:
            runtime_library_dirs.append('$ORIGIN/OpenMM')
            libPrefix = "lib"
            libExtList = ["so"]
            libExtPython = "so"
            if not openmm_lib_path:
                arch = platform.architecture()[0]
                if arch=='32bit':
                    openmm_lib_path=os.path.join("OpenMM", 'linux', 'OpenMM')
                elif arch=='64bit':
                    openmm_lib_path=os.path.join("OpenMM", 'linux64', 'OpenMM')
                else:
                    s="%s platforms are not currently supported" % arch
                    raise Exception(s)

# Copy the appropriate OpenMM and wrapper libs into the source area.
# This is an ugly hack, # but works for installs, building sdist,
# building windows bdist, etc.
    top_lib_path=os.path.join('simtk', 'chem', 'openmm')

    build_wrappers = True
    if check_for_existing_swig_lib:
        swig_lib_name = '_openmm.%s' % libExtPython
        swig_lib_path=os.path.join(openmm_lib_path, '..',
                                        swig_lib_name)
        if os.path.exists(swig_lib_path):
            build_wrappers = False
            shutil.copy(swig_lib_path, top_lib_path)
            setupKeywords["package_data"]['simtk.chem.openmm'].append(swig_lib_name)

    pluginDestDir=os.path.join(top_lib_path, 'OpenMM', 'plugins')
    if not os.path.exists(pluginDestDir):
        os.makedirs(pluginDestDir)
    elif not  os.path.isdir(pluginDestDir):
        raise IOError("file named 'plugins' not allowed: %s" % pluginDestDir)

    openmm_libs=[]
    if platform.system() == "Windows":
        extra_lib_dir=""
    else:
        extra_lib_dir="OpenMM"
    extra_lib_path=os.path.join(top_lib_path, extra_lib_dir)
    for lib_name in libraries:
        for libExt in libExtList:
            openmm_lib_name="%s%s.%s" % (libPrefix, lib_name, libExt)
            shutil.copy(os.path.join(openmm_lib_path, openmm_lib_name),
                        extra_lib_path)
            openmm_libs.append(os.path.join(extra_lib_dir, openmm_lib_name))

    openmm_plugins_path=os.path.join(openmm_lib_path, 'plugins')
    openmm_plugins=[]
    pluginFiles=[]
    for libExt in libExtList:
        pathname = os.path.join(openmm_plugins_path, "*.%s" % (libExt))
        pluginFiles.extend(glob.glob(pathname))
    for pluginFile in pluginFiles:
        shutil.copy(pluginFile, pluginDestDir)
        newFile = os.path.join('OpenMM', 'plugins',
                               os.path.split(pluginFile)[-1])
        openmm_plugins.append(newFile)

    for filename in openmm_libs+openmm_plugins:
        setupKeywords["package_data"]['simtk.chem.openmm'].append(filename)

    # Stupid Mac libraries...
    if must_fix_mac_install_names:
        import fixInstallNames
        (returnErr, log_string) = fixInstallNames.fix_mac_install_names(
                                                      top_lib_path,
                                                      openmm_libs,
                                                      openmm_plugins)
        if returnErr!=0:
            sys.stdout.write("Problem running Mac's install_name_tool: %d\n"
                              % returnErr)
            sys.stdout.write(log_string)

    library_dirs=[extra_lib_path]
    if os.getenv('LD_LIBRARY_PATH'):
        for item in os.getenv('LD_LIBRARY_PATH').split(":"):
            if item: 
                library_dirs.append(item)

    include_dirs=[openmm_include_path]

    if build_wrappers:
        setupKeywords["ext_modules"] = [
           Extension(name = "simtk.chem.openmm._openmm",
                     sources = ["src/swig_doxygen/OpenMMSwig.cxx"],
                     include_dirs = include_dirs,
                     define_macros = define_macros,
                     library_dirs = library_dirs,
                     libraries = libraries,
                     runtime_library_dirs = runtime_library_dirs,
                     extra_compile_args=extra_compile_args,
                     extra_link_args=extra_link_args,
                     )
        ]

    return setupKeywords
    

def main():
    if sys.version_info < (2, 5):
        s="ERROR: PyOpenMM requires Python 2.5 or better.\n"
        sys.stdout.write(s)
        sys.stdout.write("Exiting\n")
        sys.exit(1)
    if sys.version_info >= (3,):
        s="ERROR: PyOpenMM has not been tested with Python 3.0 or higher.\n"
        sys.stdout.write(s)
        sys.stdout.write("Exiting\n")
        sys.exit(1)
    if platform.system() == 'Darwin':
        #productVersion=os.popen('sw_vers -productVersion').readline()
        #macVersion=[int(x) for x in productVersion.split('.')[:2]]
        #if tuple(macVersion)<(10, 5):
        macVersion = [int(x) for x in platform.mac_ver()[0].split('.')]
        if tuple(macVersion) < (10, 5):
            s="ERROR: PyOpenMM requires Mac OS X Leopard (10.5) or better.\n"
            sys.stdout.write(s)
            sys.stdout.write("Exiting\n")
            sys.exit(1)
    uninstall()
    setupKeywords=buildKeywordDictionary()
    setup(**setupKeywords)

if __name__ == '__main__':
    main()


