# 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."""

import dataclasses

from PB.recipe_modules.pigweed.build import options as options_pb2
from recipe_engine import config_types, recipe_api, step_data


@dataclasses.dataclass
class BuildContext:
    _api: recipe_api.RecipeApi
    checkout_root: config_types.Path
    root: config_types.Path
    options: options_pb2.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_pb2.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=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)
