#!/usr/bin/env python3.8
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import os
import shutil
import stat
import sys

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
FUCHSIA_ROOT = os.path.dirname(  # $root
    os.path.dirname(             # scripts
    os.path.dirname(             # sdk
    SCRIPT_DIR)))                # bazel

sys.path += [os.path.join(FUCHSIA_ROOT, 'scripts', 'sdk', 'common')]
from frontend import Frontend
from files import copy_tree

from create_test_workspace import create_test_workspace, SdkWorkspaceInfo
import template_model as model


def sanitize(name):
    return name.replace('-', '_').replace('.', '_')


class BazelBuilder(Frontend):

    def __init__(self, **kwargs):
        self.install = kwargs.pop('install', True)
        super(BazelBuilder, self).__init__(**kwargs)
        self.has_dart = False
        self.has_cc = False
        self.dart_vendor_packages = {}
        self.target_arches = []
        self.workspace_info = SdkWorkspaceInfo()

    def add_dart_vendor_package(self, name, version):
        '''Adds a reference to a new Dart third-party package.'''
        if name == 'flutter' and version == 'flutter_sdk':
            # The Flutter SDK is set up separately.
            return
        if name in self.dart_vendor_packages:
            existing_version = self.dart_vendor_packages[name]
            if existing_version != version:
                raise Exception(
                    'Dart package %s can only have one version; '
                    '%s and %s requested.' % (name, version, existing_version))
        else:
            self.dart_vendor_packages[name] = version

    def prepare(self, arch, types):
        self.target_arches = arch['target']
        cc_types = ('sysroot', 'cc_source_library', 'cc_prebuilt_library')
        self.has_cc = any(t in types for t in cc_types)

        if self.install:
            # Copy the common files.
            shutil.copytree(self.local('base', 'common'), self.output)
            # Copy C/C++ files if needed.
            if self.has_cc:
                copy_tree(self.local('base', 'cc'), self.output)
            # Copy Dart files if needed.
            if 'dart_library' in types:
                # fxbug.dev/41514 : disable dart/flutter bits
                # self.has_dart = True
                # copy_tree(self.local('base', 'dart'), self.output)
                pass

        self.install_crosstool(arch)

        self.workspace_info.with_cc = self.has_cc
        self.workspace_info.with_dart = self.has_dart
        self.workspace_info.target_arches = self.target_arches

    def finalize(self, arch, types):
        self.install_tools()
        self.install_dart()

    def install_tools(self):
        '''Write BUILD files for tools directories.'''
        if not self.install:
            return

        tools_root = os.path.join(self.output, 'tools')
        for directory, _, _ in os.walk(tools_root, topdown=True):
            self.write_file(os.path.join(directory, 'BUILD'), 'tools', {})

    def install_crosstool(self, arches):
        '''Generates crosstool.bzl based on the availability of sysroot
        versions.
        '''
        if not self.has_cc or not self.install:
            return

        crosstool = model.Crosstool(arches['target'])
        crosstool_base = self.dest('build_defs', 'internal', 'crosstool')
        self.write_file(
            self.dest(crosstool_base, 'crosstool.bzl'), 'crosstool_bzl',
            crosstool)
        self.write_file(
            self.dest(crosstool_base, 'BUILD.crosstool'), 'crosstool',
            crosstool)
        self.write_file(
            self.dest(crosstool_base, 'cc_toolchain_config.bzl.in'), 'cc_toolchain_config_bzl_in',
            crosstool)
        self.write_file(
            self.dest('build_defs', 'toolchain', 'BUILD'), 'toolchain_build',
            crosstool)

    def install_dart(self):
        if not self.has_dart or not self.install:
            return
        # Write the rule for setting up Dart packages.
        # TODO(pylaligand): this process currently does not capture dependencies
        # between vendor packages.
        self.write_file(
            self.dest('build_defs', 'setup_dart.bzl'), 'setup_dart_bzl',
            self.dart_vendor_packages)

    def install_dart_library_atom(self, atom):
        if not self.has_dart or not self.install:
            return

        package_name = atom['name']
        name = sanitize(package_name)
        library = model.DartLibrary(name, package_name)
        base = self.dest('dart', name)

        self.copy_files(atom['sources'], atom['root'], base)

        for dep in atom['deps']:
            library.deps.append('//dart/' + sanitize(dep))

        for dep in atom['fidl_deps']:
            san_dep = sanitize(dep)
            library.deps.append('//fidl/%s:%s_dart' % (san_dep, san_dep))

        for dep in atom['third_party_deps']:
            name = dep['name']
            library.deps.append('@vendor_%s//:%s' % (name, name))
            self.add_dart_vendor_package(name, dep['version'])

        self.write_file(os.path.join(base, 'BUILD'), 'dart_library', library)

    def install_cc_prebuilt_library_atom(self, atom):
        name = sanitize(atom['name'])
        include_paths = [os.path.relpath(h, atom['include_dir']) for h in atom['headers']]
        self.workspace_info.headers['//pkg/' + name] = include_paths

        if not self.install:
            return

        library = model.CppPrebuiltLibrary(name)
        library.is_static = atom['format'] == 'static'
        base = self.dest('pkg', name)
        self.copy_files(atom['headers'], atom['root'], base, library.hdrs)

        for arch in self.target_arches:

            def _copy_prebuilt(path, category):
                relative_dest = os.path.join(
                    'arch', arch, category, os.path.basename(path))
                dest = self.dest(base, relative_dest)
                shutil.copy2(self.source(path), dest)
                return relative_dest

            binaries = atom['binaries'][arch]
            prebuilt_set = model.CppPrebuiltSet(
                _copy_prebuilt(binaries['link'], 'lib'))
            if 'dist' in binaries:
                dist = binaries['dist']
                prebuilt_set.dist_lib = _copy_prebuilt(dist, 'dist')
                prebuilt_set.dist_path = 'lib/' + os.path.basename(dist)

            if 'debug' in binaries:
                self.copy_file(binaries['debug'])

            library.prebuilts[arch] = prebuilt_set

        for dep in atom['deps']:
            library.deps.append('//pkg/' + sanitize(dep))

        library.includes = os.path.relpath(atom['include_dir'], atom['root'])

        self.write_file(
            os.path.join(base, 'BUILD'), 'cc_prebuilt_library', library)

    def install_cc_source_library_atom(self, atom):
        name = sanitize(atom['name'])
        include_paths = [os.path.relpath(h, atom['include_dir']) for h in atom['headers']]
        self.workspace_info.headers['//pkg/' + name] = include_paths

        if not self.install:
            return

        library = model.CppSourceLibrary(name)
        base = self.dest('pkg', name)
        self.copy_files(atom['headers'], atom['root'], base, library.hdrs)
        self.copy_files(atom['sources'], atom['root'], base, library.srcs)

        for dep in atom['deps']:
            library.deps.append('//pkg/' + sanitize(dep))

        for dep in atom['fidl_deps']:
            dep_name = sanitize(dep)
            library.deps.append('//fidl/%s:%s_cc' % (dep_name, dep_name))

        library.includes = os.path.relpath(atom['include_dir'], atom['root'])

        self.write_file(os.path.join(base, 'BUILD'), 'cc_library', library)

    def install_sysroot_atom(self, atom):
        if not self.install:
            return

        for arch in self.target_arches:
            base = self.dest('arch', arch, 'sysroot')
            arch_data = atom['versions'][arch]
            self.copy_files(arch_data['headers'], arch_data['root'], base)
            self.copy_files(arch_data['link_libs'], arch_data['root'], base)
            # We maintain debug files in their original location.
            self.copy_files(arch_data['debug_libs'])
            dist_libs = []
            self.copy_files(
                arch_data['dist_libs'], arch_data['root'], base, dist_libs)
            version = {}
            for lib in dist_libs:
                version['lib/' + os.path.basename(lib)] = lib
            self.write_file(
                os.path.join(base, 'BUILD'), 'sysroot_version', version)

        self.write_file(
            self.dest('pkg', 'sysroot', 'BUILD'), 'sysroot_pkg',
            self.target_arches)

    def install_host_tool_atom(self, atom):
        if not self.install:
            return

        if 'files' in atom:
            self.copy_files(atom['files'], atom['root'], 'tools')
        if 'target_files' in atom:
            for files in atom['target_files'].values():
                self.copy_files(files, atom['root'], 'tools')

    def install_fidl_library_atom(self, atom):
        name = sanitize(atom['name'])
        self.workspace_info.fidl_libraries.append(name)

        if not self.install:
            return

        data = model.FidlLibrary(name, atom['name'])
        data.with_cc = self.has_cc
        data.with_dart = self.has_dart
        base = self.dest('fidl', name)
        self.copy_files(atom['sources'], atom['root'], base, data.srcs)
        for dep in atom['deps']:
            data.deps.append(sanitize(dep))
        self.write_file(os.path.join(base, 'BUILD'), 'fidl', data)


