'''This module is meant to provide support for information and help systems based upon RDict.'''
import logger

class Info(logger.Logger):
  '''This basic class provides information independent of RDict'''
  def __init__(self, argDB = None):
    '''Creates a dictionary "sections" whose keys are section names, and values are a tuple of (ordinal, nameList)'''
    logger.Logger.__init__(self, None, argDB)
    self.sections = {}
    return

  def getTitle(self):
    return self._title

  def setTitle(self, title):
    self._title = str(title)
  title = property(getTitle, setTitle, None, 'Title of the Information Menu')

  def getDescription(self, section, name):
    return self._desc[(section, name)]

  def setDescription(self, section, name, desc):
    if not hasattr(self, '_desc'):
      self._desc = {}
    self._desc[(section, name)] = desc
    return

  def addArgument(self, section, name, desc):
    '''Add an argument with given name and string to an information section'''
    if not section in self.sections:
      self.sections[section] = (len(self.sections), [])
    if name in self.sections[section][1]:
      name += '@'+str(len(filter(lambda n: name == n.split('@')[0], self.sections[section][1]))+1)
    self.sections[section][1].append(name)
    self.setDescription(section, name, desc)
    return

  def printBanner(self, f):
    '''Print a banner for the information screen'''
    f.write(self.title+'\n')
    for i in range(max(map(len, self.title.split('\n')))): f.write('-')
    f.write('\n')
    return

  def getTextSizes(self):
    '''Returns the maximum name and description lengths'''
    nameLen = 1
    descLen = 1
    for section in self.sections:
      nameLen = max([nameLen, max(map(lambda n: len(n.split('@')[0]), self.sections[section][1]))+1])
      descLen = max([descLen, max(map(lambda name: len(self.getDescription(section, name)), self.sections[section][1]))+1])
    return (nameLen, descLen)

  def output(self, f = None):
    '''Print a help screen with all the argument information.'''
    if f is  None:
      import sys
      f = sys.stdout
    self.printBanner(f)
    (nameLen, descLen) = self.getTextSizes()
    format = '  %-'+str(nameLen)+'s: %s\n'
    items  = self.sections.items()
    items.sort(lambda a, b: a[1][0].__cmp__(b[1][0]))
    for section, names in items:
      f.write(section+':\n')
      for name in names[1]:
        f.write(format % (name.split('@')[0], self.getDescription(section, name)))
    return

class Help(Info):
  '''Help provides a simple help system for RDict'''
  def __init__(self, argDB):
    '''Creates a dictionary "sections" whose keys are section names, and values are a tuple of (ordinal, nameList). Also provide the RDict upon which this will be based.'''
    Info.__init__(self, argDB)
    self.title = 'Help'
    return

  def getDescription(self, section, name):
    return self.argDB.getType(self.getArgName(name)).help

  def setDescription(self, section, name, desc):
    return

  def getArgName(self, name):
    '''Return the RDict key corresponding to a more verbose help name. Right now, this means discard everything after "=".'''
    #return name.split('=')[0].strip('-')
    argName = name.split('=')[0]
    while argName[0] == '-': argName = argName[1:]
    return argName

  def addArgument(self, section, name, argType, ignoreDuplicates = 0):
    '''Add an argument with given name and type to a help section. The type, which can also have an initializer and help string, will be put into RDict.'''
##  super(Info, self).addArgument(section, name, None)
    if section in self.sections:
      if name in self.sections[section][1]:
        if ignoreDuplicates:
          return
        raise RuntimeError('Duplicate configure option '+name+' in section '+section)
    else:
      self.sections[section] = (len(self.sections), [])
    if not argType.deprecated:
      self.sections[section][1].append(name)

    self.argDB.setType(self.getArgName(name), argType, forceLocal = 1)
    return

  def output(self, f = None, sections = None):
    '''Print a help screen with all the argument information.'''
    if f is  None:
      import sys
      f = sys.stdout
    if sections: sections = [s.lower() for s in sections]
    self.printBanner(f)
    (nameLen, descLen) = self.getTextSizes()
#    format    = '  -%-'+str(nameLen)+'s: %s\n'
#    formatDef = '  -%-'+str(nameLen)+'s: %-'+str(descLen)+'s  current: %s\n'
    format    = '  -%s\n       %s\n'
    formatDef = '  -%s\n       %s  current: %s\n'
    items = self.sections.items()
    items.sort(lambda a, b: a[1][0].__cmp__(b[1][0]))
    for section, names in items:
      if sections and not section.lower() in sections: continue
      f.write(section+':\n')
      for name in names[1]:
        argName = self.getArgName(name)
        type    = self.argDB.getType(argName)
        if argName in self.argDB:
          f.write(formatDef % (name, type.help, str(self.argDB.getType(argName))))
        else:
          f.write(format % (name, type.help))
    return
