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

from elementmaker import E
from gettext import gettext as _

from book_list.theme import effective_book_list_is_dark, css_for_variables, get_color
from date import format_date
from dom import build_rule, clear, set_css, svgicon
from session import get_interface_data
from utils import fmt_sidx, safe_set_inner_html, sandboxed_html

DETAILS_LIST_CLASS = 'book-list-details-list'
ITEM_CLASS = DETAILS_LIST_CLASS + '-item'


def description():
    return _('A list with thumbnails and some book details')

THUMBNAIL_MAX_WIDTH = 35 * 3
THUMBNAIL_MAX_HEIGHT = int(THUMBNAIL_MAX_WIDTH * 3 / 2)
BORDER_RADIUS = 6


def details_list_css():
    ans = ''
    sel = '.' + DETAILS_LIST_CLASS
    ans += build_rule(sel,
        cursor='pointer',
        user_select='none',
        display='flex',
        flex_direction='column',
        gap='0.75rem',
        padding_top='0.75rem',
        padding_bottom='0.75rem',
        min_width='0',
        max_width='100%',
        box_sizing='border-box',
    )
    ans += build_rule(f'{sel} > .book-list-item',
        min_width='0',
        max_width='100%',
        box_sizing='border-box',
    )
    # Do not underline list-row links on hover (keep the row feeling like a card)
    ans += build_rule(sel + ' a:hover', text_decoration='none')
    # Remove legacy separator rows; use gap + card surfaces instead
    ans += build_rule(sel + ' > div', margin='0', padding='0', border='none')
    ans += build_rule(f'{sel} .{ITEM_CLASS}',
        display='flex',
        align_items='stretch',
        gap='1rem',
        padding='0.85rem 1rem',
        border_radius='18px',
        border='var(--calibre-border-style-subtle)',
        background='var(--calibre-surface-1)',
        box_shadow='0 16px 44px rgba(0,0,0,0.10)',
        text_decoration='none',
        min_width='0',
        max_width='100%',
        width='100%',
        box_sizing='border-box',
        overflow='hidden',
    )
    # No hover zoom; use highlight instead
    ans += build_rule(f'{sel} .{ITEM_CLASS}:hover',
        background_color='var(--calibre-color-primary-light)',
        border_color='var(--calibre-color-border)',
        box_shadow='0 20px 56px rgba(0,0,0,0.12), 0 0 0 4px var(--calibre-color-primary-light)'
    )
    ans += build_rule(f'{sel} .{ITEM_CLASS}:active',
        background_color='var(--calibre-color-primary-light-2)',
        transform='translateY(0.5px)'
    )
    ans += build_rule(f'{sel} .{ITEM_CLASS}:hover .details-list-left > img', box_shadow='0 10px 24px rgba(0,0,0,0.14)')
    s = sel + ' .details-list-left'
    ans += build_rule(s,
        margin_right='1em',
        min_width=f'{THUMBNAIL_MAX_WIDTH}px',
        height=f'{THUMBNAIL_MAX_HEIGHT}px',
        display='flex',
        align_items='stretch'
    )
    # Make the cover fill the full row height
    ans += build_rule(s + ' > img',
        border_radius=BORDER_RADIUS + 'px',
        width=f'{THUMBNAIL_MAX_WIDTH}px',
        height=f'{THUMBNAIL_MAX_HEIGHT}px',
        display='block',
        object_fit='cover',
        border='var(--calibre-border-style-subtle)',
        transition='box-shadow 160ms ease'
    )
    s = sel + ' .details-list-right'
    ans += build_rule(s,
        flex_grow='10',
        flex_shrink='1',
        flex_basis='0',
        min_width='0',
        max_width='100%',
        overflow_x='hidden',
        overflow_y='visible',
        display='flex',
        flex_direction='column',
        min_height='0',
        box_sizing='border-box',
    )
    ans += build_rule(sel + ' .details-main-head',
        display='flex',
        justify_content='space-between',
        gap='0.75rem',
        overflow_x='hidden',
        overflow_y='hidden',
        flex_shrink='0',
        min_height='0',
        min_width='0',
        max_width='100%',
        box_sizing='border-box',
    )
    ans += build_rule(sel + ' .details-head-primary',
        display='flex',
        flex_direction='column',
        flex='1 1 0',
        min_width='0',
        max_width='100%',
        min_height='0',
        overflow='hidden',
    )
    ans += build_rule(sel + ' .details-title-authors',
        flex='0 0 auto',
        min_width='0',
        max_width='100%',
        overflow='hidden',
    )
    ans += build_rule(sel + ' .details-title',
        display='block',
        white_space='nowrap',
        overflow='hidden',
        text_overflow='ellipsis'
    )
    ans += build_rule(sel + ' .details-authors',
        display='block',
        margin_top='0.1rem',
        opacity='0.88',
        white_space='nowrap',
        overflow='hidden',
        text_overflow='ellipsis'
    )
    ans += build_rule(sel + ' .details-comments',
        min_height='4ex',
        margin_top='0.65ex',
        height='0',
        border='none',
        flex_grow='1',
    )

    # Wrap badges (~2 rows): flex cannot use line-clamp; cap height and clip (align-content top).
    ans += sel + ''' .details-meta {
  margin-top: 0.35ex;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 0.35rem 0.6rem;
  opacity: 0.78;
  font-size: 0.92em;
  line-height: 1.25;
  overflow: hidden;
  flex: 0 0 auto;
  min-width: 0;
  max-width: 100%;
  max-height: calc(2 * (1.25em + 0.32rem) + 0.35rem);
}
'''
    ans += build_rule(sel + ' .details-meta:empty',
        display='none', margin_top='0'
    )
    ans += build_rule(sel + ' .details-badge',
        display='inline-flex',
        align_items='center',
        gap='0.25rem',
        padding='0.15rem 0.45rem',
        border_radius='999px',
        border='var(--calibre-border-style-subtle)',
        background='var(--calibre-color-surface-3)',
        max_width='100%',
        white_space='nowrap',
        overflow='hidden',
        text_overflow='ellipsis'
    )
    ans += build_rule(sel + ' .details-series',
        display='block',
        white_space='nowrap',
        overflow='hidden',
        text_overflow='ellipsis',
        max_width='100%',
    )
    ans += build_rule(sel + ' .details-rating',
        display='block',
        white_space='nowrap',
        overflow='hidden',
        text_overflow='ellipsis',
        max_width='100%',
    )
    top = sel + ' .details-main-head'
    extra_data = top + ' > div:last-child'
    primary = sel + ' .details-head-primary'
    ans += build_rule(extra_data,
        text_align='right',
        flex='0 3 auto',
        min_width='0',
        max_width='min(18rem, 48%)',
        overflow_x='hidden',
        overflow_y='visible',
        box_sizing='border-box',
    )
    # Narrow viewports: stack [title+meta] above rating/series. Shrink order: comments > extra > meta > title (via flex-shrink).
    ans += r'''
@media (max-width: 640px) {
  __TOP__ {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
  }
  __EXTRA__ {
    text-align: left;
    margin-top: 0.15rem;
    align-self: stretch;
    max-width: 100%;
    flex: 0 3 auto;
  }
  __PRIMARY__ {
    max-width: 100%;
    flex: 0 1 auto;
    min-height: 0;
  }
  __TA__ {
    max-width: 100%;
  }
}
'''.replace('__TOP__', top).replace('__EXTRA__', extra_data).replace('__PRIMARY__', primary).replace('__TA__', sel + ' .details-title-authors')
    return ans


