#!/usr/bin/env python

from __future__ import print_function
import argparse
import os
import sys
import eups


def linkFiles(dstDir, srcDir, verbose=0, force=False):
    """Link all the regular files in srcDir into dstDir; mkdir all the directories in srcDir and
    descend recursively"""

    if not os.path.exists(dstDir):
        os.makedirs(dstDir)

    for fileName in os.listdir(srcDir):
        fullSrc = os.path.join(srcDir, fileName)
        fullDst = os.path.join(dstDir, fileName)

        if os.path.isdir(fullSrc):
            linkFiles(fullDst, fullSrc, verbose, force)
        else:
            if verbose > 1:
                print("%s -> %s" % (fullSrc, fullDst))

            if os.path.exists(fullDst):
                if force:
                    os.unlink(fullDst)
                else:
                    print("%s already exists; use --force to overwrite" % fullDst, file=sys.stderr)
                    sys.exit(1)

            os.symlink(fullSrc, fullDst)


def main():
    parser = argparse.ArgumentParser(description='''Build a link farm to replace long -I/-L argument lists.
All the bin, include files, and libraries for all the dependencies of the specified product are linked into
    linkFarmDir/bin, linkFarmDir/include, or linkFarmDir/lib
as appropriate.  Note that the setup dependencies are used, so you can say e.g.
$ setup pipe_tasks
$ setup -r ~/LSST/afw
$ makeLinkFarm /tmp/linkFarm pipe_tasks
creates a link farm for your current selection of products.
''')
    parser.add_argument('linkFarmDir', type=str, help='The directory to setup as a link farm')
    parser.add_argument('productName', type=str, help='The desired product (must be setup)')

    parser.add_argument('--force', '-f', action='store_true', help="Force creation of farm even if it exists")
    parser.add_argument('--verbose', '-v', action='count', help="Be chatty")

    args = parser.parse_args()

    linkFarmDir = os.path.abspath(args.linkFarmDir)

    if not args.force and os.path.exists(linkFarmDir):
        print("Path %s already exists; use --force to overwrite" % args.linkFarmDir, file=sys.stderr)
        sys.exit(1)

    #
    # create the link farm
    #
    for d in ["bin", "include", "lib"]:
        d = os.path.join(linkFarmDir, d)
        if not os.path.exists(d):
            os.makedirs(d)

    products = {}
    for productName, versionName, optional, recursionDepth in \
            eups.getDependencies(args.productName, None, setup=True):
        if productName in products:
            continue

        products[productName] = 1

        pd = eups.productDir(productName)
        if not pd:                      # no product
            continue

        binDir = os.path.join(pd, "bin")
        incDir = os.path.join(pd, "include")
        libDir = os.path.join(pd, "lib")

        if args.verbose:
            if args.verbose > 1 or \
                    os.path.exists(binDir) or os.path.exists(incDir) or os.path.exists(libDir):
                print("%-15s %s" % (productName, pd))

        if os.path.exists(binDir):
            fullDstDir = os.path.join(linkFarmDir, "bin")
            linkFiles(fullDstDir, binDir, args.verbose, args.force)

        if os.path.exists(incDir):
            fullDstDir = os.path.join(linkFarmDir, "include")
            linkFiles(fullDstDir, incDir, args.verbose, args.force)

        if os.path.exists(libDir):
            for src in os.listdir(libDir):
                if not src.startswith("lib"):
                    continue

                fullSrc = os.path.join(libDir, src)
                fullDst = os.path.join(linkFarmDir, "lib", src)
                if args.verbose > 1:
                    print(src, fullSrc, fullDst)
                if os.path.exists(fullDst):
                    if args.force:
                        os.unlink(fullDst)
                    else:
                        print("%s already exists; use --force to overwrite" % fullDst, file=sys.stderr)
                        sys.exit(1)

                os.symlink(fullSrc, fullDst)


if __name__ == "__main__":
    main()
