'''
Base sequence step class and some derivatives.

@author: Eitan Isaacson
@copyright: Copyright (c) 2007 Eitan Isaacson
@license: GPL

This file may be distributed and/or modified under the terms of the GNU General
Public License version 2 as published by the Free Software Foundation. This file
is distributed without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.

See "COPYING" in the source distribution for more information.

Headers in this file shall remain intact.
'''

from gi.repository import GObject
import pyatspi
import sys

class SequenceStep(GObject.GObject):
  '''
  Base class for all sequence steps in a Macaroon sequence. Emits a "done"
  signal when the step is done.

  @cvar delta_time: Time, in milliseconds, before this step should be executed.
  @type delta_time: integer

  @ivar done: True if step is done.
  @type done: boolean
  '''
  __gsignals__ = {'done' : (GObject.SignalFlags.RUN_FIRST,
                                 None, ())}
  delta_time = 0
  def __init__(self):
    '''
    Initialize L{SequenceStep}.
    '''
    super(SequenceStep, self).__init__()
    self.done = False

  def stepDone(self):
    '''
    Puts instance in "done" state. And emits "done" signal.

    @return: Return False because this is usually called through a
    gobject timeout.
    @rtype: boolean
    '''
    if not self.done:
      self.done = True
      self.emit('done')
    return False

class AtomicAction(SequenceStep):
  '''
  A L{SequenceStep} that performs a certain action.

  @ivar _func: Function to call.
  @type _func: callable
  @ivar _args: Arguments to give the function.
  @type _args: list
  @ivar _kwargs: Key word arguments for function.
  @type _kwargs: dictionary
  '''
  def __init__(self, delta_time, func, *args, **kwargs):
    '''
    Initialize L{AtomicAction}.

    @param delta_time: Time, in milliseconds, before this step should be
    executed.
    @type delta_time: integer
    @param func: Function to call.
    @type func: callable
    @param _args: Arguments to give the function.
    @type _args: list
    @param _kwargs: Key word arguments for function.
    @type _kwargs: dictionary
    '''
    SequenceStep.__init__(self)
    self.delta_time = delta_time
    self._func = func
    self._args = args
    self._kwargs = kwargs

  def __call__(self):
    '''
    Perform the given function.
    '''
    self._func(*self._args, **self._kwargs)
    self.stepDone()

class DebugAction(AtomicAction):
  '''
  An action that prints a debug message to standard output.
  '''
  def __init__(self, debug_msg, delta_time=0):
    '''
    Initialize L{DebugAction}

    @param debug_msg: Message to print out to standard output.
    @type debug_msg: string
    @param delta_time: Time to wait before printing the message.
    @type delta_time: integer
    '''
    self._debug_msg = debug_msg
    AtomicAction.__init__(self, 0, self._printDebugMsg)

  def _printDebugMsg(self):
    '''
    Print the debug message.
    '''
    print(self._debug_msg)

  def __str__(self):
    '''
    String representation of instance.

    @return: String representation of instance.
    @rtype: string
    '''
    return 'Debug message: %s' % self._debug_msg

class PauseAction(AtomicAction):
  '''
  A simple pause for a given amount of time.
  '''
  def __init__(self, delta_time):
    '''
    Initialize a L{PauseAction}.

    @param delta_time: Duration of pause in milliseconds.
    @type delta_time: integer
    '''
    AtomicAction.__init__(self, delta_time, lambda args, kwargs: None, [], {})

  def __str__(self):
    '''
    String representation of instance.

    @return: String representation of instance.
    @rtype: string
    '''
    return 'Pause for %d milliseconds' % self.delta_time


class CallableAction(AtomicAction):
  '''
  A simplified L{AtomicAction} that makes it easy for simply calling a function.
  '''
  def __init__(self, func, *args, **kwargs):
    '''
    Initialize L{AtomicAction}.

    @param delta_time: Time, in milliseconds, before this step should be
    executed.
    @type delta_time: integer
    @param func: Function to call.
    @type func: callable
    @param _args: Arguments to give the function.
    @type _args: list
    @param _kwargs: Key word arguments for function.
    @type _kwargs: dictionary
    '''
    AtomicAction.__init__(self, 0, func, *args, **kwargs)
