# -*- coding:utf-8 -*-
#
# 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 __future__ import print_function
import sys
from command import Command
from collections import defaultdict
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>".
"""

  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 Execute(self, opt, args):
    nb = args[0]
    err = defaultdict(list)
    success = defaultdict(list)
    all_projects = self.GetProjects(args[1:])

    pm = Progress('Abandon %s' % nb, len(all_projects))
    for project in all_projects:
      pm.update()

      if opt.all:
        branches = list(project.GetBranches().keys())
      else:
        branches = [nb]

      for name in branches:
        status = project.AbandonBranch(name)
        if status is not None:
          if status:
            success[name].append(project)
          else:
            err[name].append(project)
    pm.end()

    width = 25
    for name in branches:
      if width < len(name):
        width = len(name)

    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:
      print('Abandoned branches:', file=sys.stderr)
      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), file=sys.stderr)
