# 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.
"""Recipe for testing Pigweed using developer env setup scripts."""

import re

from PB.recipes.pigweed.envtest import InputProperties

DEPS = [
    'fuchsia/macos_sdk',
    'fuchsia/status_check',
    'pigweed/checkout',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


def RunSteps(api, props):
    api.checkout()

    run = api.path['start_dir'].join('run')
    api.file.ensure_directory('mkdir run', run)

    setup_path = api.checkout.root.join(props.setup_path or 'bootstrap.sh')
    env = {}

    for entry in props.environment_variables:
        k, v = entry.split(u'=', 1)
        env[str(k)] = str(v)

    env_root = api.path['start_dir'].join('environment')
    env['PW_ENVIRONMENT_ROOT'] = env_root
    env['PW_PRESUBMIT_DISABLE_SUBPROCESS_CAPTURE'] = '1'
    env['PW_ENVIRONMENT_NO_ERROR_ON_UNRECOGNIZED'] = '1'

    setup_path_dir = api.path.abs_to_path(api.path.dirname(setup_path))

    if api.platform.is_win and api.path.splitext(setup_path)[1] == '.sh':
        setup_name = api.path.basename(setup_path)
        setup_name = api.path.splitext(setup_name)[0] + '.bat'
        setup_path = setup_path_dir.join(setup_name)

    command = (
        str(props.command)
        or 'pw --directory $PW_ROOT --loglevel debug presubmit '
        '--step gn_clang_build'
    )
    # Replace '$ABC' with '%ABC%' on Windows.
    if api.platform.is_win:
        command = re.sub(r'\$([\w_]+)\b', r'%\1%', command)

    bootstrap_command = '{dot}{env_setup}'.format(
        dot='call ' if api.platform.is_win else '. ',
        # Without the replace here we end up with paths that have no
        # separators. Not sure why, but this fixes it.
        env_setup=api.path.realpath(setup_path).replace('\\', '\\\\'),
    )

    commands = []
    # Call bootstrap multiple times because occasionally there are issues with
    # subsequent calls but not the first.
    for _ in range(props.bootstrap_count or 2):
        commands.append(bootstrap_command)
    commands.append(command)

    sh_source = ''.join(x + '\n' for x in commands)
    base = 'run.bat' if api.platform.is_win else 'run.sh'
    sh_path = setup_path_dir.join(base)
    api.file.write_text('write {}'.format(base), sh_path, sh_source)

    with api.macos_sdk(), api.step.defer_results():
        with api.context(cwd=run, env=env):
            if api.platform.is_win:
                api.step(base, [sh_path])
            else:
                api.step(base, ['sh', '-x', sh_path])

        with api.step.nest('logs') as pres:
            for pattern in [
                '*.bat',
                '*.json',
                '*.log',
                '*.sh',
                '*/*.cfg',
                '*/*.log',
            ]:
                for path in api.file.glob_paths(
                    'glob environment/{}'.format(pattern), env_root, pattern
                ).get_result():
                    log = api.file.read_text(
                        'read {}'.format(api.path.basename(path)), path
                    ).get_result()
                    pres.logs[api.path.relpath(path, env_root)] = log


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('pigweed')
        + properties()
        + api.checkout.ci_test_data()
    )

    yield (
        api.status_check.test('windows')
        + properties()
        + api.platform.name('win')
        + api.checkout.ci_test_data()
    )

    yield (
        api.status_check.test('fail', status='failure')
        + properties()
        + api.checkout.ci_test_data()
        + api.step_data('run.sh', retcode=1)
        + api.step_data(
            'logs.glob environment/*.json', api.file.glob_paths(['foo.json']),
        )
    )

    yield (
        api.status_check.test('environment_variables')
        + properties(environment_variables=['PW_BOOTSTRAP_PY27=1'])
    )