def main():
    parser = argparse.ArgumentParser(
        description='Lays out a Bazel workspace for a given SDK tarball.')
    source_group = parser.add_mutually_exclusive_group(required=True)
    source_group.add_argument(
        '--archive', help='Path to the SDK archive to ingest', default='')
    source_group.add_argument(
        '--directory', help='Path to the SDK directory to ingest', default='')
    parser.add_argument(
        '--output',
        help='Path to the directory where to install the SDK',
        required=True)
    parser.add_argument(
        '--tests', help='Path to the directory where to generate tests')
    parser.add_argument(
        '--nosdk',
        action='store_false',
        dest='install_sdk',
        help='''Do not
        install the Bazel SDK. If --tests is set, the tests will still be
        generated, but the Bazel SDK must be installed at the location specified
        by --output before running the tests.''')
    args = parser.parse_args()

    if args.install_sdk:
        # Remove any existing output.
        shutil.rmtree(args.output, ignore_errors=True)

    builder = BazelBuilder(
        archive=args.archive,
        directory=args.directory,
        output=args.output,
        local_dir=SCRIPT_DIR,
        install=args.install_sdk)
    if not builder.run():
        return 1

    if args.tests and not create_test_workspace(args.output, args.tests,
                                                builder.workspace_info):
        return 1

    return 0


if __name__ == '__main__':
    sys.exit(main())
