# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 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 Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" 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']
num_values = ['KEY_%s' % k for k in string.digits]

mouse_values = ['MOUSE_LEFT', 'MOUSE_MIDDLE', 'MOUSE_RIGHT',]
values = key_values + num_values + mouse_values + ['NONE']
EventValue = enum.Enum(*values)

EventAction = enum.Enum('NONE', 'GO_UP', 'GO_DOWN', 'GO_LEFT',
                        'GO_RIGHT', 'OK', 'MENU','DVD_MENU',
                        'EXIT', 'PLAY', 'PAUSE',
                        'STOP', 'INC_PLAYBACK_SPEED',
                        'DEC_PLAYBACK_SPEED', 'SEEK_FORWARD',
                        'SEEK_BACKWARD', 'TOGGLE_FULLSCREEN',
                        'MUTE', 'VOL_UP', 'VOL_DOWN',
                        'NEXT','PREVIOUS')
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 action:    event's high level action (EXIT, PLAY, ...)
    @ivar value:     event's value (KEY_a, MOUSE_LEFT, ...)
    @ivar modifier:  event's modifier, especially useful for keyboards
    @ivar source_id: source device id, 0 by default
    """


    def __init__(self, source_type, event_type, action=EventAction.NONE,
                 value=EventValue.NONE, source_id=None, modifier=EventModifier.NONE, origin=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 action:         event's high level action
        @type action:          L{EventAction}
        @param source_id:      source device id, 0 by default
        @type source_id:       int
        @param modifier:       event's modifier, especially useful for keyboards
        @type modifier:        L{EventModifier}
        @param origin:         origin of the event
        @type origin:          L{elisa.core.backend.Backend} or L{elisa.core.frontend.Frontend} or None


        @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.action = action
        self.modifier = modifier
        self.source_id = source_id
        self.origin = origin

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

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

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