def init(container):
    clear(container)
    container.appendChild(E.div(class_=DETAILS_LIST_CLASS))


def on_img_load(img, load_type):
    div = img.parentNode
    if not div:
        return
    if load_type is not 'load':
        clear(div)
        div.appendChild(E.div(
            E.h2(img.dataset.title, style='text-align:center; font-size:larger; font-weight: bold'),
            E.div(_('by'), style='text-align: center'),
            E.h2(img.dataset.authors, style='text-align:center; font-size:larger; font-weight: bold')
        ))
        set_css(div, border='dashed 1px currentColor', border_radius=BORDER_RADIUS + 'px')


def sandbox_css():
    is_dark_theme = effective_book_list_is_dark()
    if not sandbox_css.ans or sandbox_css.is_dark_theme is not is_dark_theme:
        sandbox_css.ans = css_for_variables() + '\n\n'
        sandbox_css.ans += 'html {{ overflow: hidden; color: {} }}'.format(get_color('window-foreground'))
        sandbox_css.is_dark_theme = is_dark_theme
    return sandbox_css.ans


def create_item(book_id, metadata, create_image, show_book_details, href):
    authors = metadata.authors.join(' & ') if metadata.authors else _('Unknown')
    img = create_image(book_id, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, on_img_load)
    img.setAttribute('alt', _('{} by {}').format(metadata.title, authors))
    img.dataset.title, img.dataset.authors = metadata.title, authors
    img_div = E.div(img, class_='details-list-left')
    extra_data = E.div()
    comments = sandboxed_html(metadata.comments, sandbox_css())
    comments.classList.add('details-comments')
    if not metadata.comments:
        comments.style.display = 'none'
    interface_data = get_interface_data()
    if metadata.rating:
        stars = E.span(class_='details-rating')
        for i in range(int(metadata.rating) // 2):
            stars.appendChild(svgicon('star'))
        extra_data.appendChild(stars), extra_data.appendChild(E.br())
    if metadata.series:
        try:
            ival = float(metadata.series_index)
        except Exception:
            ival = 1.0
        ival = fmt_sidx(ival, use_roman=interface_data.use_roman_numerals_for_series_number)
        extra_data.appendChild(safe_set_inner_html(E.span(class_='details-series'), _('{0} of <i>{1}</i>').format(ival, metadata.series)))

    # Extra metadata line (publisher / published / formats / languages / tags)
    meta = E.div(class_='details-meta')

    def add_badge(icon, text, title=None):
        if not text:
            return
        b = E.span(class_='details-badge')
        if icon:
            b.appendChild(svgicon(icon))
        b.appendChild(E.span(text))
        if title:
            b.title = title
        meta.appendChild(b)

    if metadata.pubdate:
        try:
            add_badge('date', format_date(metadata.pubdate, 'yyyy-MM-dd'), _('Published'))
        except Exception:
            pass
    fmts = metadata.formats or []
    if fmts and fmts.length:
        add_badge('book', fmts.slice(0, 4).join(' · '), _('Formats'))
    langs = metadata.lang_names or metadata.languages or []
    if langs and langs.length:
        add_badge('global-search', langs.slice(0, 3).join(' · '), _('Languages'))
    tgs = metadata.tags or []
    if tgs and tgs.length:
        for tg in tgs.slice(0, 4):
            add_badge('tags', tg, _('Tag'))
    if metadata.publisher:
        add_badge('library', metadata.publisher, _('Publisher'))

    right = E.div(
        class_='details-list-right',
        E.div(
            class_='details-main-head',
            E.div(
                class_='details-head-primary',
                E.div(
                    class_='details-title-authors',
                    E.b(metadata.title or _('Unknown'), class_='details-title'),
                    E.span(authors, class_='details-authors'),
                ),
                meta,
            ),
            extra_data
        ),
        comments,
    )
    ans = E.div(E.a(img_div, right, href=href,
                style=f'min-height:{THUMBNAIL_MAX_HEIGHT}px; display: flex',
                class_=ITEM_CLASS,
    ))
    ans.addEventListener('click', show_book_details, True)
    return ans


def append_item(container, item):
    container.lastChild.appendChild(item)
