# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2023, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import bound_methods, hash_literals

from read_book.globals import current_layout_mode, get_boss
from read_book.viewport import scroll_viewport

anchor_position_cache = {}

def invalidate_anchor_position_cache():
    nonlocal anchor_position_cache
    anchor_position_cache = {
        'layout_mode': current_layout_mode(), 'width': scroll_viewport.width(), 'height': scroll_viewport.height(),
        'positions': v'{}',
    }


def ensure_anchor_cache_valid():
    a = anchor_position_cache
    if a.layout_mode is not current_layout_mode() or a.width is not scroll_viewport.width() or a.height is not scroll_viewport.height():
        invalidate_anchor_position_cache()


def ensure_page_list_target_is_displayed(elem):
    # The stupid EPUB 3 examples have page list links pointing to
    # display:none divs. Sigh.
    if elem and window.getComputedStyle(elem).display is 'none':
        elem.textContent = ''
        elem.setAttribute('style', 'all: revert')


def position_for_anchor(anchor, is_page_list_anchor):
    ensure_anchor_cache_valid()
    cache = anchor_position_cache.positions
    val = cache[anchor]
    if val?:
        return val
    anchor_funcs = get_boss().anchor_funcs
    if anchor:
        elem = document.getElementById(anchor)
        if not elem:
            q = document.getElementsByName(anchor)
            if q and q.length:
                elem = q[0]
    else:
        elem = document.body
    if is_page_list_anchor:
        ensure_page_list_target_is_displayed(elem)
    val = anchor_funcs.pos_for_elem(elem) if elem else anchor_funcs.pos_for_elem()
    cache[anchor] = val
    return val


def is_anchor_on_screen(anchor):
    pos = position_for_anchor(anchor)
    anchor_funcs = get_boss().anchor_funcs
    return anchor_funcs.visibility(pos) is 0
