# 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 multiprocessing
import sys

from command import Command, DEFAULT_LOCAL_JOBS, WORKER_BATCH_SIZE
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, opt, nb, project):
    """Abandon one project."""
    if opt.all:
      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:])

    def _ProcessResults(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()

    pm = Progress('Abandon %s' % nb, len(all_projects), quiet=opt.quiet)
    # NB: Multiprocessing is heavy, so don't spin it up for one job.
    if len(all_projects) == 1 or opt.jobs == 1:
      _ProcessResults(self._ExecuteOne(opt, nb, x) for x in all_projects)
    else:
      with multiprocessing.Pool(opt.jobs) as pool:
        states = pool.imap_unordered(
            functools.partial(self._ExecuteOne, opt, nb), all_projects,
            chunksize=WORKER_BATCH_SIZE)
        _ProcessResults(states)
    pm.end()

    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" % proj.relpath, 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(p.relpath for p in success[br]))
        print("%s%s| %s\n" % (br, ' ' * (width - len(br)), result))
