# -*- coding: utf-8 -*-
"""Where a context menu of a hero button opens (docs/plan/skin-milionar/220-hero-buttons.md).

Kodi centres a context menu on the focused control. A card's menu opens over its row, the row being the focused control.
A hero button lies in a group list, which places its buttons only when it draws them, so Kodi takes the list's own
position for every button and the menu opened at the list's left end. Every hero has an invisible anchor over the width
of its rows at the height of its buttons (gen_cinema.HERO_ANCHOR, id <base> + BUTTON_ANCHOR): it takes the focus while
the menu is open, so the menu opens where the rows' menus open, right over the buttons; then the button gets it back.
"""
from contextlib import contextmanager

import xbmc
from wcs.skin.detail_contract import GROUP as DETAIL_BASE
from wcs.skin.hero_contract import BASES, BUTTON_ANCHOR, BUTTON_OFFSETS, BUTTON_PLAIN


def anchor_of(control):
    """The anchor of the hero whose button `control` (an id) is, or None."""
    for base in tuple(BASES.values()) + (DETAIL_BASE,):
        if control - base in BUTTON_OFFSETS + (BUTTON_PLAIN,):
            return base + BUTTON_ANCHOR
    return None


@contextmanager
def anchored():
    """Open the context menus of this block at the focused hero button's anchor (no change for anything else)."""
    focused = xbmc.getInfoLabel('System.CurrentControlID')
    anchor = anchor_of(int(focused)) if focused.isdigit() else None
    if anchor:
        xbmc.executebuiltin('SetFocus({})'.format(anchor), True)
    try:
        yield
    finally:
        if anchor and xbmc.getInfoLabel('System.CurrentControlID') == str(anchor):
            xbmc.executebuiltin('SetFocus({})'.format(focused), True)
