"""
This module enables you to use macros for when you go idle at the keyboard
and when you come back and start issuing commands again.  It lets you
set the amount of time before it switches into idle mode.

example:

  #setidle on 600
  #alias STARTIDLE {afk woah!  i've been idle for 10 minutes!}
  #alias ENDIDLE {afk i'm not idle right now.}

Currently implemented:
  - setting the amount of time before idle mode
  - grabbing aliases for STARTIDLE and ENDIDLE
  - checking the current time against the time of the last entered
    user command
  - allows you to set up different idle amounts for each session
    as well as STARTIDLE and ENDIDLE aliases

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 Will Guaraldi
"""

__author__ = "Will Guaraldi <willg@bluesock.org>"
__version__ = "1.3 (15 January, 2004)"
__description__ = "Handles when you're idle."

from lyntin import exported, manager, event
from lyntin.modules import modutils

OFF = -1
NOT_IDLE = 0
IDLE = 1

class IdleData:
  def __init__(self, ses):
    self._amount = 600     # this is in seconds
    self._last_user_command_tick = -1
    self._idle = OFF
    self._ses = ses

  def callCommand(self, eventname):
    am = exported.get_manager("alias")
    if am:
      action = am.getAlias(self._ses, eventname)

    if action:
      event.InputEvent(action, internal=1, ses=self._ses).enqueue()

  def updateIdle(self, tick):
    if self._idle == IDLE:
      self.callCommand("ENDIDLE")
      exported.write_message("UNIDLE!!!")
      self._idle = NOT_IDLE
    self._last_user_command_tick = tick

  def checkIdle(self, tick):
    if self._last_user_command_tick == -1:
      self._last_user_command_tick = tick
      return

    if self._idle == NOT_IDLE and self._last_user_command_tick != -1:
      delta = tick - self._last_user_command_tick

      if self._amount < delta:
        self._idle = IDLE
        self.callCommand("STARTIDLE")
        exported.write_message("IDLE!!!")

      if delta != 0 and delta % 60 == 0:
        exported.write_message("idle for %d minutes." % (delta / 60))


  def setIdleAmount(self, current_tick, amount):
    self._amount = amount
    self._idle = NOT_IDLE
    self._last_user_command_tick = current_tick

  def disableIdle(self):
    self._idle = OFF


class IdleManager(manager.Manager):
  def __init__(self):
    self._idledata = {}
    self._current_tick = -1

  def setIdleAmount(self, ses, amount):
    if not self._idledata.has_key(ses):
      self._idledata[ses] = IdleData(ses)
    self._idledata[ses].setIdleAmount(self._current_tick, amount)

  def disableIdle(self, ses):
    if not self._idledata.has_key(ses):
      self._idledata[ses] = IdleData(ses)
    self._idledata[ses].disableIdle()
    
  def updateIdle(self):
    for mem in self._idledata.keys():
      self._idledata[mem].updateIdle(self._current_tick)

  def checkIdle(self, tick):
    self._current_tick = tick

    for mem in self._idledata.keys():
      self._idledata[mem].checkIdle(tick)


def handle_timer(args):
  im = exported.get_manager("idle")
  im.checkIdle(args["tick"])

def handle_from_user(args):
  im = exported.get_manager("idle")
  im.updateIdle()


commands_dict = {}

def setidle_cmd(ses, args, input):
  """
  This allows you to idle and when you're idling at the keyboard it
  can automatically switch you into an idle mode.  When you come back
  and enter in a command (like hitting the enter key), then it'll switch
  you out of idle mode.

  Switching into the idle mode involves executing the alias for that
  session called STARTIDLE.

  Switching out of idle mode involves executing the alis for that session
  called ENDIDLE.

  arguments:

    onoff - sets the idle checker on and off

    amount - the amount of time that needs to pass before the STARTIDLE
             alias is executed

  category: wbgidler
  """
  onoff = args["onoff"]
  amount = args["amount"]

  im = exported.get_manager("idle")

  if onoff:
    if not amount:
      exported.write_error("setidle: Idler requires an amount when started.")
      return

    im.setIdleAmount(ses, amount)
    exported.write_message("setidle: Idler has been set to %d and started." % amount)
    return

  im.disableIdle(ses)
  exported.write_message("setidle: Idler has been disabled.")

commands_dict["setidle"] = (setidle_cmd, "onoff:boolean amount:int=-1")

im = None

def load():
  """ Initializes the module by binding all the commands."""
  global im
  im = IdleManager()
  exported.add_manager("idle", im)
  modutils.load_commands(commands_dict)
  exported.hook_register("timer_hook", handle_timer)
  exported.hook_register("from_user_hook", handle_from_user)

def unload():
  """ Unload things."""
  global im
  exported.remove_manager("idle")
  modutils.unload_commands(commands_dict)

  exported.hook_unregister("timer_hook", handle_timer)
  exported.hook_unregister("from_user_hook", handle_from_user)