# 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):
    super()._Options(p)
    p.add_option('-q', '--quiet',
                 action='store_true', default=False,
                 help='be quiet')
    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))
    # 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))
