import re
import html
import sublime

phantom_sets_by_buffer = {}
previews_by_buffer = {}

def plugin_unloaded():
    for wnd in sublime.windows():
        for view in wnd.views():
            hide(view)


def show(view, marker, as_phantom=False):
    "Displays Emmet abbreviation as a preview for given view"
    content = None
    buffer_id = view.buffer_id()

    try:
        content = format_snippet(marker.preview())
    except Exception as e:
        content = '<div class="error">%s</div>' % format_snippet(str(e))

    if content:
        if as_phantom:
            if buffer_id not in phantom_sets_by_buffer:
                phantom_set = sublime.PhantomSet(view, 'emmet')
                phantom_sets_by_buffer[buffer_id] = phantom_set
            else:
                phantom_set = phantom_sets_by_buffer[buffer_id]

            r = sublime.Region(marker.region.end(), marker.region.end())
            phantoms = [sublime.Phantom(r, phantom_content(content), sublime.LAYOUT_INLINE)]
            phantom_set.update(phantoms)
        elif not view.is_popup_visible() or previews_by_buffer.get(buffer_id, None) != marker.abbreviation:
            previews_by_buffer[buffer_id] = marker.abbreviation
            view.show_popup(popup_content(content), sublime.COOPERATE_WITH_AUTO_COMPLETE, marker.region.begin(), 400, 300)


def hide(view):
    "Hides Emmet abbreviation preview for given view"
    buffer_id = view.buffer_id()

    if buffer_id in previews_by_buffer:
        del previews_by_buffer[buffer_id]
        view.hide_popup()

    if buffer_id in phantom_sets_by_buffer:
        del phantom_sets_by_buffer[buffer_id]
        view.erase_phantoms('emmet')


def toggle(view, marker, pos, as_phantom=False):
    "Toggle Emmet abbreviation preview display for given marker and location"
    if marker.contains(pos) and marker.abbreviation and (not marker.simple or marker.type == 'stylesheet'):
        show(view, marker, as_phantom)
    else:
        hide(view)

def format_snippet(text, class_name=None):
    class_attr = (' class="%s"' % class_name) if class_name else ''
    lines = [
        '<div%s style="padding-left: %dpx"><code>%s</code></div>' % (class_attr, indent_size(line, 20), html.escape(line, False)) for line in text.splitlines()
    ]

    return '\n'.join(lines)


def popup_content(content):
    return """
    <body>
        <style>
            body { line-height: 1.5rem; }
            .error { color: red }
        </style>
        <div>%s</div>
    </body>
    """ % content


def phantom_content(content):
    return """
    <body>
        <style>
            body {
                background-color: var(--orangish);
                color: #fff;
                border-radius: 3px;
                padding: 1px 3px;
                position: relative;
            }

            .error { color: red }
        </style>
        <div class="main">%s</div>
    </body>
    """ % content


def indent_size(line, width=1):
    m = re.match(r'\t+', line)
    if m:
        return len(m.group(0)) * width
    return 0