# Copyright (C) 2010 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 sys

from color import Coloring
from command import Command
from error import GitError
from git_command import GitCommand
from project import Project
from repo_logging import RepoLogger


logger = RepoLogger(__file__)


class RebaseColoring(Coloring):
    def __init__(self, config):
        Coloring.__init__(self, config, "rebase")
        self.project = self.printer("project", attr="bold")
        self.fail = self.printer("fail", fg="red")


def _ResolveOntoManifest(project: Project) -> str:
    """Resolve project's revisionExpr to a local tracking branch.

    Falls back to the raw revisionExpr if ToLocal fails or raises GitError.
    """
    try:
        return project.GetRemote().ToLocal(project.revisionExpr)
    except GitError:
        return project.revisionExpr


class Rebase(Command):
    COMMON = True
    helpSummary = "Rebase local branches on upstream branch"
    helpUsage = """
%prog {[<project>...] | -i <project>...}
"""
    helpDescription = """
'%prog' uses git rebase to move local changes in the current topic branch to
the HEAD of the upstream history, useful when you have made commits in a topic
branch but need to incorporate new upstream changes "underneath" them.
"""

    def _Options(self, p):
        g = p.get_option_group("--quiet")
        g.add_option(
            "-i",
            "--interactive",
            action="store_true",
            help="interactive rebase (single project only)",
        )

        p.add_option(
            "--fail-fast",
            action="store_true",
            help="stop rebasing after first error is hit",
        )
        p.add_option(
            "-f",
            "--force-rebase",
            action="store_true",
            help="pass --force-rebase to git rebase",
        )
        p.add_option(
            "--no-ff",
            dest="ff",
            default=True,
            action="store_false",
            help="pass --no-ff to git rebase",
        )
        p.add_option(
            "--autosquash",
            action="store_true",
            help="pass --autosquash to git rebase",
        )
        p.add_option(
            "--whitespace",
            action="store",
            metavar="WS",
            help="pass --whitespace to git rebase",
        )
        p.add_option(
            "--auto-stash",
            action="store_true",
            help="stash local modifications before starting",
        )
        p.add_option(
            "-m",
            "--onto-manifest",
            action="store_true",
            help="rebase onto the manifest version instead of upstream "
            "HEAD (this helps to make sure the local tree stays "
            "consistent if you previously synced to a manifest)",
        )

    def Execute(self, opt, args):
        all_projects = self.GetProjects(
            args, all_manifests=not opt.this_manifest_only
        )
        one_project = len(all_projects) == 1

        if opt.interactive and not one_project:
            logger.error(
                "error: interactive rebase not supported with multiple projects"
            )

            if len(args) == 1:
                logger.warning(
                    "note: project %s is mapped to more than one path", args[0]
                )

            return 1

        # Setup the common git rebase args that we use for all projects.
        common_args = ["rebase"]
        if opt.whitespace:
            common_args.append("--whitespace=%s" % opt.whitespace)
        if opt.quiet:
            common_args.append("--quiet")
        if opt.force_rebase:
            common_args.append("--force-rebase")
        if not opt.ff:
            common_args.append("--no-ff")
        if opt.autosquash:
            common_args.append("--autosquash")
        if opt.interactive:
            common_args.append("-i")
        if opt.auto_stash:
            common_args.append("--autostash")

        config = self.manifest.manifestProject.config
        out = RebaseColoring(config)
        out.redirect(sys.stdout)
        _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)

        ret = 0
        for project in all_projects:
            if ret and opt.fail_fast:
                break

            cb = project.CurrentBranch
            if not cb:
                if one_project:
                    logger.error(
                        "error: project %s has a detached HEAD",
                        _RelPath(project),
                    )
                    return 1
                # Ignore branches with detached HEADs.
                continue

            upbranch = project.GetBranch(cb)
            if not upbranch.LocalMerge:
                if one_project:
                    logger.error(
                        "error: project %s does not track any remote branches",
                        _RelPath(project),
                    )
                    return 1
                # Ignore branches without remotes.
                continue

            args = common_args[:]
            if opt.onto_manifest:
                args.append("--onto")
                args.append(_ResolveOntoManifest(project))

            args.append(upbranch.LocalMerge)

            out.project(
                "project %s: rebasing %s -> %s",
                _RelPath(project),
                cb,
                upbranch.LocalMerge,
            )
            out.nl()
            out.flush()

            if GitCommand(project, args).Wait() != 0:
                ret += 1
                continue

        if ret:
            msg_fmt = "%d projects had errors"
            self.git_event_log.ErrorEvent(msg_fmt % (ret), msg_fmt)
            out.fail(msg_fmt, ret)
            out.nl()

        return ret
