"""
For internal use only.
"""
from __future__ import unicode_literals

from rp.prompt_toolkit.mouse_events import MouseEventTypes
import re

__all__ = (
    'has_unclosed_brackets',
    'document_is_multiline_python',
)


def has_unclosed_brackets(text):
    """
    Starting at the end of the string. If we find an opening bracket
    for which we didn't had a closing one yet, return True.
    """
    stack = []

    # Ignore braces inside strings
    text = re.sub(r'''('[^']*'|"[^"]*")''', '', text)  # XXX: handle escaped quotes.!

    for c in reversed(text):
        if c in '])}':
            stack.append(c)

        elif c in '[({':
            if stack:
                if ((c == '[' and stack[-1] == ']') or
                        (c == '{' and stack[-1] == '}') or
                        (c == '(' and stack[-1] == ')')):
                    stack.pop()
            else:
                # Opening bracket for which we didn't had a closing one.
                return True

    return False


_multiline_string_delims = re.compile('''[']{3}|["]{3}''')


def document_is_multiline_python(document):
    """
    Determine whether this is a multiline Python document.
    """
    def ends_in_multiline_string():
        """
        ``True`` if we're inside a multiline string at the end of the text.
        """
        delims = _multiline_string_delims.findall(document.text)
        opening = None
        for delim in delims:
            if opening is None:
                opening = delim
            elif delim == opening:
                opening = None
        return bool(opening)

    if '\n' in document.text or ends_in_multiline_string():
        return True

    def line_ends_with_colon():
        return document.current_line.rstrip()[-1:] == ':'

    # If we just typed a colon, or still have open brackets, always insert a real newline.
    if line_ends_with_colon() or \
            (document.is_cursor_at_the_end and
             has_unclosed_brackets(document.text_before_cursor)) or \
            document.text.startswith('@'):
        return True

    # If the character before the cursor is a backslash (line continuation
    # char), insert a new line.
    elif document.text_before_cursor[-1:] == '\\':
        return True

    return False


def if_mousedown(handler):
    """
    Decorator for mouse handlers.
    Only handle event when the user pressed mouse down.

    (When applied to a token list. Scroll events will bubble up and are handled
    by the Window.)
    """
    def handle_if_mouse_down(cli, mouse_event):
        if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN:
            return handler(cli, mouse_event)
        else:
            return NotImplemented
    return handle_if_mouse_down


