"""
Most muds have chatlines which when something is said over the chatline,
it comes in the form of:

<name> <verb>: ...................................................
           .......................................................

Where <name> is a specific person doing the saying/telling/shouting/whatever 
and <verb> is the chatline verb involved like "shouts" or "tells you" or
something along those lines.

This allows you to "power-gag" those sorts of lines.  So that you never
see the text again.  It handles chats where the line is wrapped and the
second and future lines are indented with whitespace characters.

example:

  #powergag shouts
  #antipowergag Sven

Currently implemented:
 - power-gagging as defined above.
 - powergag history--so you could check to see what's been powergagged
   in case you accidentally missed something important
 - powergags now persist
 - antipowergags--like if you wanted to gag everyone shouting on the
   shout line except for specific people


Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Copyright 2002, 2003, 2004 Will Guaraldi
"""

__author__ = "Will Guaraldi <willg@bluesock.org>"
__version__ = "1.5 (15 January, 2004)"
__description__ = "Handles gagging of conversation items that span multiple lines."

import string
from lyntin import config, ansi, manager, utils, exported
from lyntin.modules import modutils

class PowergagData:
  def __init__(self):
    self._gags = []
    self._gagging = 0
    self._antigags = []
    self._history = []

  def addAntiPowergag(self, item):
    """ Adds an anti powergag to the list."""
    if item not in self._antigags:
      self._antigags.append(item)

  def addPowergag(self, item):
    """ Adds a powergag to the list."""
    if item not in self._gags:
      self._gags.append(item)

  def clear(self):
    """ Removes all the powergags."""
    self._gags = []

  def removeAntiPowergags(self, text):
    """
    Removes antipowergags from the list.

    @returns: a list of antipowergags that were removed.
    @rtype: list of strings
    """
    badgags = utils.expand_text(text, self._antigags)

    ret = []
    for mem in badgags:
      ret.append(mem)
      self._antigags.remove(mem)

    return ret

  def removePowergags(self, text):
    """
    Removes gags from the list.

    @returns: a list of gags that were removed.
    @rtype: list of strings
    """
    badgags = utils.expand_text(text, self._gags)

    ret = []
    for mem in badgags:
      ret.append(mem)
      self._gags.remove(mem)

    return ret

  def getPowergags(self):
    """ Returns the list of powergags."""
    list = self._gags
    list.sort()
    return list

  def getPowergagHistory(self):
    """ Returns the list of gagged stuff."""
    return self._history

  def expand(self, text):
    """ Looks at mud data and performs any powergags.

    It returns the final text--even if there were no powergags.
    """
    if len(text) > 0:
      newtext = ansi.filter_ansi(text)

      if self._gagging == 1:
        if len(newtext) > 1 and (newtext[0:2] == "  " or newtext[0] == '\t'):
          tokens = ansi.split_ansi_from_text(text)
          colors = []
          text = []
          for mem in tokens:
            if ansi.is_color_token(mem):
              colors.append(mem)
            else:
              text.append(mem)
          colors = string.join(colors, "")
          self._history.append(string.join(text, ""))
          return colors
        else:
          self._gagging = 0


      # check for antigags first
      for mem in self._antigags:
        if newtext.find(mem) != -1:
          return text

      # check for gags
      for mem in self._gags:
        if newtext.find(mem) != -1:
          tokens = ansi.split_ansi_from_text(text)
          colors = []
          text = []

          for mem in tokens:
            if ansi.is_color_token(mem):
              colors.append(mem)
            else:
              text.append(mem)

          colors = string.join(colors, "")
          self._gagging = 1
          self._history.append(string.join(text, ""))
          return colors

    return text


  def getAntiInfo(self, text=''):
    """
    Returns antipowergag information.
    """
    listing = list(self._antigags)
    if text:
      listing = utils.expand_text(text, listing)

    listing = ["antipowergag {%s}" % m for m in listing]

    return listing

  def getInfo(self, text=''):
    """
    Returns information about the powergags in here.

    This is used by #powergag to tell all the powergags involved
    as well as #write which takes this information and dumps
    it to the file.
    """
    listing = list(self._gags)
    if text:
      listing = utils.expand_text(text, listing)

    listing = ["powergag {%s}" % m for m in listing]

    return listing

  def getStatus(self):
    """ Returns the number of powergags we're managing."""
    return ("%d powergags(s). %s antipowergag(s)." 
            % (len(self._gags), len(self._antigags)))

