# Copyright (C) 2012 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 optparse

from command import PagedCommand
from color import Coloring
from git_refs import R_M, R_HEADS


class _Coloring(Coloring):
    def __init__(self, config):
        Coloring.__init__(self, config, "status")


class Info(PagedCommand):
    COMMON = True
    helpSummary = (
        "Get info on the manifest branch, current branch or unmerged branches"
    )
    helpUsage = "%prog [-dl] [-o [-c]] [<project>...]"

    def _Options(self, p):
        p.add_option(
            "-d",
            "--diff",
            dest="all",
            action="store_true",
            help="show full info and commit diff including remote branches",
        )
        p.add_option(
            "-o",
            "--overview",
            dest="overview",
            action="store_true",
            help="show overview of all local commits",
        )
        p.add_option(
            "-c",
            "--current-branch",
            dest="current_branch",
            action="store_true",
            help="consider only checked out branches",
        )
        p.add_option(
            "--no-current-branch",
            dest="current_branch",
            action="store_false",
            help="consider all local branches",
        )
        # Turn this into a warning & remove this someday.
        p.add_option(
            "-b",
            dest="current_branch",
            action="store_true",
            help=optparse.SUPPRESS_HELP,
        )
        p.add_option(
            "-l",
            "--local-only",
            dest="local",
            action="store_true",
            help="disable all remote operations",
        )

    def Execute(self, opt, args):
        self.out = _Coloring(self.client.globalConfig)
        self.heading = self.out.printer("heading", attr="bold")
        self.headtext = self.out.nofmt_printer("headtext", fg="yellow")
        self.redtext = self.out.printer("redtext", fg="red")
        self.sha = self.out.printer("sha", fg="yellow")
        self.text = self.out.nofmt_printer("text")
        self.dimtext = self.out.printer("dimtext", attr="dim")

        self.opt = opt

        if not opt.this_manifest_only:
            self.manifest = self.manifest.outer_client
        manifestConfig = self.manifest.manifestProject.config
        mergeBranch = manifestConfig.GetBranch("default").merge
        manifestGroups = self.manifest.GetGroupsStr()

        self.heading("Manifest branch: ")
        if self.manifest.default.revisionExpr:
            self.headtext(self.manifest.default.revisionExpr)
        self.out.nl()
        self.heading("Manifest merge branch: ")
        self.headtext(mergeBranch)
        self.out.nl()
        self.heading("Manifest groups: ")
        self.headtext(manifestGroups)
        self.out.nl()

        self.printSeparator()

        if not opt.overview:
            self._printDiffInfo(opt, args)
        else:
            self._printCommitOverview(opt, args)

    def printSeparator(self):
        self.text("----------------------------")
        self.out.nl()

    def _printDiffInfo(self, opt, args):
        # We let exceptions bubble up to main as they'll be well structured.
        projs = self.GetProjects(args, all_manifests=not opt.this_manifest_only)

        for p in projs:
            self.heading("Project: ")
            self.headtext(p.name)
            self.out.nl()

            self.heading("Mount path: ")
            self.headtext(p.worktree)
            self.out.nl()

            self.heading("Current revision: ")
            self.headtext(p.GetRevisionId())
            self.out.nl()

            currentBranch = p.CurrentBranch
            if currentBranch:
                self.heading("Current branch: ")
                self.headtext(currentBranch)
                self.out.nl()

            self.heading("Manifest revision: ")
            self.headtext(p.revisionExpr)
            self.out.nl()

            localBranches = list(p.GetBranches().keys())
            self.heading("Local Branches: ")
            self.redtext(str(len(localBranches)))
            if localBranches:
                self.text(" [")
                self.text(", ".join(localBranches))
                self.text("]")
            self.out.nl()

            if self.opt.all:
                self.findRemoteLocalDiff(p)

            self.printSeparator()

    def findRemoteLocalDiff(self, project):
        # Fetch all the latest commits.
        if not self.opt.local:
            project.Sync_NetworkHalf(quiet=True, current_branch_only=True)

        branch = self.manifest.manifestProject.config.GetBranch("default").merge
        if branch.startswith(R_HEADS):
            branch = branch[len(R_HEADS) :]
        logTarget = R_M + branch

        bareTmp = project.bare_git._bare
        project.bare_git._bare = False
        localCommits = project.bare_git.rev_list(
            "--abbrev=8",
            "--abbrev-commit",
            "--pretty=oneline",
            logTarget + "..",
            "--",
        )

        originCommits = project.bare_git.rev_list(
            "--abbrev=8",
            "--abbrev-commit",
            "--pretty=oneline",
            ".." + logTarget,
            "--",
        )
        project.bare_git._bare = bareTmp

        self.heading("Local Commits: ")
        self.redtext(str(len(localCommits)))
        self.dimtext(" (on current branch)")
        self.out.nl()

        for c in localCommits:
            split = c.split()
            self.sha(split[0] + " ")
            self.text(" ".join(split[1:]))
            self.out.nl()

        self.printSeparator()

        self.heading("Remote Commits: ")
        self.redtext(str(len(originCommits)))
        self.out.nl()

        for c in originCommits:
            split = c.split()
            self.sha(split[0] + " ")
            self.text(" ".join(split[1:]))
            self.out.nl()

    def _printCommitOverview(self, opt, args):
        all_branches = []
        for project in self.GetProjects(
            args, all_manifests=not opt.this_manifest_only
        ):
            br = [project.GetUploadableBranch(x) for x in project.GetBranches()]
            br = [x for x in br if x]
            if self.opt.current_branch:
                br = [x for x in br if x.name == project.CurrentBranch]
            all_branches.extend(br)

        if not all_branches:
            return

        self.out.nl()
        self.heading("Projects Overview")
        project = None

        for branch in all_branches:
            if project != branch.project:
                project = branch.project
                self.out.nl()
                self.headtext(project.RelPath(local=opt.this_manifest_only))
                self.out.nl()

            commits = branch.commits
            date = branch.date
            self.text(
                "%s %-33s (%2d commit%s, %s)"
                % (
                    branch.name == project.CurrentBranch and "*" or " ",
                    branch.name,
                    len(commits),
                    len(commits) != 1 and "s" or "",
                    date,
                )
            )
            self.out.nl()

            for commit in commits:
                split = commit.split()
                self.text("{0:38}{1} ".format("", "-"))
                self.sha(split[0] + " ")
                self.text(" ".join(split[1:]))
                self.out.nl()
