"""
I wrote this module to hold a series of commands I find very useful
in debugging things I'm writing, figuring out what's going on, and
general Lyntin development.

The commands detailed within are very useful for folks who are doing 
module development to see what's going on under the hood.  Take your 
time to get to know these commands and they can help you greatly.


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 2003, 2004 Will Guaraldi

"""
__author__ = "Will Guaraldi <willg@bluesock.org>"
__version__ = "1.0 (15 January, 2004)"
__description__ = "Some nice Lyntin hacker commands."

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

commands_dict = {}

def exatel_cmd(ses, args, input):
  """
  Prints out the telnet control conversation for this session.
  This is useful for debugging telnet control code handling.

  category: hacker
  """
  if ses._name == "common":
    exported.write_error("common session!")
    return

  output = list(ses._socket._controllog)
  exported.write_message("%stelnet sequences:%s\n%s" % 
      (ansi.get_color("yellow"), ansi.get_color("default"), "\n".join(output)))
  return

commands_dict["exatel"] = (exatel_cmd, "")

def wprint_cmd(ses, args, input):
  """
  Prints text to a specific window.  If the window doesn't exist, then
  it'll spin off the window.  For example, you could print things to
  a debugging window.

  examples:
    #action {shouts %0} {#wprint {shouts} {%a}}

  category: hacker
  """
  window = args["window"]
  text = args["text"] + "\n"

  ui = str(exported.get_engine().getUI().__class__)
  if ui.find("Tkui") != -1:
    exported.get_engine().getUI().writeWindow(window, text)
  else:    
    exported.write_message(output)

commands_dict["wprint"] = (wprint_cmd, "window text=")


def printmodules_cmd(ses, args, input):
  """
  Prints all the modules that are currently loaded by Lyntin.
  These were either loaded at startup, or loaded via the #import
  command.

  category: hacker
  """
  exported.write_message("Lyntin modules currently loaded:\n")
  exported.write_message(utils.columnize(config.lyntinmodules))

commands_dict["printmodules"] = (printmodules_cmd, "")


def printhooks_cmd(ses, args, input):
  """
  Prints all the functions registered with a given hook.

  examples:
    #printhooks to_user_hook

  category: hacker
  """
  name = args["name"]

  # we have to do this double-check because exported.get_hook will create
  # a hook if it doesn't already exist--and that's bad!
  e = exported.get_engine()
  hlist = e._hooks.keys()

  if not name:
    exported.write_message("hooks available:")
    exported.write_message(utils.columnize(hlist))
    return

  if name not in hlist:
    exported.write_error("no hook by that name. '%s'")
    exported.write_error(utils.columnize(hlist))
    return

  h = exported.get_hook(name)

  output = []
  keys = h._prioritymap.keys()
  keys.sort()
  for mem in keys:
    hooklist = h._prioritymap[mem]
    for mem2 in hooklist:
      output.append("%d: %s" % (mem, mem2))

  exported.write_message(("registered to %s:\n" % name) + string.join(output, "\n"))

commands_dict["printhooks"] = (printhooks_cmd, "name=")


def testansi_cmd(session, args, input):
  """
  Runs through all the highlight styles.

  (Stolen from Josh's stuff.)

  category: hacker
  """
  keys = ansi.STYLEMAP.keys()
  keys.sort()

  for color in keys:
    val = ansi.STYLEMAP[color]
    exported.write_message(chr(27) + "[" + val + "m" + "test" + chr(27) + "[0m" + " - " + color)
  return

commands_dict["testansi"] = (testansi_cmd,"")


def log_everything_cmd(ses, args, input):
  """
  Logs everything being said so you can see what's going on.  This
  is different than using the logger--this logs _everything_ we
  get from the mud except for telnet control codes and prints it
  to the screen.

  category: hacker
  """
  onoff = args["onoff"]
  if onoff:
    exported.hook_register("mud_filter_hook", log_everything_filter, 0)
    exported.write_message("logging everything: on")
  else:
    exported.hook_unregister("mud_filter_hook", log_everything_filter)
    exported.write_message("logging everything: off")

commands_dict["logall"] = (log_everything_cmd, "onoff:boolean")


def log_hook_cmd(ses, args, input):
  """
  Turns on and off logging of a particular hook.  Anything spammed
  to that hook will go through the hook_debug function which will
  spam it to your screen.

  It won't let you debug the "to_user_hook" because it writes its
  output via the to_user_hook and that'd cause a loop of infinite
  badness.

  category: hacker
  """
  hook = args["hook"]
  onoff = args["onoff"]

  if hook == "to_user_hook":
    exported.write_error("This is really _not_ a good idea to do.")
    return

  hm = exported.get_manager("hook")
  hlist = hm.getHookList()

  if hook not in hlist:
    exported.write_error("Hook %s does not exist." % hook)
    return

  h = exported.get_hook(hook)
  if onoff:
    h.register(hook_debug)
    exported.write_message("Registered with %s." % hook)
  else:
    h.unregister(hook_debug)
    exported.write_message("Unregistered with %s." % hook)

commands_dict["loghook"] = (log_hook_cmd, "hook onoff:boolean")

def log_everything_filter(args):
  # newtext = ansi.fix_color(text)
  
  text = args["data"]
  codes = ( (chr(27), "ESC"),
            (chr(10), "CR"),
            (chr(8), "BS"),
            (chr(13), "LF") )
  d = text
  for a, b in codes:
    d = d.replace(a, b)
            
  print "===%s===" % d
  return text
  
def hook_debug(args):
  """ For debugging hooks."""
  exported.write_message("SPAMHOOK: %s" % repr(args))

def load():
  """ Initializes the module by binding all the commands."""
  modutils.load_commands(commands_dict)

def unload():
  """ Unload things."""
  modutils.unload_commands(commands_dict)