# 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

PYTHON_VERSION_COMPATIBILITY = "PY3"


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)
