"""
This module contains code for ClickableText
"""


import urwid
from urwid.util import is_mouse_press


class LinkIndicatorSpec(urwid.AttrSpec):
    """Used to track a link within an urwid.Text instance
    """

    def __init__(self, link_label, link_target, orig_spec):
        """Create a new LinkIndicator spec from an existing urwid.AttrSpec

        :param str link_label: The label for the link
        :param str link_target: The target url for the link
        """
        self.link_label = link_label
        self.link_target = link_target

        urwid.AttrSpec.__init__(
            self, orig_spec.foreground, orig_spec.background)


class ClickableText(urwid.Text):
    """Allows clickable/changing text to be part of the Text() contents
    """

    signals = ["click", "change"]

    def mouse_event(self, size, event, button, x, y, focus):
        """Handle mouse events!
        """
        if button != 1 or not is_mouse_press(event):
            return False

        total_offset = (y * size[0]) + x

        text, chunk_stylings = self.get_text()
        curr_offset = 0

        found_style = None
        found_text = None
        found_idx = 0
        found_length = 0

        for idx, info in enumerate(chunk_stylings):
            style, length = info
            if curr_offset < total_offset <= curr_offset + length:
                found_text = text[curr_offset:curr_offset + length]
                found_style = style
                found_idx = idx
                found_length = length
                break
            curr_offset += length

        if found_style is None or not isinstance(found_style, LinkIndicatorSpec):
            self._emit('click')
            return True

        # it's a link, so change the text and update the RLE!
        if found_text == found_style.link_label:
            new_text = found_style.link_target
        else:
            new_text = found_style.link_label
        text = text[:curr_offset] + new_text + text[curr_offset+found_length:]
        new_rle = len(new_text)

        chunk_stylings[found_idx] = (found_style, new_rle)

        self._text = text
        self._attrib = chunk_stylings
        self._invalidate()

        self._emit("change")

        return True
