"""
finder.py
------------

Locate `libspatialindex` shared library by any means necessary.
"""
import ctypes
import os
import platform
import sys
from ctypes.util import find_library

# the current working directory of this file
_cwd = os.path.abspath(os.path.expanduser(os.path.dirname(__file__)))

# generate a bunch of candidate locations where the
# libspatialindex shared library *might* be hanging out
_candidates = [
    os.environ.get("SPATIALINDEX_C_LIBRARY", None),
    os.path.join(_cwd, "lib"),
    _cwd,
    "",
]


def load() -> ctypes.CDLL:
    """Load the `libspatialindex` shared library.

    :returns: Loaded shared library
    """
    if os.name == "nt":
        # check the platform architecture
        if "64" in platform.architecture()[0]:
            arch = "64"
        else:
            arch = "32"
        lib_name = f"spatialindex_c-{arch}.dll"

        # add search paths for conda installs
        if (
            os.path.exists(os.path.join(sys.prefix, "conda-meta"))
            or "conda" in sys.version
        ):
            _candidates.append(os.path.join(sys.prefix, "Library", "bin"))

        # get the current PATH
        oldenv = os.environ.get("PATH", "").strip().rstrip(";")
        # run through our list of candidate locations
        for path in _candidates:
            if not path or not os.path.exists(path):
                continue
            # temporarily add the path to the PATH environment variable
            # so Windows can find additional DLL dependencies.
            os.environ["PATH"] = ";".join([path, oldenv])
            try:
                rt = ctypes.cdll.LoadLibrary(os.path.join(path, lib_name))
                if rt is not None:
                    return rt
            except OSError:
                pass
            except BaseException as E:
                print(f"rtree.finder unexpected error: {E!s}")
            finally:
                os.environ["PATH"] = oldenv
        raise OSError(f"could not find or load {lib_name}")

    elif os.name == "posix":

        # posix includes both mac and linux
        # use the extension for the specific platform
        if platform.system() == "Darwin":
            # macos shared libraries are `.dylib`
            lib_name = "libspatialindex_c.dylib"
        else:
            # linux shared libraries are `.so`
            lib_name = "libspatialindex_c.so"

        # get the starting working directory
        cwd = os.getcwd()
        for cand in _candidates:
            if cand is None:
                continue
            elif os.path.isdir(cand):
                # if our candidate is a directory use best guess
                path = cand
                target = os.path.join(cand, lib_name)
            elif os.path.isfile(cand):
                # if candidate is just a file use that
                path = os.path.split(cand)[0]
                target = cand
            else:
                continue

            if not os.path.exists(target):
                continue

            try:
                # move to the location we're checking
                os.chdir(path)
                # try loading the target file candidate
                rt = ctypes.cdll.LoadLibrary(target)
                if rt is not None:
                    return rt
            except BaseException as E:
                print(f"rtree.finder ({target}) unexpected error: {E!s}")
            finally:
                os.chdir(cwd)

    try:
        # try loading library using LD path search
        path = find_library("spatialindex_c")
        if path is not None:
            return ctypes.cdll.LoadLibrary(path)

    except BaseException:
        pass

    raise OSError("Could not load libspatialindex_c library")
