#!/usr/bin/env python
import glob
import os
import platform
import shutil
import stat
import sys

from site import getusersitepackages
from distutils import log
from distutils import dir_util
from distutils.command.build_clib import build_clib
from distutils.command.sdist import sdist
from distutils.core import setup
from distutils.sysconfig import get_python_lib

# prebuilt libraries for Windows - for sdist
PATH_LIB64 = "prebuilt/win64/capstone.dll"
PATH_LIB32 = "prebuilt/win32/capstone.dll"

# package name can be 'capstone' or 'capstone-windows'
PKG_NAME = 'capstone'
if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
    PKG_NAME = 'capstone-windows'

VERSION = '3.0.3'
SYSTEM = sys.platform

if "--user" in sys.argv:
    SITE_PACKAGES = os.path.join(getusersitepackages(), "capstone")
else:
    SITE_PACKAGES = os.path.join(get_python_lib(), "capstone")


SETUP_DATA_FILES = []

# adapted from commit e504b81 of Nguyen Tan Cong
# Reference: https://docs.python.org/2/library/platform.html#cross-platform
is_64bits = sys.maxsize > 2**32

def copy_sources():
    """Copy the C sources into the source directory.
    This rearranges the source files under the python distribution
    directory.
    """
    src = []

    try:
        dir_util.remove_tree("src/")
    except (IOError, OSError):
        pass

    dir_util.copy_tree("../../arch", "src/arch/")
    dir_util.copy_tree("../../include", "src/include/")
    dir_util.copy_tree("../../msvc/headers", "src/msvc/headers")

    src.extend(glob.glob("../../*.[ch]"))
    src.extend(glob.glob("../../*.mk"))

    src.extend(glob.glob("../../Makefile"))
    src.extend(glob.glob("../../LICENSE*"))
    src.extend(glob.glob("../../README"))
    src.extend(glob.glob("../../*.TXT"))
    src.extend(glob.glob("../../RELEASE_NOTES"))
    src.extend(glob.glob("../../make.sh"))
    src.extend(glob.glob("../../CMakeLists.txt"))

    for filename in src:
        outpath = os.path.join("./src/", os.path.basename(filename))
        log.info("%s -> %s" % (filename, outpath))
        shutil.copy(filename, outpath)


class custom_sdist(sdist):
    """Reshuffle files for distribution."""

    def run(self):
        # if prebuilt libraries are existent, then do not copy source
        if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
            return sdist.run(self)
        copy_sources()
        return sdist.run(self)


class custom_build_clib(build_clib):
    """Customized build_clib command."""

    def run(self):
        log.info('running custom_build_clib')
        build_clib.run(self)

    def finalize_options(self):
        # We want build-clib to default to build-lib as defined by the "build"
        # command.  This is so the compiled library will be put in the right
        # place along side the python code.
        self.set_undefined_options('build',
                                   ('build_lib', 'build_clib'),
                                   ('build_temp', 'build_temp'),
                                   ('compiler', 'compiler'),
                                   ('debug', 'debug'),
                                   ('force', 'force'))

        build_clib.finalize_options(self)

    def build_libraries(self, libraries):
        if SYSTEM in ("win32", "cygwin"):
            # if Windows prebuilt library is available, then include it
            if is_64bits and os.path.exists(PATH_LIB64):
                SETUP_DATA_FILES.append(PATH_LIB64)
                return
            elif os.path.exists(PATH_LIB32):
                SETUP_DATA_FILES.append(PATH_LIB32)
                return

        # build library from source if src/ is existent
        if not os.path.exists('src'):
            return

        try:
            for (lib_name, build_info) in libraries:
                log.info("building '%s' library", lib_name)

                os.chdir("src")

                # platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
                if SYSTEM == "win32":
                    # Windows build: this process requires few things:
                    #    - CMake + MSVC installed
                    #    - Run this command in an environment setup for MSVC
                    os.mkdir("build")
                    os.chdir("build")
                    # Do not build tests & static library
                    os.system('cmake -DCMAKE_BUILD_TYPE=RELEASE -DCAPSTONE_BUILD_TESTS=0 -DCAPSTONE_BUILD_STATIC=0 -G "NMake Makefiles" ..')
                    os.system("nmake")
                    os.chdir("..")
                    SETUP_DATA_FILES.append("src/build/capstone.dll")
                elif SYSTEM == "cygwin":
                    os.chmod("make.sh", stat.S_IREAD|stat.S_IEXEC)
                    if is_64bits:
                        os.system("CAPSTONE_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw64")
                    else:
                        os.system("CAPSTONE_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw32")
                    SETUP_DATA_FILES.append("src/capstone.dll")
                else:   # Unix
                    os.chmod("make.sh", stat.S_IREAD|stat.S_IEXEC)
                    os.system("CAPSTONE_BUILD_CORE_ONLY=yes ./make.sh")
                    if SYSTEM == "darwin":
                        SETUP_DATA_FILES.append("src/libcapstone.dylib")
                    else:   # Non-OSX
                        SETUP_DATA_FILES.append("src/libcapstone.so")

                os.chdir("..")
        except:
            pass


def dummy_src():
    return []


setup(
    provides=['capstone'],
    packages=['capstone'],
    name=PKG_NAME,
    version=VERSION,
    author='Nguyen Anh Quynh',
    author_email='aquynh@gmail.com',
    description='Capstone disassembly engine',
    url='http://www.capstone-engine.org',
    classifiers=[
        'License :: OSI Approved :: BSD License',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 3',
    ],
    requires=['ctypes'],
    cmdclass=dict(
        build_clib=custom_build_clib,
        sdist=custom_sdist,
    ),

    libraries=[(
        'capstone', dict(
            package='capstone',
            sources=dummy_src()
        ),
    )],

    data_files=[(SITE_PACKAGES, SETUP_DATA_FILES)],
)
