# 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)
        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)
        )
