
import os
import sys
import subprocess
import shutil

installPath = "@CMAKE_INSTALL_PREFIX@"  # "/Users/paul/projets/CloudCompare/installConda/CloudComPy310"
condaPath = "@CONDA_LIBS@"              # "/Users/paul/miniconda3/envs/CloudComPy310/lib"
fbxPath = "@FBX_SDK_LIBRARY_DIR@"       #"/Applications/Autodesk/FBX SDK/2020.2.1/lib/clang/release"
mainprg =installPath + "/CloudCompare/CloudCompare.app/Contents/MacOS/CloudCompare"
frameworkspath = '../Frameworks'
pluginpath = '../PlugIns/ccPlugins'

def getlibs(mainlib):
    libs = []
    libex = []
    with subprocess.Popen(['otool', '-L', mainlib], stdout=subprocess.PIPE) as proc:
        lines = proc.stdout.readlines()
        for l in lines:
            res = l.decode()
            #print("   ", res.strip())
            vals = l.split()
            if len(vals) < 2:
                continue
            pathlib = vals[0].decode()
            #print("     ", pathlib)
            dirs = pathlib.split("/")
            if dirs[0] == '@rpath':
                libs.append(dirs[1])
            elif dirs[0] == '@executable_path':
                libs.append(dirs[1])
                print("mainlib: ", mainlib, " target: ", dirs[1])
                libex.append((os.path.basename(mainlib), dirs[1]))
            else:
                if (dirs[1] != 'usr') and (dirs[1] != 'System'):
                    print(dirs)
    return libs, libex

def getrpath(mainlib):
    rpaths = []
    with subprocess.Popen(['otool', '-l', mainlib], stdout=subprocess.PIPE) as proc:
        lines = proc.stdout.readlines()
        for l in lines:
            res = l.decode()
            #print("   ", res.strip())
            vals = res.split()
            #print(vals)
            if len(vals) > 1 and vals[0] == 'path':
                rpaths.append(vals[1])
    return rpaths

def convertRpaths(lib, rpaths):
    libpath = os.path.dirname(lib)
    absrpaths = []
    for rpath in rpaths:
        if rpath[0] == '@':
            vals = rpath.split('/')
            absrp = libpath
            if len(vals) > 1:
                for val in vals[1:]:
                    absrp = os.path.abspath(os.path.join(absrp, val))
            #print(absrp)
        else:
            absrp = os.path.abspath(rpath)
        absrpaths.append(absrp)
    return absrpaths


mainpath = os.path.dirname(mainprg)
absFrameworksPath = os.path.abspath(os.path.join(mainpath, frameworkspath))
print(" --- Frameworks path: ", absFrameworksPath)
absPluginPath = os.path.abspath(os.path.join(mainpath, pluginpath))
print(" --- plugin path: ", absPluginPath)

libsfound = []
libexfound = []
libsToCheck = [mainprg]
for filename in os.listdir(absPluginPath):
    f = os.path.join(absPluginPath, filename)
    #print("f:",f)
    if os.path.isfile(f) and (os.path.splitext(f)[1] == '.dylib' or os.path.splitext(f)[1] == '.so'):
        libsToCheck.append(f)

while len(libsToCheck):
    #print(" ... libsToCheck:", len(libsToCheck))
    #print(" ... libsfound:", len(libsfound))

    lib2check = libsToCheck.pop(0)
    if not lib2check in libsfound:
        libsfound.append(lib2check)
    #print(" --- lib2check: ", lib2check)
    libs, libex = getlibs(lib2check)
    #print("   libs:", libs)
    for maintar in libex:
        if not maintar in libexfound:
            libexfound.append(maintar)

    rpaths = getrpath(lib2check)
    #print("   rpaths:", rpaths)

    absrpaths = convertRpaths(lib2check, rpaths)
    if not condaPath in absrpaths:
        absrpaths.append(condaPath)
    if not fbxPath in absrpaths:
        absrpaths.append(fbxPath)
    #print("   absrpaths:", absrpaths)
    
    for lib in libs:
        #print("    --- lib:", lib)
        for absrp in absrpaths:

            alib = os.path.join(absrp, lib)
            if os.path.isfile(alib):
                #print("      exist:",alib)
                if not alib in libsToCheck and not alib in libsfound:
                    libsToCheck.append(alib)
                break

print("libexfound",libexfound)

libsfound.sort()             
print("libsfound:", len(libsfound))
#print("libsfound:", libsfound)
for filename in os.listdir(absFrameworksPath):
    #print(filename, os.path.splitext(filename))
    if os.path.splitext(filename)[1] == '.so':
        print("addr path: ", filename)
        subprocess.run(["install_name_tool", "-add_rpath", "@loader_path/../PlugIns/ccPlugins", os.path.join(absFrameworksPath, filename)])
        subprocess.run(["install_name_tool", "-add_rpath", "@loader_path", os.path.join(absFrameworksPath, filename)])
        subprocess.run(["install_name_tool", "-change", "@executable_path/libfbxsdk.dylib", "@rpath/libfbxsdk.dylib", os.path.join(absFrameworksPath, filename)])


libsInFrameworks = os.listdir(absFrameworksPath)
libsInPlugins = os.listdir(absPluginPath)

for lib in libsfound:
    if lib == mainprg:
        continue
    base = os.path.basename(lib)
    if base not in libsInFrameworks and base not in libsInPlugins:
        print("copy:",lib)
        shutil.copy2(lib, absFrameworksPath)
for maintar in libexfound:
    base = maintar[0]
    target = maintar[1]
    if os.path.isfile(os.path.join(absFrameworksPath, base)):
       print("modify rpath: ",os.path.join(absFrameworksPath, base))
       subprocess.run(["install_name_tool", "-change", "@executable_path/"+target, "@rpath/"+target, os.path.join(absFrameworksPath, base)])
    elif os.path.isfile(os.path.join(absPluginPath, base)):
       print("modify rpath: ",os.path.join(absPluginPath, base))
       subprocess.run(["install_name_tool", "-change", "@executable_path/"+target, "@rpath/"+target, os.path.join(absPluginPath, base)])

for filename in os.listdir(absPluginPath):
    f = os.path.join(absPluginPath, filename)
    if os.path.isfile(f) and os.path.splitext(f)[1] == '.dylib':
        subprocess.run(["install_name_tool", "-add_rpath", "@loader_path/../../Frameworks", f])

for filename in os.listdir(absFrameworksPath):
    f = os.path.join(absFrameworksPath, filename)
    if os.path.isfile(f) and os.path.splitext(f)[1] == '.dylib':
        subprocess.run(["install_name_tool", "-add_rpath", "@loader_path", f])



