# Copyright 2019 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.
"""Test API for checkout."""

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.recipe_modules.pigweed.checkout import properties as checkout_properties
from recipe_engine import post_process, recipe_test_api

REPO = 'https://pigweed.googlesource.com/pigweed/pigweed'
MANIFEST_REPO = 'https://pigweed.googlesource.com/pigweed/manifest'

DEFAULT_MANIFEST = """
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote
    name="default_remote"
    fetch="sso://default"
    />

  <remote
    name="pigweed_remote"
    revision="main"
    fetch=".."
    review="https://pigweed.googlesource.com"
    />

  <remote
    name="pigweed-internal_remote"
    revision="main"
    fetch="https://pigweed-internal.googlesource.com"
    review="https://pigweed-internal.googlesource.com"
    />

  <remote
    name="prefixed"
    fetch="https://foo.googlesource.com/prefix"
    review="https://foo.googlesource.com/prefix"
    />

  <default
    remote="default_remote"
    revision="main"
    />

  <project
    name="default_name"
    path="default_path"
    />

  <project
    name="pigweed_name"
    path="pigweed_path"
    remote="pigweed_remote"
    revision="main"
    />

  <project
    name="pigweed-internal_name"
    path="pigweed-internal_path"
    remote="pigweed-internal_remote"
    />

  <project
    name="pinned"
    path="pinned"
    remote="pigweed_remote"
    revision="0123456789012345678901234567890123456789"
    upstream="main"
    />

  <project
    name="suffix"
    path="prefix/suffix"
    remote="prefixed"
    />
</manifest>
""".strip()


class CheckoutTestApi(recipe_test_api.RecipeTestApi):
    """Test API for checkout."""

    @property
    def manifest_repo(self):
        return MANIFEST_REPO

    def git_properties(self, **kwargs):
        props = checkout_properties.InputProperties()
        props.remote = kwargs.pop('remote', REPO)
        props.branch = kwargs.pop('branch', 'main') or 'main'
        props.use_repo = kwargs.pop('use_repo', False)
        for remotes in kwargs.pop('equivalent_remotes', ()):
            remote_group = checkout_properties.EquivalentRemotes()
            remote_group.remotes.extend(remotes)
            props.equivalent_remotes.extend([remote_group])
        props.force_no_rebase = kwargs.pop('force_no_rebase', False)
        props.match_branch = kwargs.pop('match_branch', True)
        assert not kwargs
        return {'$pigweed/checkout': props}

    def repo_properties(self, remote=MANIFEST_REPO, use_repo=True, **kwargs):
        return self.git_properties(remote=remote, use_repo=use_repo, **kwargs)

    def ci_test_data(
        self, git_repo=REPO, name='pigweed', branch=None, **kwargs
    ):
        if branch:
            kwargs['git_ref'] = 'refs/heads/{}'.format(branch)
        ret = self.m.buildbucket.ci_build(git_repo=git_repo, **kwargs)
        if branch:
            ret += self.override_step_data(
                'checkout {}.change data.process gitiles commit.number'.format(
                    name
                ),
                self.m.json.output([{'_number': '1234', 'branch': branch}]),
            )
        return ret

    def cl(self, host, project, change, patchset=1):
        return common_pb2.GerritChange(
            host=host, project=project, change=change, patchset=patchset
        )

    def try_test_data(self, git_repo=REPO, **kwargs):
        return self.m.buildbucket.try_build(git_repo=git_repo, **kwargs)

    def manifest_test_data(self, name='pigweed', raw_xml=DEFAULT_MANIFEST):
        return self.step_data(
            'checkout {}.read manifest.read file'.format(name),
            self.m.file.read_text(raw_xml),
        )

    def cl_branch(self, branch, index=0, name='pigweed'):
        return self.override_step_data(
            'checkout {}.change data.process gerrit changes.{}.details'.format(
                name, index
            ),
            self.m.json.output({'branch': branch}),
        )

    def manifest_has_matching_branch(self, branch, name='pigweed'):
        # The contents of the returned JSON data don't matter--they just need to
        # evaluate to True when converted to bool. Gitiles returns an empty
        # dictionary when the branch does not exist.
        return self.m.git.get_remote_branch_head(
            'checkout {}.manifest has branch.git ls-remote {}'.format(
                name, branch,
            ),
            'a' * 40,
        )

    def root_files(self, *files, **kwargs):
        name = kwargs.pop('name', 'pigweed')
        assert not kwargs
        files = set(files)
        files.add('.repo')
        return self.step_data(
            'checkout {}.ls'.format(name),
            stdout=self.m.raw_io.output_text(
                ''.join(('{}\n'.format(x) for x in sorted(files)))
            ),
        )

    def submodules(
        self,
        prefix='checkout pigweed.',
        checkout_root='[START_DIR]/checkout',
        raw_submodule_status=None,
        **submodules
    ):
        # kwargs = { path: remote }
        # (e.g., {'foo': 'https://x.googlesource.com/foo'})
        output = raw_submodule_status or ''.join(
            '{} {} ({})\n'.format('a' * 40, path, 'foo') for path in submodules
        )
        res = self.override_step_data(
            '{}git submodule status'.format(prefix),
            stdout=self.m.raw_io.output_text(output),
        )
        for path, remote in submodules.items():
            res += self.step_data(
                '{}parse submodules.git origin {}/{}'.format(
                    prefix, checkout_root, path
                ),
                stdout=self.m.raw_io.output_text(remote),
            )

        return res

    def all_changes_applied(self):
        return self.some_changes_applied() + self.post_process(
            post_process.DoesNotRunRE, '.*some changes were not applied.*'
        )

    def some_changes_applied(self):
        return self.post_process(
            post_process.DoesNotRunRE, '.*no changes were applied.*'
        )

    def no_changes_applied(self):
        return self.post_process(
            post_process.MustRunRE, '.*no changes were applied.*'
        )

    def change_applied(self, name):
        return self.post_process(
            post_process.DoesNotRunRE, '.*failed to apply {}.*'.format(name)
        ) + self.post_process(
            post_process.MustRunRE, r'.*apply {}.git.*'.format(name)
        )

    def change_not_applied(self, name):
        return self.post_process(
            post_process.MustRunRE, '.*failed to apply {}.*'.format(name)
        ) + self.post_process(
            post_process.DoesNotRunRE, r'.*apply {}.git.*'.format(name)
        )
