# swift_build_support/products/swiftpm.py -----------------------*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2019 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
#
# ----------------------------------------------------------------------------

import os

from . import cmark
from . import foundation
from . import libcxx
from . import libdispatch
from . import libicu
from . import llbuild
from . import llvm
from . import product
from . import swift
from . import xctest
from .. import shell


class SwiftPM(product.Product):
    @classmethod
    def product_source_name(cls):
        return "swiftpm"

    @classmethod
    def is_build_script_impl_product(cls):
        return False

    def should_build(self, host_target):
        return True

    def run_bootstrap_script(self, action, host_target, additional_params=[]):
        script_path = os.path.join(
            self.source_dir, 'Utilities', 'bootstrap')
        toolchain_path = self.install_toolchain_path(host_target)
        swiftc = os.path.join(toolchain_path, "bin", "swiftc")

        # FIXME: We require llbuild build directory in order to build. Is
        # there a better way to get this?
        build_root = os.path.dirname(self.build_dir)
        llbuild_build_dir = os.path.join(
            build_root, '%s-%s' % ("llbuild", host_target))

        helper_cmd = [script_path, action]

        if action == 'clean':
            helper_cmd += ["--build-dir", self.build_dir]
            shell.call(helper_cmd)
            return

        if self.is_release():
            helper_cmd.append("--release")

        helper_cmd += [
            "--swiftc-path", swiftc,
            "--clang-path", self.toolchain.cc,
            "--cmake-path", self.toolchain.cmake,
            "--ninja-path", self.toolchain.ninja,
            "--build-dir", self.build_dir,
            "--llbuild-build-dir", llbuild_build_dir
        ]

        # Pass Dispatch directory down if we built it
        dispatch_build_dir = os.path.join(
            build_root, '%s-%s' % ("libdispatch", host_target))

        # SWIFT_ENABLE_TENSORFLOW
        # Don't pass in these args since they interfere with yams.
        # if os.path.exists(dispatch_build_dir):
        #     helper_cmd += [
        #         "--dispatch-build-dir", dispatch_build_dir
        #     ]

        # Pass Foundation directory down if we built it
        foundation_build_dir = os.path.join(
            build_root, '%s-%s' % ("foundation", host_target))

        # if os.path.exists(foundation_build_dir):
        #     helper_cmd += [
        #         "--foundation-build-dir", foundation_build_dir
        #     ]
        # SWIFT_ENABLE_TENSORFLOW END

        # Pass Cross compile host info
        if self.has_cross_compile_hosts(self.args):
            helper_cmd += ['--cross-compile-hosts']
            for cross_compile_host in self.args.cross_compile_hosts:
                helper_cmd += [cross_compile_host]

        helper_cmd.extend(additional_params)

        shell.call(helper_cmd)

    def build(self, host_target):
        self.run_bootstrap_script('build', host_target, ["--reconfigure"])

    def should_test(self, host_target):
        return self.args.test_swiftpm

    def test(self, host_target):
        self.run_bootstrap_script('test', host_target)

    def should_clean(self, host_target):
        return self.args.clean_swiftpm

    def clean(self, host_target):
        self.run_bootstrap_script('clean', host_target)

    def should_install(self, host_target):
        return self.args.install_swiftpm

    @classmethod
    def has_cross_compile_hosts(self, args):
        return args.cross_compile_hosts

    @classmethod
    def get_install_destdir(self, args, host_target, build_dir):
        install_destdir = args.install_destdir
        if self.has_cross_compile_hosts(args):
            build_root = os.path.dirname(build_dir)
            install_destdir = '%s/intermediate-install/%s' % (build_root, host_target)
        return install_destdir

    def install(self, host_target):
        install_destdir = self.get_install_destdir(self.args,
                                                   host_target,
                                                   self.build_dir)
        install_prefix = install_destdir + self.args.install_prefix

        self.run_bootstrap_script('install', host_target, [
            '--prefix', install_prefix
        ])

    @classmethod
    def get_dependencies(cls):
        return [cmark.CMark,
                llvm.LLVM,
                libcxx.LibCXX,
                libicu.LibICU,
                swift.Swift,
                libdispatch.LibDispatch,
                foundation.Foundation,
                xctest.XCTest,
                llbuild.LLBuild]
