# 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 attr
from recipe_engine import recipe_api


@attr.s
class Context:
    _api = attr.ib()
    checkout_root = attr.ib()
    root = attr.ib()
    options = attr.ib()


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

    CAS_DIGEST_PROPERTY_NAME = 'cas_build_digest'

    def create(self, checkout_root, options, root=None):
        if not root:
            root = checkout_root / 'out'
        return Context(self.m, checkout_root, root, options)

    def __call__(self, ctx):
        self.install_packages(ctx)
        self.gn_gen(ctx)
        self.ninja(ctx)

    def install_packages(self, ctx):
        if not ctx.options.packages:
            return

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

    def gn_gen(self, ctx):
        cmd = ['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, test_data=None):
        context_kwargs = {'cwd': ctx.checkout_root} if ctx.checkout_root else {}
        with self.m.context(**context_kwargs):
            cmd = ['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):
        cmd = ['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):
        # TODO(b/234879756) Only archive necessary files.
        with self.m.step.nest('archive to cas') as pres:
            digest = 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, digest):
        return self.m.cas.download('download from cas', digest, ctx.root)
