# Copyright 2018 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.
"""Recipe for generating docs."""

from PB.recipes.fuchsia.docs_roller import InputProperties

DEPS = [
    "fuchsia/auto_roller",
    "fuchsia/build",
    "fuchsia/buildbucket_util",
    "fuchsia/checkout",
    "fuchsia/jiri",
    "recipe_engine/cipd",
    "recipe_engine/context",
    "recipe_engine/json",
    "recipe_engine/path",
    "recipe_engine/properties",
    "recipe_engine/raw_io",
    "recipe_engine/step",
]

PROPERTIES = InputProperties

COMMIT_MESSAGE = """\
[gndoc] Update GN build arguments documentation

"""


def RunSteps(api, props):
    gndoc_path = api.cipd.ensure_tool("fuchsia/tools/gndoc/${platform}", "latest")

    checkout = api.checkout.fuchsia_with_options(
        manifest=props.manifest,
        remote=props.remote,
    )
    docs_dir = checkout.root_dir.join("docs", "gen")

    gn_args_files = []

    # Generate a GN args JSON file for each build target.
    for target_arch, fint_params_path in props.fint_params_paths.items():
        with api.step.nest(target_arch) as presentation:
            gn_results = api.build.gen(
                checkout, fint_params_path, presentation=presentation
            )
            with api.context(cwd=checkout.root_dir):
                gn_args_file = gn_args_json(
                    "gn args --list", api, gn_results, gn_results.build_dir
                )
            # Add targets to final gndoc command
            gn_args_files.append(gn_args_file)

    with api.step.nest("gndoc"), api.context(cwd=checkout.root_dir):
        gndoc(
            api, gndoc_path, gn_args_files, out_file=docs_dir.join("build_arguments.md")
        )

    change = api.auto_roller.attempt_roll(
        api.auto_roller.Options(
            remote="fuchsia.googlesource.com/fuchsia",
        ),
        repo_dir=checkout.root_dir,
        commit_message=COMMIT_MESSAGE,
    )

    return api.auto_roller.raw_result(change)


def gn_args_json(step_name, api, gn_results, build_dir):
    """Return a path to a JSON file containing the GN args."""
    cmd = [gn_results.tool("gn"), "args", build_dir, "--list", "--json"]

    path = api.path.mkstemp("gn-args-json")
    api.step(
        step_name,
        cmd,
        stdout=api.raw_io.output_text(leak_to=path),
        step_test_data=lambda: api.json.test_api.output_stream({}),
    )
    return path


def gndoc(api, gndoc_path, args_files, out_file):
    # Get the project list for linkifying (need all projects).
    jiri_projects = api.jiri.project().json.output

    gndoc_cmd = [
        gndoc_path,
        "-key",
        "target_cpu",
        "-out",
        out_file,
        "-s",
        api.json.input(jiri_projects),
    ]
    for path in args_files:
        gndoc_cmd.extend(["-in", path])

    api.step("gndoc", gndoc_cmd)


def GenTests(api):
    yield (
        api.buildbucket_util.test("basic")
        + api.properties(
            manifest="fuchsia",
            remote="https://fuchsia.googlesource.com/fuchsia",
            fint_params_paths={
                "arm64": "fint_params/docs-roller-arm64.textproto",
                "x64": "fint_params/docs-roller-x64.textproto",
            },
        )
        + api.auto_roller.success()
    )
