# Copyright 2020 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.
"""Generate docs using GN/Ninja and upload to GCS."""

from PB.go.chromium.org.luci.buildbucket.proto import common
from PB.recipes.pigweed.docs_builder import InputProperties
from PB.recipe_engine import result

DEPS = [
    'fuchsia/gerrit',
    'fuchsia/gsutil',
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'recipe_engine/file',
    'recipe_engine/json',
    'recipe_engine/properties',
    'recipe_engine/swarming',
]

PROPERTIES = InputProperties


def RunSteps(api, props):  # pylint: disable=invalid-name
    bucket = props.bucket or 'pigweed-docs'
    base_url = props.base_url or 'https://pigweed.dev/'

    checkout = api.checkout(props.checkout_options)
    env = api.environment.init(checkout.root, props.environment_options)

    with env():
        api.build(checkout.root, props.build_options)

    html = api.build.dir.join('docs', 'gen', 'docs', 'html')

    if props.dry_run:
        path = 'testing/swarming-{}/{}'.format(
            api.swarming.task_id, checkout.revision()
        )
    else:
        path = checkout.revision()

    api.gsutil.upload(
        bucket=bucket, src=html, dst=path, recursive=True, multithreaded=True,
    )

    # Getting gerrit details even if this is a dry run so testing will show if
    # it would have worked.
    change = api.gerrit.change_details(
        'get change details',
        change_id=str(checkout.revision()),
        host=checkout.gerrit_host(),
        max_attempts=5,
        timeout=30,
        test_data=api.json.test_api.output({'branch': 'main'}),
    ).json.output

    if change['branch'] in ('master', 'main') and not props.dry_run:
        head = api.build.dir.join('HEAD')
        api.file.write_text('write HEAD', head, checkout.revision())
        api.gsutil.upload(bucket=bucket, src=head, dst='HEAD')

        api.gsutil.rsync(
            bucket=bucket,
            src=html,
            dst='latest',
            recursive=True,
            multithreaded=True,
        )

    link = '{}/?rev={}'.format(base_url.rstrip("/"), path)

    return result.RawResult(
        summary_markdown='Docs available at {}.'.format(link),
        status=common.SUCCESS,
    )


def GenTests(api):  # pylint: disable=invalid-name
    def properties(**kwargs):
        new_kwargs = api.checkout.git_properties()
        new_kwargs.update(kwargs)
        return api.properties(**new_kwargs)

    yield api.status_check.test('docs_dry_run') + properties(dry_run=True)

    yield api.status_check.test('docs') + properties(dry_run=False)