class PowergagManager(manager.Manager):
  def __init__(self):
    self._gags = {}

  def addAntiPowergag(self, ses, item):
    if not self._gags.has_key(ses):
      self._gags[ses] = PowergagData()
    self._gags[ses].addAntiPowergag(item)

  def addPowergag(self, ses, item):
    if not self._gags.has_key(ses):
      self._gags[ses] = PowergagData()
    self._gags[ses].addPowergag(item)

  def clear(self, ses):
    if self._gags.has_key(ses):
      self._gags[ses].clear()

  def removeAntiPowergags(self, ses, text):
    if self._gags.has_key(ses):
      return self._gags[ses].removeAntiPowergags(text)
    return []

  def removePowergags(self, ses, text):
    if self._gags.has_key(ses):
      return self._gags[ses].removePowergags(text)
    return []

  def getPowergagHistory(self, ses):
    if self._gags.has_key(ses):
      return self._gags[ses].getPowergagHistory()
    return []

  def getPowergag(self, ses):
    if self._gags.has_key(ses):
      return self._gags[ses].getPowergags()
    return []

  def getInfo(self, ses, text=''):
    if self._gags.has_key(ses):
      return self._gags[ses].getInfo(text)
    return []

  def getAntiInfo(self, ses, text=''):
    if self._gags.has_key(ses):
      return self._gags[ses].getAntiInfo(text)
    return []

  def getStatus(self, ses):
    if self._gags.has_key(ses):
      return self._gags[ses].getStatus()
    return "0 powergags(s).  0 antipowergag(s)."

  def expand(self, ses, text):
    if self._gags.has_key(ses):
      return self._gags[ses].expand(text)
    return text

  def persist(self, args):
    """
    write_hook function for persisting the state of our session.
    """
    ses = args["session"]
    quiet = args["quiet"]

    # persist powergags
    data = self.getInfo(ses) + self.getAntiInfo(ses)
    if quiet == 1:
      data = [m + " quiet={true}" for m in data]

    return data

  def mudfilter(self, args):
    """
    mud_filter_hook function to perform powergags on data 
    that comes from the mud.
    """
    ses = args["session"]
    text = args["dataadj"]

    if exported.get_config("ignoresubs", ses, 0) == 0:
      text = self.expand(ses, text)
    return text


commands_dict = {}

def powergag_cmd(ses, args, input):
  """
  With no arguments, prints all powergags.
  Otherwise creates a powergag.

  Braces are advised around 'gag'.

  category: wbgpowergag
  """
  item = args["gag"]
  quiet = args["quiet"]

  pgm = exported.get_manager("powergag")

  if not item:
    data = pgm.getInfo(ses)
    if not data:
      data = ["powergag: no powergags defined."]

    exported.write_message("powergags:\n" + "\n".join(data))
    return

  pgm.addPowergag(ses, item)
  if not quiet:
    exported.write_message("powergag: {%s} added." % (item))

commands_dict["powergag"] = (powergag_cmd, "gag= quiet:boolean=false")


def antipowergag_cmd(ses, args, input):
  """
  Allows you to specify words that indicate that something shouldn't
  be gagged.

  examples:
    #antipowergag {Joe}

  category: wbgpowergag
  """
  item = args["word"]
  quiet = args["quiet"]

  pgm = exported.get_manager("powergag")
  
  if not item:
    data = pgm.getAntiInfo(ses)
    if not data:
      data = ["antipowergag: no antipowergags defined."]

    exported.write_message("antipowergags:\n" + "\n".join(data))
    return

  pgm.addAntiPowergag(ses, item)
  if not quiet:
    exported.write_message("powergag: {%s} added to antipowergag list." % (item))

commands_dict["antipowergag"] = (antipowergag_cmd, "word= quiet:boolean=false")

def powergaghist_cmd(ses, args, input):
  """
  Retrieves history for this powergag session.  All the things that
  have been gagged are in the history.

  category: wbgpowergag
  """
  count = args["count"]
  count = 0 - count

  pgm = exported.get_manager("powergag")
  hist = pgm.getPowergagHistory(ses)
  
  histlist = string.join(hist[count:], "")
  exported.write_message("Powergagged:\n" + histlist)

commands_dict["powergaghist"] = (powergaghist_cmd, "count:int=30")


def unpowergag_cmd(ses, args, input):
  """
  Allows you to remove powergags.

  category: wbgpowergag
  """
  func = exported.get_manager("powergag").removePowergags
  modutils.unsomething_helper(args, func, ses, "powergag", "powergags")

commands_dict["unpowergag"] = (unpowergag_cmd, "str= quiet:boolean=false")


def unantipowergag_cmd(ses, args, input):
  """
  Allows you to remove antipowergags.

  category: wbgpowergag
  """
  func = exported.get_manager("powergag").removeAntiPowergags
  modutils.unsomething_helper(args, func, ses, "antipowergag", "antipowergags")

commands_dict["unantipowergag"] = (unantipowergag_cmd, "str= quiet:boolean=false")


pgm = None

def load():
  """ Initializes the module by binding all the commands."""
  global pgm
  modutils.load_commands(commands_dict)
  pgm = PowergagManager()
  exported.add_manager("powergag", pgm)

  exported.hook_register("mud_filter_hook", pgm.mudfilter, 49)
  exported.hook_register("write_hook", pgm.persist)

def unload():
  """ Unloads the module by calling any unload/unbind functions."""
  global pgm
  modutils.unload_commands(commands_dict.keys())
  exported.remove_manager("powergag")

  exported.hook_unregister("mud_filter_hook", pgm.mudfilter)
  exported.hook_unregister("write_hook", pgm.persist)