"""utils for patching libraries"""

# Copyright (c) PyZMQ Developers.
# Distributed under the terms of the Modified BSD License.


import logging
import os
import re
import sys

from .misc import get_output_error

pjoin = os.path.join

# LIB_PAT from delocate
LIB_PAT = re.compile(
    r"\s*(.*) \(compatibility version (\d+\.\d+\.\d+), "
    r"current version (\d+\.\d+\.\d+)\)"
)


def _get_libs(fname):
    rc, so, se = get_output_error(['otool', '-L', fname])
    if rc:
        logging.error(f"otool -L {fname} failed: {se!r}")
        return
    for line in so.splitlines()[1:]:
        m = LIB_PAT.match(line)
        if m:
            yield m.group(1)


def _find_library(lib, path):
    """Find a library"""
    for d in path[::-1]:
        real_lib = os.path.join(d, lib)
        if os.path.exists(real_lib):
            return real_lib


def _install_name_change(fname, lib, real_lib):
    rc, so, se = get_output_error(
        ['install_name_tool', '-change', lib, real_lib, fname]
    )
    if rc:
        logging.error("Couldn't update load path: %s", se)


def patch_lib_paths(fname, library_dirs):
    """Load any weakly-defined libraries from their real location

    (only on OS X)

    - Find libraries with `otool -L`
    - Update with `install_name_tool -change`
    """
    if sys.platform != 'darwin':
        return

    libs = _get_libs(fname)
    for lib in libs:
        if not lib.startswith(('@', '/')):
            real_lib = _find_library(lib, library_dirs)
            if real_lib:
                _install_name_change(fname, lib, real_lib)


__all__ = ['patch_lib_paths']