# Copyright 2021 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.

from recipe_engine import recipe_api


class CIPDPlatformApi(recipe_api.RecipeApi):
    """Utilities for interacting with CIPD."""

    @property
    def platform_name(self):
        """Returns CIPD's name for the current platform.

        This is the value that the CIPD CLI will substitute for ${platform}
        in any package names that it sees.
        """
        os = self.m.platform.name.replace("win", "windows")
        arch = {"intel": {32: "386", 64: "amd64"}, "arm": {32: "armv6", 64: "arm64"}}[
            self.m.platform.arch
        ][self.m.platform.bits]
        return "%s-%s" % (os, arch)

    def upload_package(
        self,
        pkg_name,
        pkg_root,
        pkg_paths,
        search_tag,
        repository=None,
        install_mode="copy",
        refs=("latest",),
        metadata=None,
        add_version_file=True,
        name=None,
        step_name="cipd",
    ):
        """Creates and uploads a CIPD package containing the tool at pkg_dir.

        The tool is published to CIPD under the path pkg_name.

        Args:
            pkg_name (basestr): The CIPD package to publish to.
            pkg_root (Path): The absolute path to the parent directory of the
                package.
            pkg_paths (list(Path)): A list of Path objects which specify the
                paths to directories or files to upload.
            search_tag (dict): The tag to search for the CIPD pin with. This
                should contain one element and be either `git_revision` or
                `version`.
            repository (str or None): The git repository where code for the
                package lives.
            install_mode (str or None): The install mode for the package.
            refs (str): Refs to set on the package.
            metadata (list of pair/Metadata or None): Metadata to add to the
                package.
            add_version_file (bool): Include a .cipd_version file in the
                package.
            name (str or None): Logical name of the package. Defaults to
                second-to-last part of pkg_name.
            step_name (str): Name of the step.

        Returns:
            The CIPDApi.Pin instance_id.
        """
        pkg_def = self.m.cipd.PackageDefinition(
            package_name=pkg_name, package_root=pkg_root, install_mode=install_mode
        )

        # Mock the existence of the package root directory so `isdir()` will
        # return True.
        self.m.path.mock_add_directory(pkg_root)
        for path in pkg_paths:
            if self.m.path.isdir(path):
                pkg_def.add_dir(path)
            else:
                pkg_def.add_file(path)

        if not name:
            # E.g., "fuchsia/go/linux-amd64" -> "go".
            name = str(pkg_name.split("/")[-2])
        if add_version_file:
            pkg_def.add_version_file(".versions/%s.cipd_version" % name)

        with self.m.step.nest(step_name) as step:
            assert (
                len(search_tag) == 1
            ), "search_tag must contain one (key: value) pair to search for."
            search_tag_key = list(search_tag.keys())[0]
            search_tag_value = search_tag[search_tag_key]
            cipd_pins = self.m.cipd.search(
                pkg_name,
                "%s:%s" % (search_tag_key, search_tag_value),
                test_instances=[],
            )
            if cipd_pins:
                self.m.step("package is up-to-date", cmd=None)
                assert len(cipd_pins) == 1, "%s has too many pins" % pkg_name
                return cipd_pins[0].instance_id

            tags = {}
            tags.update(search_tag)

            final_metadata = [
                self.m.cipd.Metadata("bbid", self.m.buildbucket_util.id),
            ]
            if repository:
                final_metadata.append(
                    self.m.cipd.Metadata("git_repository", repository)
                )

            if metadata:
                for metadatum in metadata:
                    if isinstance(metadatum, self.m.cipd.Metadata):
                        final_metadata.append(metadatum)
                    else:
                        key, value = metadatum
                        final_metadata.append(self.m.cipd.Metadata(key, value))
                        # TODO(fxbug.dev/85982) Remove metadata from tags.
                        tags[key] = value

            cipd_pin = self.m.cipd.create_from_pkg(
                pkg_def=pkg_def,
                refs=refs,
                tags=tags,
                metadata=final_metadata,
            )
            step.presentation.properties.update(cipd_pin._asdict())
            if search_tag:
                # Return search_tag to output properties so it can be
                # used by builders like goma_toolchain.
                step.presentation.properties.update(search_tag)

            return cipd_pin.instance_id
