# Copyright 2023 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Bazel-related functions."""

import dataclasses
from typing import Any

from PB.recipe_modules.pigweed.bazel.options import Options
from RECIPE_MODULES.pigweed.checkout import api as checkout_api

from recipe_engine import config_types, recipe_api


# This is copied from bazel.json in Pigweed, but there's no need to keep it
# up-to-date.
_JSON_TEST_DATA: dict[str, Any] = {
    "included_files": [],
    "packages": [
        {
            "path": "fuchsia/third_party/bazel/${platform}",
            "platforms": ["linux-amd64", "mac-amd64", "windows-amd64"],
            "tags": ["version:2@6.3.0.6"],
            "version_file": ".versions/bazel.cipd_version",
        },
        {
            "path": "flutter/java/openjdk/${platform}",
            "platforms": [
                "linux-amd64",
                "mac-amd64",
                "mac-arm64",
                "windows-amd64",
            ],
            "tags": ["version:17"],
        },
    ],
}


@dataclasses.dataclass
class BazelRunner:
    api: recipe_api.RecipeApi
    checkout_root: config_types.Path
    options: Options
    bazel: config_types.Path | None = None

    def ensure(self) -> config_types.Path:
        if self.bazel:
            return self.bazel

        # read_json in a few lines requires absolute, normalized paths.
        json_path: config_types.Path = self.api.path.abspath(
            self.checkout_root / self.options.cipd_json_path
        )

        ensure_file: self.api.cipd.EnsureFile = self.api.cipd.EnsureFile()
        for package in self.api.file.read_json(
            f'read {self.api.path.basename(json_path)}',
            json_path,
            test_data=_JSON_TEST_DATA,
        )["packages"]:
            ensure_file.add_package(package['path'], package['tags'][0])

        root: config_types.Path = self.api.path.mkdtemp()
        self.api.cipd.ensure(root, ensure_file, name='ensure bazel')
        self.bazel = root / 'bazel'
        return self.bazel

    def run(self, **kwargs) -> None:
        name: str = ' '.join(['bazel'] + list(self.options.args))
        with self.api.context(cwd=self.checkout_root):
            self.api.step(name, [self.ensure(), *self.options.args], **kwargs)

            for invocation in self.options.invocations:
                name: str = ' '.join(['bazel'] + list(invocation.args))
                self.api.step(name, [self.ensure(), *invocation.args], **kwargs)


class BazelApi(recipe_api.RecipeApi):
    """Bazel utilities."""

    BazelRunner = BazelRunner

    def new_runner(
        self,
        checkout: checkout_api.CheckoutContext,
        options: Options,
    ) -> BazelRunner:
        return BazelRunner(self.m, checkout.root, options)
