# -*- 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 re
import sys
from formatter import AbstractFormatter, DumbWriter

from color import Coloring
from command import PagedCommand, MirrorSafeCommand, GitcAvailableCommand, GitcClientCommand
import gitc_utils

class Help(PagedCommand, MirrorSafeCommand):
  common = False
  helpSummary = "Display detailed help on a command"
  helpUsage = """
%prog [--all|command]
"""
  helpDescription = """
Displays detailed usage information about a command.
"""

  def _PrintCommands(self, commandNames):
    """Helper to display |commandNames| summaries."""
    maxlen = 0
    for name in commandNames:
      maxlen = max(maxlen, len(name))
    fmt = '  %%-%ds  %%s' % maxlen

    for name in commandNames:
      command = self.commands[name]
      try:
        summary = command.helpSummary.strip()
      except AttributeError:
        summary = ''
      print(fmt % (name, summary))

  def _PrintAllCommands(self):
    print('usage: repo COMMAND [ARGS]')
    print('The complete list of recognized repo commands are:')
    commandNames = list(sorted(self.commands))
    self._PrintCommands(commandNames)
    print("See 'repo help <command>' for more information on a "
          'specific command.')

  def _PrintCommonCommands(self):
    print('usage: repo COMMAND [ARGS]')
    print('The most commonly used repo commands are:')

    def gitc_supported(cmd):
      if not isinstance(cmd, GitcAvailableCommand) and not isinstance(cmd, GitcClientCommand):
        return True
      if self.manifest.isGitcClient:
        return True
      if isinstance(cmd, GitcClientCommand):
        return False
      if gitc_utils.get_gitc_manifest_dir():
        return True
      return False

    commandNames = list(sorted([name
                    for name, command in self.commands.items()
                    if command.common and gitc_supported(command)]))
    self._PrintCommands(commandNames)

    print(
"See 'repo help <command>' for more information on a specific command.\n"
"See 'repo help --all' for a complete list of recognized commands.")

  def _PrintCommandHelp(self, cmd, header_prefix=''):
    class _Out(Coloring):
      def __init__(self, gc):
        Coloring.__init__(self, gc, 'help')
        self.heading = self.printer('heading', attr='bold')

        self.wrap = AbstractFormatter(DumbWriter())

      def _PrintSection(self, heading, bodyAttr):
        try:
          body = getattr(cmd, bodyAttr)
        except AttributeError:
          return
        if body == '' or body is None:
          return

        self.nl()

        self.heading('%s%s', header_prefix, heading)
        self.nl()
        self.nl()

        me = 'repo %s' % cmd.NAME
        body = body.strip()
        body = body.replace('%prog', me)

        asciidoc_hdr = re.compile(r'^\n?#+ (.+)$')
        for para in body.split("\n\n"):
          if para.startswith(' '):
            self.write('%s', para)
            self.nl()
            self.nl()
            continue

          m = asciidoc_hdr.match(para)
          if m:
            self.heading('%s%s', header_prefix, m.group(1))
            self.nl()
            self.nl()
            continue

          self.wrap.add_flowing_data(para)
          self.wrap.end_paragraph(1)
        self.wrap.end_paragraph(0)

    out = _Out(self.manifest.globalConfig)
    out._PrintSection('Summary', 'helpSummary')
    cmd.OptionParser.print_help()
    out._PrintSection('Description', 'helpDescription')

  def _PrintAllCommandHelp(self):
    for name in sorted(self.commands):
      cmd = self.commands[name]
      cmd.manifest = self.manifest
      self._PrintCommandHelp(cmd, header_prefix='[%s] ' % (name,))

  def _Options(self, p):
    p.add_option('-a', '--all',
                 dest='show_all', action='store_true',
                 help='show the complete list of commands')
    p.add_option('--help-all',
                 dest='show_all_help', action='store_true',
                 help='show the --help of all commands')

  def Execute(self, opt, args):
    if len(args) == 0:
      if opt.show_all_help:
        self._PrintAllCommandHelp()
      elif opt.show_all:
        self._PrintAllCommands()
      else:
        self._PrintCommonCommands()

    elif len(args) == 1:
      name = args[0]

      try:
        cmd = self.commands[name]
      except KeyError:
        print("repo: '%s' is not a repo command." % name, file=sys.stderr)
        sys.exit(1)

      cmd.manifest = self.manifest
      self._PrintCommandHelp(cmd)

    else:
      self._PrintCommandHelp(self)
