'''
<insert purpose of Perk here>

@author: <author's name>
@organization: <author's organization (or None)>
@copyright: Copyright (c) <year and copyright holder>
@license: <license name>

All rights reserved. This program and the accompanying materials are made 
available under the terms of the <license name> which is available at
U{<license URL>}
'''
# import useful modules for Perks
import Perk, Task.Tools
from POR import POR
from i18n import bind, _

# metadata describing this Perk
__uie__ = dict(kind='perk', tier=None, all_tiers=True)

# to support translation of strings in this Perk, uncomment the following line
# and provide the proper domain and path to your translation file
# _ = bind(domain, locale_dir)

class BasicBraillePerk(Perk.Perk):
  
  def init(self):
    # set the output device                       
    self.setPerkIdealOutput('braille')
    
    # register braille events handlers
    self.registerTask(HandleSelectorChange('default selector'))
    self.registerTask(HandleCaretChange('default caret'))
    self.registerTask(HandleFocusChange('default focus'))
    
    # register braille named tasks for input events
    self.registerTask(ScrollForward('scroll forward'))
    self.registerTask(ScrollBackward('scroll backward'))
    self.registerTask(ScrollUp('scroll up'))
    self.registerTask(ScrollDown('scroll down'))
    
    # register keyboard command listeners
    kbd = self.getInputDevice('Keyboard')
    self.addInputModifiers(kbd, kbd.AEK_CAPS_LOCK)
    self.registerCommand(kbd, 'scroll forward', True, 
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_RIGHT])
    self.registerCommand(kbd, 'scroll backward', True, 
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_LEFT])
    self.registerCommand(kbd, 'scroll up', True, 
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_UP])
    self.registerCommand(kbd, 'scroll down', True, 
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_DOWN])
                      
  def getDescription(self):
    return _('Applies to all applications by default.')

class ScrollForward(Task.InputTask):
  '''
  Scrolls Braille display to right
  '''
  def execute(self, **kwargs):
    print "BasicBraillePerk handling ScrollForward"
    
class ScrollBackward(Task.InputTask):
  '''
  Scrolls Braille display to left
  '''
  def execute(self, **kwargs):
    print "BasicBraillePerk handling ScrollBackward"
    
class ScrollUp(Task.InputTask):
  '''
  Scrolls Braille display up
  '''
  def execute(self, **kwargs):
    print "BasicBraillePerk handling ScrollUp"
    
class ScrollDown(Task.InputTask):
  '''
  Scrolls Braille display down
  '''
  def execute(self, **kwargs):
    print "BasicBraillePerk handling ScrollDown"
    
class HandleFocusChange(Task.FocusTask):
  '''  
  Task that handles a L{AEEvent.FocusChange}.
  '''  
  def executeGained(self, por, **kwargs):
    '''
    Annouces the label and role of the newly focused widget. The role is output
    only if it is different from the last one announced.
    
    @param por: Point of regard for the new focus
    @type por: L{POR}
    '''
    self.sayItem(text=self.getItemText()) 
    return True

class HandleSelectorChange(Task.SelectorTask):
  ''' 
  Task that handles a L{AEEvent.SelectorChange}.
  '''
  def executeActive(self, por, text, **kwargs):
    '''
    Announces the text of the active item.
    
    @param por: Point of regard where the selection event occurred
    @type por: L{POR}
    @param text: The text of the active item
    @type text: string
    '''
    outtext = self.getItemText()
    if len(outtext) == 0:
      outtext = self.getAccLabel()
    self.sayItem(text=outtext)
      
  def executeText(self, por, text, **kwargs):
    '''
    Announces the localized word selected or unselected followed by the total 
    number of characters in the selection.
    
    @param por: Point of regard where the selection event occurred
    @type por: L{POR}
    @param text: The currently selected text
    @type text: string
    '''
    pass  
    
class HandleCaretChange(Task.CaretTask):
  '''  
  Task that handles a L{AEEvent.CaretChange}. The L{execute} method performs
  actions that should be done regardless of whether text was inserted or
  deleted or the caret moved. The other three methods handle these more
  specific cases.
  
  @ivar changed: Tracks whether the last caret move event was a caused by a
    change (insert/delete) or just navigation
  @type changed: boolean
  '''
  def init(self):
    pass
  
  def execute(self, por, text, text_offset, added, **kwargs):
    '''
    Stores the point of regard to the caret event location. Tries to stop
    current output.
    
    @param por: Point of regard where the caret event occurred
    @type por: L{POR}
    @param text: The text inserted, deleted or the line of the caret
    @type text: string
    @param text_offset: The offset of the inserted/deleted text or the line 
      offset when movement only
    @type text_offset: integer
    @param added: True when text added, False when text deleted, and None 
      (the default) when event is for caret movement only
    @type added: boolean
    '''
    # let the base class call the appropriate method for inset, move, delete
    rv = Task.CaretTask.execute(self, por, text, text_offset, added, **kwargs)
    return rv
    
  def executeInserted(self, por, text, text_offset, **kwargs):
    '''
    Announces the inserted text.
    
    @param por: Point of regard where the caret event occurred
    @type por: L{POR}
    @param text: The text inserted
    @type text: string
    @param text_offset: The offset of the inserted text
    @type text_offset: integer
    '''
    self.sayItem(text=self.getItemText()) 
    
  def executeMoved(self, por, text, text_offset, **kwargs):
    '''
    Announces the text passed in the caret movement.
    
    @param por: Point of regard where the caret event occurred
    @type por: L{POR}
    @param text: The text passed during the move
    @type text: string
    @param text_offset: The offset of the new caret position
    @type text_offset: integer
    '''
    pass
    
  def executeDeleted(self, por, text, text_offset, **kwargs):
    '''
    Announces the deleted text. Prepends delete and backspace text to indicate
    which way the caret moved.
    
    @param por: Point of regard where the caret event occurred
    @type por: L{POR}
    @param text: The text delete
    @type text: string
    @param text_offset: The offset of the delete text
    @type text_offset: integer
    '''
    self.sayItem(text=self.getItemText())

  def update(self, por, text, text_offset, added, **kwargs):
    '''
    Updates the L{DefaultPerk}.last_caret with the current L{por}.
    
    @param por: Point of regard where the caret event occurred
    @type por: L{POR}
    @param text: The text inserted, deleted or the line of the caret
    @type text: string
    @param text_offset: The offset of the inserted/deleted text or the line 
      offset when movement only
    @type text_offset: integer
    @param added: True when text added, False when text deleted, and None 
      when event is for caret movement only
    @type added: boolean
    '''
    self.sayItem(text=self.getItemText())
