#!/usr/bin/env python

# install-lldb-swift.py
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ------------------------------------------------------------------------------

# This script will install the files from an LLDB build into Xcode.

import argparse
import os
import shutil
import sys

parser = argparse.ArgumentParser(
    description="Installs the files from an LLDB build into Xcode.  Without options, tries to do the right thing.")
parser.add_argument("-l", "--lldb", help="Path to build/Configuration.")
parser.add_argument(
    "-s",
    "--swift",
    help="Path to llvm-build/LLVMConfig/arch/LLVMConfig.")
parser.add_argument("-x", "--xcode", help="Path to Xcode.app.")
parser.add_argument(
    "-d",
    "--dry",
    help="Dry run: log what would happen but don't do it.",
    action="store_true")

args = parser.parse_args()


def checkCandidates(candidates, checker):
    for candidate in candidates:
        if checker(candidate):
            return candidate
    return None

# Checker helpers


def checkDirOrLink(path):
    return (os.path.isdir(path) or os.path.islink(path))


def checkFileOrLink(path):
    return (os.path.isfile(path) or os.path.islink(path))

# Find an LLDB build


def checkLLDB(path):
    if not checkFileOrLink(path + "/lldb"):
        return False
    if not checkDirOrLink(path + "/LLDB.framework"):
        return False
    return True


def findLLDB():
    lldb_candidates = [
        "build/DebugClang",
        "build/Debug",
        "build/Release"
    ]
    return checkCandidates(lldb_candidates, checkLLDB)

# Find a Swift build


def checkSwift(path):
    if not checkFileOrLink(path + "/bin/swift"):
        return False
    if not checkDirOrLink(path + "/lib/swift"):
        return False
    return True


def findSwift():
    swift_candidates = [
        "llvm-build/Debug+Asserts/x86_64",
        "llvm-build/Debug/x86_64",
        "llvm-build/Release+Debug/x86_64",
        "llvm-build/Release+Asserts/x86_64",
        "llvm-build/Release/x86_64"
    ]
    return checkCandidates(swift_candidates, checkSwift)

# Find an Xcode installation


def checkXcode(path):
    if not checkFileOrLink(
            path +
            "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift"):
        return False
    if not checkDirOrLink(
            path +
            "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift"):
        return False
    return True


def findXcode():
    xcode_candidates = [
        "/Applications/Xcode.app"
    ]
    return checkCandidates(xcode_candidates, checkXcode)

# Check input arguments


def getPaths():
    lldb = None

    if args.lldb:
        lldb = args.lldb
    else:
        lldb = findLLDB()

    swift = None

    if args.swift:
        swift = args.swift
    else:
        swift = findSwift()

    xcode = None

    if args.xcode:
        xcode = args.xcode
    else:
        xcode = findXcode()

    if not lldb:
        print "Couldn't find LLDB automatically.  Please use --lldb."
        return None
    if not checkLLDB(lldb):
        print "The path passed to --lldb is not a valid LLDB build."
        return None

    if not swift:
        print "Couldn't find Swift automatically.  Please use --swift."
        return None
    if not checkSwift(swift):
        print "The path passed to --swift is not a valid Swift build."
        return None

    if not xcode:
        print "Couldn't find Xcode automatically.  Please use --xcode."
        return None
    if not checkXcode(xcode):
        print "The path passed to --xcode is not a valid Xcode installation."
        return None

    return (lldb, swift, xcode)

# Work unit classes


class WorkUnit:

    def __init__(self, from_path, to_path):
        self.from_path = from_path
        self.to_path = to_path
        self.backup_path = to_path + ".backup"

    # basic operations

    def remove(self, path):
        if os.path.islink(path):
            print "Remove alias " + self.to_path
        elif os.path.isdir(path):
            print "Remove (recursive) " + self.to_path
        else:
            print "Remove " + self.to_path
        if not args.dry:
            if os.path.islink(path):
                os.remove(path)
            elif os.path.isdir(path):
                shutil.rmtree(path)
            else:
                os.remove(path)

    def removeBackup(self):
        self.remove(self.backup_path)

    def backupUnchecked(self):
        print "Move " + self.to_path + " to " + self.backup_path
        if not args.dry:
            os.rename(self.to_path, self.backup_path)

    def removeTo(self):
        self.remove(self.to_path)

    def linkFromTo(self):
        abs_from_path = os.path.abspath(self.from_path)
        print "Link " + abs_from_path + " to " + self.to_path
        if not args.dry:
            os.symlink(abs_from_path, self.to_path)

    # high-level operations

    def checkAndBackup(self):
        if os.path.islink(self.to_path):
            self.removeTo()  # no backup necessary
        else:
            if os.path.exists(self.backup_path):
                self.removeBackup()
            self.backupUnchecked()

    def install(self):
        self.linkFromTo()

# Make path dictionary


def makeWorkUnits(lldb, swift, xcode):
    toolchain = xcode + "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain"
    toolchain_usr_bin = toolchain + "/usr/bin"
    toolchain_usr_lib = toolchain + "/usr/lib"

    work_units = [
        WorkUnit(
            swift +
            "/bin/swift",
            toolchain_usr_bin +
            "/swift"),
        WorkUnit(
            swift +
            "/lib/swift",
            toolchain_usr_lib +
            "/swift"),
        WorkUnit(
            lldb +
            "/LLDB.framework",
            xcode +
            "/Contents/SharedFrameworks/LLDB.framework")]

    # if we've built sourcekitd, install that too

#  ## commented out because a built sourcekit doesn't work
#
#  if os.path.isdir(swift + "/lib/sourcekitd.framework"):
#    work_units.append(WorkUnit(swift + "/lib/sourcekitd.framework", toolchain_usr_lib + "/sourcekitd.framework"))

    return work_units

# Prepare Xcode installation, backing up data as necessary


def prepareAndBackup(work_units):
    for work_unit in work_units:
        work_unit.checkAndBackup()

# Install


def install(work_units):
    for work_unit in work_units:
        work_unit.install()

# Main

validated_paths = getPaths()

if not validated_paths:
    sys.exit(0)

(lldb, swift, xcode) = validated_paths

print "Installing LLDB from " + lldb + " and Swift from " + swift + " into Xcode at " + xcode

work_units = makeWorkUnits(lldb, swift, xcode)

prepareAndBackup(work_units)
install(work_units)
