#!/usr/bin/env python3

#
#   Install dylib dependencies, strip debugging symbols, and deal with the shitfucked digital abortion that is the macOS dynamic linker.
#

import re
import sys
import subprocess
import itertools
import shutil
from os import chmod, environ, pathsep
from pathlib import Path

build_root = Path(environ['MESON_BUILD_ROOT'])
source_root = Path(environ['MESON_SOURCE_ROOT'])
install_prefix = Path(environ['MESON_INSTALL_DESTDIR_PREFIX'])

args = sys.argv[1:]

macos_lib_paths = filter(None, (Path(x) for x in args.pop(0).split(pathsep)))
macos_tool_paths = filter(None, (Path(x) for x in args.pop(0).split(pathsep)))
macos_tool_prefix = args.pop(0)

if macos_tool_paths:
    environ['PATH'] = pathsep.join(itertools.chain((str(p) for p in macos_tool_paths), [environ['PATH']]))

exe_path = install_prefix / 'Taisei.app' / 'Contents' / 'MacOS' / 'Taisei'
dylib_dir_path = exe_path.parent / 'dylibs'
dylib_dir_path.mkdir(mode=0o755, parents=True, exist_ok=True)


def tool(name):
    def func(*args):
        cmd = [macos_tool_prefix + name] + list(args)
        print(' '.join(('{0!r}' if ' ' in str(s) else '{0}').format(str(s)) for s in cmd))
        return subprocess.check_output(cmd, universal_newlines=True)
    return func

otool = tool('otool')
install_name_tool = tool('install_name_tool')
strip = tool('strip')


def fix_libs(opath):
    handled = set()
    regex = re.compile(r'\s*(.*?\.dylib) \(')

    def install(src, dst):
        src = str(src)
        dst = str(dst)
        print('Installing {0} as {1}'.format(src, dst))
        shutil.copy(str(src), str(dst))
        chmod(str(dst), 0o755)

    def fix(path):
        for lib in regex.findall(otool('-L', path)):
            if lib.startswith('/usr/lib') or lib.startswith('@'):
                continue

            src_lib_path = Path(lib)
            dst_lib_path = dylib_dir_path / src_lib_path.name

            install_name_tool(path, '-change', lib, '@executable_path/dylibs/{0}'.format(dst_lib_path.name))

            if dst_lib_path in handled:
                continue

            install(src_lib_path, dst_lib_path)
            handled.add(dst_lib_path)
            fix(dst_lib_path)

        install_name_tool(path, '-id', path.name)
        strip('-S', path)

    fix(opath)
    return handled

new_files = fix_libs(exe_path)

if new_files:
    with (build_root / 'meson-logs' / 'install-log.txt').open('a') as f:
        f.write('# ...except when it does :^)\n')
        for i in new_files:
            f.write('{0}\n'.format(str(i)))
