# 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 crossrefs using Kythe and upload to GCS."""

import urllib

from PB.recipes.pigweed.xrefs import InputProperties

DEPS = [
    'fuchsia/buildbucket_util',
    'fuchsia/kythe',
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/swarming',
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    if api.buildbucket_util.is_tryjob:
        gcs_bucket = props.gcs_bucket or 'pigweed-kythe-try'
        dry_run = True
    else:
        gcs_bucket = props.gcs_bucket or 'pigweed-kythe'
        dry_run = props.dry_run

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

    # It's complicated to set up the environment sufficiently enough for
    # PW_KYTHE_CIPD_INSTALL_DIR to be set. When running recipe unit tests,
    # just use a stand-in path when it isn't set.
    try:
        api.kythe.kythe_dir = api.path.abs_to_path(
            env.PW_KYTHE_CIPD_INSTALL_DIR
        )
    except AttributeError:
        api.kythe.kythe_dir = api.path['start_dir'].join('kythe')

    api.kythe.kythe_libs_dir = api.kythe.kythe_dir

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

    assert checkout.options.branch in ('master', 'main')
    url = urllib.parse.urlparse(checkout.options.remote)
    corpus = url.netloc + url.path
    if corpus.endswith('.git'):
        corpus = corpus[0:-4]  # pragma: no cover

    name = corpus.replace('.googlesource.com', '')
    name = name.replace('.', '-').replace('/', '-')

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

    api.kythe.extract_and_upload(
        checkout_dir=checkout.root,
        build_dir=api.build.dir,
        corpus=corpus,
        gcs_bucket=gcs_bucket,
        gcs_filename=final_kzip_name,
        langs=('cxx'),
    )


def GenTests(api):
    def properties(**kwargs):
        new_kwargs = api.checkout.git_properties()
        new_kwargs.update(kwargs)
        return api.properties(**new_kwargs)

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

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

    yield (
        api.status_check.test('tryjob')
        + properties(dry_run=False)
        + api.checkout.try_test_data()
        + api.kythe.valid()
    )
