# Copyright 2021 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.
"""Calls to build code."""

from __future__ import annotations

import dataclasses

from recipe_engine import config_types, recipe_api, step_data

from PB.recipe_modules.pigweed.build import options as options_pb


@dataclasses.dataclass
class BuildContext:
    _api: recipe_api.RecipeApi
    checkout_root: config_types.Path
    root: config_types.Path
    options: options_pb.Options


_Command = list[str | config_types.Path]


class BuildApi(recipe_api.RecipeApi):
    """Calls to build code."""

    BuildContext = BuildContext

    CAS_DIGEST_PROPERTY_NAME: str = 'cas_build_digest'

    def create(
        self,
        checkout_root: config_types.Path,
        options: options_pb.Options,
        root: config_types.Path | None = None,
    ) -> BuildContext:
        if not root:
            root = checkout_root / 'out'
        return BuildContext(self.m, checkout_root, root, options)

    def __call__(self, ctx: BuildContext) -> None:
        self.install_packages(ctx)
        self.gn_gen(ctx)
        self.ninja(ctx)

    @recipe_api.ignore_warnings('recipe_engine/PYTHON2_DEPRECATED')
    def install_packages(self, ctx: BuildContext) -> None:
        if not ctx.options.packages:
            return

        with self.m.step.nest('install packages'):
            cmd: _Command = ['python', '-m', 'pw_cli', 'package', 'install']
            for package in ctx.options.packages:
                self.m.step(package, cmd + [package])

    def gn_gen(self, ctx: BuildContext) -> None:
        cmd: _Command = ['gn', 'gen']

        for gn_arg in ctx.options.gn_args:
            cmd.append(f'--args={gn_arg}')

        # Infrequently needed but harmless to always add this.
        cmd.append('--export-compile-commands')

        cmd.append(ctx.root)

        with self.m.context(cwd=ctx.checkout_root):
            self.m.step('gn gen', cmd)

    def get_gn_args(
        self,
        ctx: BuildContext,
        test_data: list[dict] | None = None,
    ) -> dict[str, int | str]:
        context_kwargs = {'cwd': ctx.checkout_root} if ctx.checkout_root else {}
        with self.m.context(**context_kwargs):
            cmd: _Command = ['gn', 'args', ctx.root, '--list', '--json']
            args = self.m.step(
                'all gn args',
                cmd,
                stdout=self.m.json.output(),
                step_test_data=lambda: self.m.json.test_api.output_stream(
                    test_data or []
                ),
            ).stdout
            return {x['name']: x for x in args or ()}

    def ninja(self, ctx: BuildContext) -> None:
        cmd: _Command = ['ninja', '-C', ctx.root]
        cmd.extend(ctx.options.ninja_targets)
        with self.m.default_timeout():
            self.m.step('ninja', cmd)

    def archive_to_cas(self, ctx: BuildContext) -> str:
        # TODO: b/234879756 - Only archive necessary files.
        with self.m.step.nest('archive to cas') as pres:
            digest: str = self.m.cas.archive('archive', ctx.root, ctx.root)
            pres.properties[self.CAS_DIGEST_PROPERTY_NAME] = digest
            return digest

    def download_from_cas(
        self, ctx: BuildContext, digest: str
    ) -> step_data.StepData:
        return self.m.cas.download('download from cas', digest, ctx.root)
