"""
Mouse events.


How it works
------------

The renderer has a 2 dimensional grid of mouse event handlers.
(`prompt_toolkit.layout.MouseHandlers`.) When the layout is rendered, the
`Window` class will make sure that this grid will also be filled with
callbacks. For vt100 terminals, mouse events are received through stdin, just
like any other key press. There is a handler among the key bindings that
catches these events and forwards them to such a mouse event handler. It passes
through the `Window` class where the coordinates are translated from absolute
coordinates to coordinates relative to the user control, and there
`UIControl.mouse_handler` is called.
"""
from __future__ import unicode_literals

__all__ = (
    'MouseEventType',
    'MouseButton',
    'MouseModifier',
    'MouseEvent'
)


class MouseEventType:
    """Mouse event types."""
    MOUSE_UP = 'MOUSE_UP'
    MOUSE_DOWN = 'MOUSE_DOWN'
    SCROLL_UP = 'SCROLL_UP'
    SCROLL_DOWN = 'SCROLL_DOWN'
    # Triggered when the left mouse button is held down and the mouse moves
    MOUSE_MOVE = 'MOUSE_MOVE'


MouseEventTypes = MouseEventType  # Deprecated: plural for backwards compatibility.


class MouseButton:
    """Mouse button types."""
    LEFT = 'LEFT'
    MIDDLE = 'MIDDLE'
    RIGHT = 'RIGHT'
    # When we're scrolling, or just moving the mouse and not pressing a button
    NONE = 'NONE'
    # This is for when we don't know which mouse button was pressed
    UNKNOWN = 'UNKNOWN'


class MouseModifier:
    """Mouse modifier keys."""
    SHIFT = 'SHIFT'
    ALT = 'ALT'
    CONTROL = 'CONTROL'


class MouseEvent(object):
    """
    Mouse event, sent to `UIControl.mouse_handler`.

    :param position: `Point` instance.
    :param event_type: `MouseEventType`.
    :param button: `MouseButton` (optional, defaults to UNKNOWN).
    :param modifiers: frozenset of `MouseModifier` (optional, defaults to empty).
    """
    def __init__(self, position, event_type, button=None, modifiers=None):
        self.position = position
        self.event_type = event_type
        self.button = button if button is not None else MouseButton.UNKNOWN
        self.modifiers = modifiers if modifiers is not None else frozenset()

    def __repr__(self):
        return 'MouseEvent(%r, %r, %r, %r)' % (
            self.position, self.event_type, self.button, self.modifiers)
