# -*- 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.

"""
Input events data structures
"""


__maintainer__ = 'Philippe Normand <philippe@fluendo.com>'
__maintainer2__ = 'Florian Boucault <florian@fluendo.com>'


# FIXME: many questions are left unanswered such as:
# - do we need more information than that ?
# : mouse position x/y
# - how do we handle events from multiple Pigment's viewports ?

from elisa.extern import enum
import string

EventSource = enum.Enum('KEYBOARD', 'MOUSE', 'REMOTE', 'OTHER')
EventType = enum.Enum('MOUSE_DOWN', 'MOUSE_UP', 'MOUSE_MOVE', 'KEY_DOWN',
                      'KEY_UP', 'OTHER')


key_values = ['KEY_%s' % k for k in string.ascii_letters] + ['KEY_RETURN'] + ['KEY_SPACE']
num_values = ['KEY_%s' % k for k in string.digits]

mouse_values = ['MOUSE_LEFT', 'MOUSE_MIDDLE', 'MOUSE_RIGHT',]

special_key_values = ['KEY_GO_UP', 'KEY_GO_DOWN', 'KEY_GO_LEFT',
                        'KEY_GO_RIGHT', 'KEY_OK', 'KEY_MENU', 'KEY_DVD_MENU',
                        'KEY_EXIT', 'KEY_PLAY', 'KEY_PAUSE', 'KEY_PLAY_PAUSE',
                        'KEY_STOP', 'KEY_INC_PLAYBACK_SPEED',
                        'KEY_DEC_PLAYBACK_SPEED', 'KEY_SEEK_FORWARD', 'KEY_SEEK_BACKWARD',
                        'KEY_MUTE', 'KEY_VOL_UP', 'KEY_VOL_DOWN',
                        'KEY_NEXT', 'KEY_PREVIOUS', 'KEY_PAGE_UP', 'KEY_PAGE_DOWN',
                        'KEY_ESCAPE', 'KEY_F11', 'KEY_TAB']

values = key_values + num_values + mouse_values + special_key_values + ['NONE']
EventValue = enum.Enum(*values)

EventModifier = enum.Enum('NONE', 'CTRL', 'SHIFT', 'ALT')


class InputEvent:
    """
    InputEvent base class

    Each InputProvider component is able to build them and feed the
    InputManager with them. This class should allow us to abstract any
    kind of input event that can be injected in Elisa.

    @ivar source:    source device of the event (keyboard, mouse, ...)
    @ivar type:      type of event (KEY_UP, KEY_DOWN, ...)
    @ivar value:     event's value (KEY_a, MOUSE_LEFT, ...)
    @ivar modifier:  event's modifier, especially useful for keyboards
    """


    def __init__(self, source_type, event_type, value=EventValue.NONE, modifier=EventModifier.NONE):
        """
        Create an InputEvent of a given type

        @param source_type:    source device of the event (keyboard, mouse, ...)
        @type source_type:     L{EventSource}
        @param event_type:     type of event (key_up, key_down, ...)
        @type event_type:      L{EventType}
        @param value:          event's value (KEY_a, MOUSE_LEFT, ...)
        @type value:           L{EventValue}
        @param modifier:       event's modifier, especially useful for keyboards
        @type modifier:        L{EventModifier}

        @raise ValueError:     raised when either source, event_type
                               or value is None
        """
        if not source_type:
            raise ValueError("Event with no source")
        if not event_type:
            raise ValueError("Event with no type")
        if not value:
            raise ValueError("Event with no value")

        self.source = source_type
        self.type = event_type
        self.value = value
        self.modifier = modifier

    def __str__(self):
        return "InputEvent from a %s with: type=%s, value=%s, modifier=%s" \
                % (self.source, self.type, self.value, self.modifier)

    def __eq__(self, other):
        if not isinstance(other, InputEvent):
            return False
        return self.source == other.source and \
               self.type == other.type and \
               self.value == other.value and \
               self.modifier == other.modifier

    def __ne__(self, other):
        return not self.__eq__(other)

class UnicodeInputEvent(InputEvent):
    """
    An Keyboard C{InputEvent} which has a unicode character as
    I{value} attribute.

    @ivar value: event's value
    @type value: C{unicode}
    """

    def __init__(self, event_type, value=u'', modifier=EventModifier.NONE):
        InputEvent.__init__(self, EventSource.KEYBOARD, event_type,
                            value=value, modifier=modifier)
