# Copyright (C) 2008 The Android Open Source Project
#
# 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
#
#      http://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.

import re
import sys

from command import Command
from error import GitError, NoSuchProjectError

CHANGE_RE = re.compile(r"^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$")


class Download(Command):
    COMMON = True
    helpSummary = "Download and checkout a change"
    helpUsage = """
%prog {[project] change[/patchset]}...
"""
    helpDescription = """
The '%prog' command downloads a change from the review system and
makes it available in your project's local working directory.
If no project is specified try to use current directory as a project.
"""

    def _Options(self, p):
        p.add_option("-b", "--branch", help="create a new branch first")
        p.add_option(
            "-c",
            "--cherry-pick",
            dest="cherrypick",
            action="store_true",
            help="cherry-pick instead of checkout",
        )
        p.add_option(
            "-x",
            "--record-origin",
            action="store_true",
            help="pass -x when cherry-picking",
        )
        p.add_option(
            "-r",
            "--revert",
            dest="revert",
            action="store_true",
            help="revert instead of checkout",
        )
        p.add_option(
            "-f",
            "--ff-only",
            dest="ffonly",
            action="store_true",
            help="force fast-forward merge",
        )

    def _ParseChangeIds(self, opt, args):
        if not args:
            self.Usage()

        to_get = []
        project = None

        for a in args:
            m = CHANGE_RE.match(a)
            if m:
                if not project:
                    project = self.GetProjects(".")[0]
                    print("Defaulting to cwd project", project.name)
                chg_id = int(m.group(1))
                if m.group(2):
                    ps_id = int(m.group(2))
                else:
                    ps_id = 1
                    refs = "refs/changes/%2.2d/%d/" % (chg_id % 100, chg_id)
                    output = project._LsRemote(refs + "*")
                    if output:
                        regex = refs + r"(\d+)"
                        rcomp = re.compile(regex, re.I)
                        for line in output.splitlines():
                            match = rcomp.search(line)
                            if match:
                                ps_id = max(int(match.group(1)), ps_id)
                to_get.append((project, chg_id, ps_id))
            else:
                projects = self.GetProjects(
                    [a], all_manifests=not opt.this_manifest_only
                )
                if len(projects) > 1:
                    # If the cwd is one of the projects, assume they want that.
                    try:
                        project = self.GetProjects(".")[0]
                    except NoSuchProjectError:
                        project = None
                    if project not in projects:
                        print(
                            "error: %s matches too many projects; please "
                            "re-run inside the project checkout." % (a,),
                            file=sys.stderr,
                        )
                        for project in projects:
                            print(
                                "  %s/ @ %s"
                                % (
                                    project.RelPath(
                                        local=opt.this_manifest_only
                                    ),
                                    project.revisionExpr,
                                ),
                                file=sys.stderr,
                            )
                        sys.exit(1)
                else:
                    project = projects[0]
                    print("Defaulting to cwd project", project.name)
        return to_get

    def ValidateOptions(self, opt, args):
        if opt.record_origin:
            if not opt.cherrypick:
                self.OptionParser.error(
                    "-x only makes sense with --cherry-pick"
                )

            if opt.ffonly:
                self.OptionParser.error(
                    "-x and --ff are mutually exclusive options"
                )

    def Execute(self, opt, args):
        for project, change_id, ps_id in self._ParseChangeIds(opt, args):
            dl = project.DownloadPatchSet(change_id, ps_id)
            if not dl:
                print(
                    "[%s] change %d/%d not found"
                    % (project.name, change_id, ps_id),
                    file=sys.stderr,
                )
                sys.exit(1)

            if not opt.revert and not dl.commits:
                print(
                    "[%s] change %d/%d has already been merged"
                    % (project.name, change_id, ps_id),
                    file=sys.stderr,
                )
                continue

            if len(dl.commits) > 1:
                print(
                    "[%s] %d/%d depends on %d unmerged changes:"
                    % (project.name, change_id, ps_id, len(dl.commits)),
                    file=sys.stderr,
                )
                for c in dl.commits:
                    print("  %s" % (c), file=sys.stderr)

            if opt.cherrypick:
                mode = "cherry-pick"
            elif opt.revert:
                mode = "revert"
            elif opt.ffonly:
                mode = "fast-forward merge"
            else:
                mode = "checkout"

            # We'll combine the branch+checkout operation, but all the rest need
            # a dedicated branch start.
            if opt.branch and mode != "checkout":
                project.StartBranch(opt.branch)

            try:
                if opt.cherrypick:
                    project._CherryPick(
                        dl.commit,
                        ffonly=opt.ffonly,
                        record_origin=opt.record_origin,
                    )
                elif opt.revert:
                    project._Revert(dl.commit)
                elif opt.ffonly:
                    project._FastForward(dl.commit, ffonly=True)
                else:
                    if opt.branch:
                        project.StartBranch(opt.branch, revision=dl.commit)
                    else:
                        project._Checkout(dl.commit)

            except GitError:
                print(
                    "[%s] Could not complete the %s of %s"
                    % (project.name, mode, dl.commit),
                    file=sys.stderr,
                )
                sys.exit(1)
