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

from collections import defaultdict
import functools
import itertools
import sys

from command import Command, DEFAULT_LOCAL_JOBS
from git_command import git
from progress import Progress


class Abandon(Command):
  COMMON = True
  helpSummary = "Permanently abandon a development branch"
  helpUsage = """
%prog [--all | <branchname>] [<project>...]

This subcommand permanently abandons a development branch by
deleting it (and all its history) from your local repository.

It is equivalent to "git branch -D <branchname>".
"""
  PARALLEL_JOBS = DEFAULT_LOCAL_JOBS

  def _Options(self, p):
    p.add_option('--all',
                 dest='all', action='store_true',
                 help='delete all branches in all projects')

  def ValidateOptions(self, opt, args):
    if not opt.all and not args:
      self.Usage()

    if not opt.all:
      nb = args[0]
      if not git.check_ref_format('heads/%s' % nb):
        self.OptionParser.error("'%s' is not a valid branch name" % nb)
    else:
      args.insert(0, "'All local branches'")

  def _ExecuteOne(self, all_branches, nb, project):
    """Abandon one project."""
    if all_branches:
      branches = project.GetBranches()
    else:
      branches = [nb]

    ret = {}
    for name in branches:
      status = project.AbandonBranch(name)
      if status is not None:
        ret[name] = status
    return (ret, project)

  def Execute(self, opt, args):
    nb = args[0]
    err = defaultdict(list)
    success = defaultdict(list)
    all_projects = self.GetProjects(args[1:], all_manifests=not opt.this_manifest_only)
    _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)

    def _ProcessResults(_pool, pm, states):
      for (results, project) in states:
        for branch, status in results.items():
          if status:
            success[branch].append(project)
          else:
            err[branch].append(project)
        pm.update()

    self.ExecuteInParallel(
        opt.jobs,
        functools.partial(self._ExecuteOne, opt.all, nb),
        all_projects,
        callback=_ProcessResults,
        output=Progress('Abandon %s' % (nb,), len(all_projects), quiet=opt.quiet))

    width = max(itertools.chain(
        [25], (len(x) for x in itertools.chain(success, err))))
    if err:
      for br in err.keys():
        err_msg = "error: cannot abandon %s" % br
        print(err_msg, file=sys.stderr)
        for proj in err[br]:
          print(' ' * len(err_msg) + " | %s" % _RelPath(proj), file=sys.stderr)
      sys.exit(1)
    elif not success:
      print('error: no project has local branch(es) : %s' % nb,
            file=sys.stderr)
      sys.exit(1)
    else:
      # Everything below here is displaying status.
      if opt.quiet:
        return
      print('Abandoned branches:')
      for br in success.keys():
        if len(all_projects) > 1 and len(all_projects) == len(success[br]):
          result = "all project"
        else:
          result = "%s" % (
              ('\n' + ' ' * width + '| ').join(_RelPath(p) for p in success[br]))
        print("%s%s| %s\n" % (br, ' ' * (width - len(br)), result))
