# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Lionel Martin <lionel@fluendo.com>'

import string
from elisa.core.components.input_provider import PushInputProvider
from elisa.core.input_event import *
import pgm

KEYS_TO_IGNORE = [pgm.keysyms.Shift_L, pgm.keysyms.Shift_R,
                  pgm.keysyms.Alt_L, pgm.keysyms.Alt_R,
                  pgm.keysyms.Super_L, pgm.keysyms.Super_R,
                  pgm.keysyms.Control_L, pgm.keysyms.Control_R,
                  pgm.keysyms.Tab, pgm.keysyms.Caps_Lock,
                  pgm.keysyms.Delete, pgm.keysyms.Insert,
                  pgm.keysyms.Begin, pgm.keysyms.End,
                  pgm.keysyms.Pause,] + \
                  [getattr(pgm.keysyms, k) for k in dir(pgm.keysyms)
                   if k.startswith('ISO_')]

class PigmentInput(PushInputProvider):
    """
    This class implements Pigment events support.
    """

    def __init__(self):
        PushInputProvider.__init__(self)
        self._handler_ids = []
        self._simple_keys = {}

        for key in string.ascii_letters:
            key_value = getattr(EventValue, 'KEY_%s' % key)
            pgm_key = getattr(pgm.keysyms, key)
            self._simple_keys[pgm_key] = key_value

        for key in string.digits:
            key_value = getattr(EventValue, 'KEY_%s' % key)
            pgm_key = getattr(pgm.keysyms, '_%s' % key)
            self._simple_keys[pgm_key] = key_value


    def bind(self):
        signal_id = self.viewport.connect('key-press-event',
                                          self._process_press_event)
        self._handler_ids.append(signal_id)
        signal_id = self.viewport.connect('key-release-event',
                                          self._process_release_event)
        self._handler_ids.append(signal_id)

    def unbind(self):
        for signal_id in self._handler_ids:
            self.viewport.disconnect(signal_id)

        # releasing our reference to the viewport
        del self.viewport

    def _process_press_event(self, viewport, event):
        elisa_event = self._create_event_with_type(event, EventType.KEY_DOWN)
        self.input_manager.process_event(elisa_event)

    def _process_release_event(self, viewport, event):
        elisa_event = self._create_event_with_type(event, EventType.KEY_UP)
        self.input_manager.process_event(elisa_event)

    def _process_scroll_event(self, viewport, event):
        if event.direction == pgm.SCROLL_DOWN:
            elisa_event = InputEvent(EventSource.MOUSE, EventType.OTHER,
                                     EventValue.KEY_GO_LEFT)
        elif event.direction == pgm.SCROLL_UP:
            elisa_event = InputEvent(EventSource.MOUSE, EventType.OTHER,
                                     EventValue.KEY_GO_RIGHT)

        self.input_manager.process_event(elisa_event)

    def _process_button_press_event(self, viewport, event):
        if event.button == pgm.BUTTON_LEFT:
            elisa_event = InputEvent(EventSource.MOUSE, EventType.OTHER,
                                     EventValue.KEY_GO_DOWN)
        elif event.button == pgm.BUTTON_RIGHT:
            elisa_event = InputEvent(EventSource.MOUSE, EventType.OTHER,
                                     EventValue.KEY_GO_UP)
        elif event.button == pgm.BUTTON_MIDDLE:
            elisa_event = InputEvent(EventSource.MOUSE, EventType.OTHER,
                                     EventValue.KEY_OK)

        self.input_manager.process_event(elisa_event)

    def _create_event_with_type(self, event, event_type):
        elisa_event = None

        if event.modifier == pgm.ALT_MASK:
            modifier = EventModifier.ALT
        #Add here other modifiers as they are neeeded
        else:
            modifier = EventModifier.NONE

        if event_type == EventType.KEY_DOWN:
            # TODO: support more keys
            keyval = event.keyval
            if keyval == pgm.keysyms.Up:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_GO_UP)
            elif keyval == pgm.keysyms.Down:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_GO_DOWN)
            elif keyval == pgm.keysyms.Right:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_GO_RIGHT)
            elif keyval == pgm.keysyms.Left:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_GO_LEFT)
            elif keyval == pgm.keysyms.Page_Down:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_PAGE_DOWN)
            elif keyval == pgm.keysyms.Page_Up:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_PAGE_UP)
            elif keyval in (pgm.keysyms.Return, pgm.keysyms.KP_Enter):
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_OK)
                elisa_event.modifier = modifier
            elif keyval == pgm.keysyms.BackSpace:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_MENU)
            elif keyval == pgm.keysyms.Escape:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_ESCAPE)
            elif keyval == pgm.keysyms.space:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_SPACE)
            elif keyval == pgm.keysyms.F11:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_F11)
            elif keyval == pgm.keysyms.Tab:
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         EventValue.KEY_TAB)
            # All the other events
            elif keyval in self._simple_keys:
                event_value = self._simple_keys[keyval]
                elisa_event = InputEvent(EventSource.KEYBOARD,
                                         EventType.KEY_DOWN,
                                         event_value)
            elif keyval not in KEYS_TO_IGNORE:
                try:
                    unicode_value = unichr(keyval)
                except ValueError:
                    # Pigment most likely returns an invalid keyval (on windows)
                    self.debug("Invalid key value received: %s", keyval)
                else:
                    self.info(u'Sending key as Unicode: %s (%s)', keyval,
                              unicode_value)
                    elisa_event = UnicodeInputEvent(EventType.KEY_DOWN,
                                                    unicode_value)
            else:
                self.info('Unrecognized key received: %s, hw code: %s',
                          keyval, event.hardware_keycode)

        else:
            self.debug('Unrecognized key received: %s', event.keyval)

        return elisa_event
