#!/usr/bin/env python3
"""Generate resources/skins/Default/1080i/games/DialogAICosts.xml: the "Ceny AI" card (AI costs and history).

The same large rounded translucent card as the Millionaire game (it reuses the building blocks of
gen_modern_game.py: panel, button, label, textures, tokens), opened from the hero buttons of the Milionář section.
Left column: the four pages (Přehled, Modely, Účely, Historie) and the actions (Smazat…, Export CSV, Zavřít). Right: the
period chips and the page, chosen by the window property `AICosts.Page` (overview | models | purposes | history | detail).
Lists are one `list` (id 9720) whose rows are filled by wcs/ai/DialogAICosts.py; the daily bars of the overview are
30 images (ids 9801-9830) the dialog positions. Control ids: wcs/ai/DialogAICosts.py. Run after changing this file; never
edit the XML by hand.
"""
import os
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import gen_modern_game as g  # noqa: E402
from xml.sax.saxutils import escape  # noqa: E402

OUT = os.path.join(HERE, '..', '..', 'resources', 'skins', 'Default', '1080i', 'games', 'DialogAICosts.xml')

PAGE_IDS = {'overview': 9701, 'models': 9702, 'purposes': 9703, 'history': 9704}
ACTION_IDS = {'delete': 9761, 'export': 9762, 'close': 9763}
CHIP_IDS = {'today': 9711, 'week': 9712, 'month': 9713, 'all': 9714}
LIST_ID = 9720
BAR_FIRST, BAR_COUNT = 9801, 30

PAD = g.PAD
NAV_X, NAV_W, NAV_H, NAV_GAP, NAV_Y = PAD, 330, 76, 14, 130
ACT_Y, ACT_H, ACT_GAP = 560, 72, 16
CONTENT_X = 420
CONTENT_W = g.CARD_W - PAD - CONTENT_X                    # 1244
CHIP_W, CHIP_H, CHIP_GAP, CHIP_Y = 190, 56, 12, 130
KPI_Y, KPI_H, KPI_GAP = 206, 158, 24
KPI_W = (CONTENT_W - 3 * KPI_GAP) // 4                     # 293
CHART_Y, CHART_H = 380, 206
LIST_Y, LIST_H = 290, 580
OVERVIEW_LIST_SHIFT = 354                                  # the overview's list starts below the chart (644)
ROW_H = 76
OVERVIEW_TOP_Y = 600

PAGE = 'Window.Property(AICosts.Page)'
LIST_INFO = 'ListItem.Property({})'


def str_id(number):
    return '$ADDON[plugin.video.milionar {}]'.format(number)


def on_page(*names):
    return ' | '.join('String.IsEqual({},{})'.format(PAGE, n) for n in names)


def prop(name):
    return '$INFO[Window.Property(AICosts.{})]'.format(name)


def nav_item(ident, page, text, y, indent, links, icon):
    """A page button of the left column: like g.button, plus a gold ring and gold text while its page is open."""
    i = indent + '    '
    w, h, pad = NAV_W, NAV_H, 30
    focus = 'Control.HasFocus({})'.format(ident)
    # the detail of a history entry belongs to the History page
    chosen = on_page(page, 'detail') if page == 'history' else on_page(page)
    idle = '!{} + ![{}]'.format(focus, chosen)
    open_ = '!{} + [{}]'.format(focus, chosen)
    children = [
        g.image(g.BTN_TEX, 0, 0, w, h, i, color=g.BTN_FILL, border=g.R_BTN),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.BTN_STROKE, border=g.R_BTN, visible=idle),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.GOLD, border=g.R_BTN, visible=open_),
        g.image(g.BTN_TEX, 0, 0, w, h, i, color=g.BTN_FOCUS_FILL, border=g.R_BTN, visible=focus,
                animations=[('effect="fade" start="0" end="100" time="140"', 'Visible')]),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.GOLD, border=g.R_BTN, visible=focus,
                animations=[('effect="fade" start="62" end="100" time="900" tween="sine" easing="inout" pulse="true"', 'Visible')]),
        g.image(icon, pad, (h - 36) // 2, 36, 36, i, aspect='keep', visible=idle),
        g.image(icon, pad, (h - 36) // 2, 36, 36, i, aspect='keep', color=g.GOLD, visible=open_),
        g.image(icon, pad, (h - 36) // 2, 36, 36, i, aspect='keep', color=g.INK, visible=focus),
        g.label(text, pad + 58, 0, w - pad - 58 - pad, h, i, font='font27', color=g.TXT, visible=idle),
        g.label(text, pad + 58, 0, w - pad - 58 - pad, h, i, font='font27', color=g.GOLD, visible=open_),
        g.label(text, pad + 58, 0, w - pad - 58 - pad, h, i, font='font27', color=g.INK, visible=focus)]
    body = g.geometry(0, 0, w, h, i + '    ') + [g.tag('label', '', i + '    '),
                                                  '{}<texturefocus>-</texturefocus>'.format(i + '    '),
                                                  '{}<texturenofocus>-</texturenofocus>'.format(i + '    ')]
    body += g.nav(*links, indent=i + '    ')
    children.append(g.control('button', body, i, id=ident))
    zoom = [('effect="zoom" start="100" end="102" center="auto" time="180" tween="cubic" easing="out" condition="{}"'.format(focus),
             'Conditional')]
    return g.group(children, NAV_X, y, w, h, indent, animations=zoom)


def segment(ident, period, text, x, indent, links):
    """A period chip: translucent, a gold ring while it is the chosen period, cream while focused."""
    i = indent + '    '
    w, h = CHIP_W, CHIP_H
    focus = 'Control.HasFocus({})'.format(ident)
    chosen = 'String.IsEqual(Window.Property(AICosts.Period),{})'.format(period)
    children = [
        g.image(g.BTN_TEX, 0, 0, w, h, i, color=g.BTN_FILL, border=g.R_BTN),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.BTN_STROKE, border=g.R_BTN, visible='!{} + !{}'.format(focus, chosen)),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.GOLD, border=g.R_BTN, visible='!{} + {}'.format(focus, chosen)),
        g.image(g.BTN_TEX, 0, 0, w, h, i, color=g.BTN_FOCUS_FILL, border=g.R_BTN, visible=focus,
                animations=[('effect="fade" start="0" end="100" time="140"', 'Visible')]),
        g.image(g.BTN_STROKE_TEX, 0, 0, w, h, i, color=g.GOLD, border=g.R_BTN, visible=focus,
                animations=[('effect="fade" start="62" end="100" time="900" tween="sine" easing="inout" pulse="true"', 'Visible')]),
        g.label(text, 0, 0, w, h, i, font='font25_title', color=g.TXT, align='center', visible='!{} + !{}'.format(focus, chosen)),
        g.label(text, 0, 0, w, h, i, font='font25_title', color=g.GOLD, align='center', visible='!{} + {}'.format(focus, chosen)),
        g.label(text, 0, 0, w, h, i, font='font25_title', color=g.INK, align='center', visible=focus)]
    body = g.geometry(0, 0, w, h, i + '    ') + [g.tag('label', '', i + '    '),
                                                  '{}<texturefocus>-</texturefocus>'.format(i + '    '),
                                                  '{}<texturenofocus>-</texturenofocus>'.format(i + '    ')]
    body += g.nav(*links, indent=i + '    ')
    children.append(g.control('button', body, i, id=ident))
    return g.group(children, x, CHIP_Y, w, h, indent)


def kpi(x, title, value, note, indent):
    i = indent + '    '
    return g.group([g.panel(0, 0, KPI_W, KPI_H, i),
                    g.label(title, 24, 12, KPI_W - 48, 32, i, font='font25', color=g.SUB),
                    g.label(prop(value), 24, 44, KPI_W - 48, 54, i, font='font45_title', color=g.GOLD, scroll=True),
                    g.label(prop(note), 24, 98, KPI_W - 48, 28, i, font='font25', color=g.SUB, scroll=True),
                    g.label(prop(note + '2'), 24, 124, KPI_W - 48, 28, i, font='font25', color=g.DIM, scroll=True)],
                   x, KPI_Y, KPI_W, KPI_H, indent, animations=g.stagger(60))


def bar(ident, indent):
    i = indent + '    '
    body = g.geometry(0, 0, 20, 4, i) + ['{}<texture>{}</texture>'.format(i, g.WHITE_TEX)]
    return g.control('image', body, indent, id=ident)


def chart(indent):
    i = indent + '    '
    children = [g.panel(0, 0, CONTENT_W, CHART_H, i),
                g.label(str_id(32816), 24, 10, 500, 40, i, font='font25_title', color=g.SUB),
                g.label(prop('Facts'), 420, 10, CONTENT_W - 444, 40, i, font='font25', color=g.SUB, align='right', scroll=True),
                g.label(prop('ChartMax'), 24, 50, 300, 28, i, font='font25', color=g.DIM),
                g.image(g.WHITE_TEX, 24, CHART_H - 48, CONTENT_W - 48, 1, i, color='28FFFFFF'),
                g.label(prop('ChartFrom'), 24, CHART_H - 44, 400, 34, i, font='font25', color=g.DIM),
                g.label(prop('ChartTo'), CONTENT_W - 424, CHART_H - 44, 400, 34, i, font='font25', color=g.DIM, align='right')]
    children += [bar(BAR_FIRST + n, i) for n in range(BAR_COUNT)]
    return g.group(children, 0, CHART_Y, CONTENT_W, CHART_H, indent, animations=g.stagger(140))


def row_lines(focused, indent, visible=None):
    """The drawing of a list row, cream with INK text (focused) or plain (not); `visible` limits it (see row_layout)."""
    i = indent + '    '
    w = CONTENT_W
    ink = g.INK if focused else g.TXT
    sub = g.INK if focused else g.DIM
    red = None if focused else g.RED

    def show(extra=None):
        parts = [part for part in (visible, extra) if part]
        return ' + '.join(parts) or None

    def row_label(name, x, y, width, height, font, color, align, error_color=None):
        text = '$INFO[ListItem.Property({})]'.format(name)
        if error_color:
            return (g.label(text, x, y, width, height, i, font=font, color=color, align=align,
                            visible=show('!String.IsEqual(ListItem.Property(error),true)')) +
                    g.label(text, x, y, width, height, i, font=font, color=error_color, align=align,
                            visible=show('String.IsEqual(ListItem.Property(error),true)')))
        return g.label(text, x, y, width, height, i, font=font, color=color, align=align, visible=show())

    lines = []
    if focused:
        lines += g.image(g.BTN_TEX, 0, 2, w, ROW_H - 4, i, color=g.BTN_FOCUS_FILL, border=g.R_BTN, visible=show())
        lines += g.image(g.BTN_STROKE_TEX, 0, 2, w, ROW_H - 4, i, color=g.GOLD, border=g.R_BTN, visible=show(),
                         animations=[('effect="fade" start="62" end="100" time="900" tween="sine" easing="inout" pulse="true"', 'Visible')])
    else:
        lines += g.image(g.WHITE_TEX, 24, ROW_H - 1, w - 48, 1, i, color='14FFFFFF', visible=show())
    lines += row_label('c1', 24, 6, 600, 36, 'font27', ink, 'left', error_color=red)
    lines += row_label('c2', 24, 40, 700, 30, 'font25', sub, 'left')
    lines += row_label('c3', 640, 6, 90, 36, 'font27', ink, 'right')
    lines += row_label('c4', 740, 6, 190, 36, 'font27', ink, 'right')
    lines += row_label('c5', 940, 6, w - 940 - 24, 36, 'font27', ink, 'right', error_color=red)
    track = '33000000' if focused else '26FFFFFF'
    fill = g.INK if focused else g.GOLD
    bar_visible = show('String.IsEqual(ListItem.Property(bar),true)')
    lines += ['{}<control type="progress">'.format(i),
              '{}    <left>740</left><top>56</top><width>190</width><height>7</height>'.format(i),
              '{}    <info>ListItem.Property(share)</info>'.format(i),
              '{}    <texturebg colordiffuse="{}">{}</texturebg>'.format(i, track, g.WHITE_TEX),
              '{}    <lefttexture></lefttexture><righttexture></righttexture><overlaytexture></overlaytexture>'.format(i),
              '{}    <midtexture colordiffuse="{}">{}</midtexture>'.format(i, fill, g.WHITE_TEX),
              '{}    <visible>{}</visible>'.format(i, escape(bar_visible)),
              '{}</control>'.format(i)]
    return lines


def row_layout(focused, indent):
    """The plain row, and for the selected one both looks: Kodi draws the selected row with the focused layout even while
    the list has no focus, so the cream pill shows only while the list does."""
    has_focus = 'Control.HasFocus({})'.format(LIST_ID)
    if focused:
        lines = row_lines(False, indent, '!' + has_focus) + row_lines(True, indent, has_focus)
        tag = 'focusedlayout'
    else:
        lines = row_lines(False, indent)
        tag = 'itemlayout'
    return ['{}<{} height="{}">'.format(indent, tag, ROW_H)] + lines + ['{}</{}>'.format(indent, tag)]


def list_control(indent):
    i = indent + '    '
    shift = [('effect="slide" start="0,0" end="0,{}" time="0" condition="String.IsEqual({},overview)"'.format(OVERVIEW_LIST_SHIFT, PAGE),
              'Conditional')]
    body = g.geometry(0, LIST_Y, CONTENT_W, LIST_H, i) + [
        g.tag('onup', CHIP_IDS['month'], i), g.tag('ondown', 'noop', i), g.tag('onleft', PAGE_IDS['overview'], i),
        g.tag('onright', 'noop', i), g.tag('orientation', 'vertical', i), g.tag('scrolltime', '180', i),
        g.tag('focusposition', '0', i)]
    body += g.anims(shift, i)
    body += row_layout(False, i) + row_layout(True, i)
    return g.control('list', body, indent, id=LIST_ID)


def column_headers(indent):
    i = indent + '    '
    spec = [('Col1', 24, 560, 'left'), ('Col3', 590, 140, 'right'), ('Col4', 740, 190, 'right'), ('Col5', 940, CONTENT_W - 940 - 24, 'right')]
    return g.group([g.label(prop('Heading'), 0, 0, CONTENT_W, 44, i, font='font32_title', color=g.TXT, scroll=True)] +
                   [g.label(prop(name), x, 46, w, 34, i, font='font25', color=g.DIM, align=align) for name, x, w, align in spec] +
                   [g.image(g.WHITE_TEX, 24, 82, CONTENT_W - 48, 1, i, color='28FFFFFF')],
                   0, 198, CONTENT_W, 90, indent, visible='!' + on_page('overview'), animations=g.screen_animations())


def overview_page(indent):
    i = indent + '    '
    x = [n * (KPI_W + KPI_GAP) for n in range(4)]
    return g.group([kpi(x[0], str_id(32812), 'Cost', 'CostNote', i), kpi(x[1], str_id(32813), 'Calls', 'CallsNote', i),
                    kpi(x[2], str_id(32814), 'Tokens', 'TokensNote', i), kpi(x[3], str_id(32815), 'Savings', 'SavingsNote', i),
                    chart(i),
                    g.label(str_id(32817), 0, OVERVIEW_TOP_Y, CONTENT_W, 40, i, font='font25_title', color=g.SUB)],
                   0, 0, CONTENT_W, 960, indent, visible=on_page('overview'), animations=g.screen_animations())


def hint_bar(indent):
    i = indent + '    '
    y = g.CARD_H - 70
    return g.group([
        g.image(g.WHITE_TEX, PAD, 0, g.CARD_W - 2 * PAD, 1, i, color='1FFFFFFF'),
        g.label(str_id(32873), PAD, 12, 110, 46, i, font='font25_title', color=g.TXT),
        g.label(str_id(32874), PAD + 116, 12, 200, 46, i, font='font25', color=g.DIM),
        g.label('OK', g.CARD_W // 2 - 160, 12, 60, 46, i, font='font25_title', color=g.TXT, align='right'),
        g.label(str_id(32875), g.CARD_W // 2 - 90, 12, 240, 46, i, font='font25', color=g.DIM),
        g.label(str_id(32876), g.CARD_W - PAD - 290, 12, 110, 46, i, font='font25_title', color=g.TXT, align='right'),
        g.label(str_id(32877), g.CARD_W - PAD - 170, 12, 170, 46, i, font='font25', color=g.DIM)],
        0, y, g.CARD_W, 70, indent)


def header(indent):
    i = indent + '    '
    return g.group([
        g.image(g.M('brand/milionar-mark.png'), PAD, 30, 52, 52, i, aspect='keep'),
        g.label(prop('TitleSpaced'), PAD + 68, 30, 600, 52, i, font='font25_title', color=g.SUB),
        g.label(prop('Rate'), g.CARD_W - PAD - 700, 30, 700, 52, i, font='font25', color=g.SUB, align='right')],
        0, 0, g.CARD_W, 100, indent)


def card(indent):
    i = indent + '    '
    nav_links = {'overview': (None, PAGE_IDS['models']), 'models': (PAGE_IDS['overview'], PAGE_IDS['purposes']),
                 'purposes': (PAGE_IDS['models'], PAGE_IDS['history']), 'history': (PAGE_IDS['purposes'], ACTION_IDS['delete'])}
    labels = {'overview': 32801, 'models': 32802, 'purposes': 32803, 'history': 32804}
    icons = {'overview': 'icons/infodialogs/info.png', 'models': 'icons/infodialogs/rating.png',
             'purposes': 'icons/infodialogs/cinema.png', 'history': 'osd/fullscreen/buttons/repeat-all.png'}
    body = [
        g.image(g.CARD_TEX, 0, 0, g.CARD_W, g.CARD_H, i, color=g.CARD_FILL, border=g.R_CARD),
        g.image(g.CARD_STROKE_TEX, 0, 0, g.CARD_W, g.CARD_H, i, color=g.CARD_STROKE, border=g.R_CARD),
        header(i)]
    for index, page in enumerate(('overview', 'models', 'purposes', 'history')):
        up, down = nav_links[page]
        body.append(nav_item(PAGE_IDS[page], page, str_id(labels[page]), NAV_Y + index * (NAV_H + NAV_GAP), i,
                             (up, down, None, CHIP_IDS['month']), icons[page]))
    body.append(g.image(g.WHITE_TEX, NAV_X, ACT_Y - 36, NAV_W, 1, i, color='28FFFFFF'))
    actions = [('delete', 32809, 'icons/infodialogs/disable.png', PAGE_IDS['history'], ACTION_IDS['export']),
               ('export', 32810, None, ACTION_IDS['delete'], ACTION_IDS['close']),
               ('close', 32811, 'dialogs/close.png', ACTION_IDS['export'], None)]
    for index, (name, text, icon, up, down) in enumerate(actions):
        body.append(g.button(ACTION_IDS[name], str_id(text), NAV_X, ACT_Y + index * (ACT_H + ACT_GAP), NAV_W, ACT_H, i,
                             (up, down, None, LIST_ID), icon=icon))
    chips = [('today', 32805), ('week', 32806), ('month', 32807), ('all', 32808)]
    content = []
    for index, (period, text) in enumerate(chips):
        left = PAGE_IDS['overview'] if index == 0 else CHIP_IDS[chips[index - 1][0]]
        right = CHIP_IDS[chips[index + 1][0]] if index < 3 else None
        content.append(segment(CHIP_IDS[period], period, str_id(text), index * (CHIP_W + CHIP_GAP), i + '    ',
                               (None, LIST_ID, left, right)))
    content += [overview_page(i + '    '), column_headers(i + '    '), list_control(i + '    ')]
    body.append(g.group(content, CONTENT_X, 0, CONTENT_W, g.CARD_H, i))
    body.append(hint_bar(i))
    return g.group(body, g.CARD_X, g.CARD_Y, g.CARD_W, g.CARD_H, indent,
                   animations=[('effect="fade" start="0" end="100" time="380" tween="cubic" easing="out"', 'WindowOpen'),
                               ('effect="zoom" start="94" end="100" center="auto" time="420" tween="cubic" easing="out"', 'WindowOpen'),
                               ('effect="fade" start="100" end="0" time="220"', 'WindowClose'),
                               ('effect="zoom" start="100" end="96" center="auto" time="220" tween="cubic" easing="in"', 'WindowClose')])


def build():
    indent = '        '
    lines = ['<?xml version="1.0" encoding="UTF-8"?>',
             '<!-- generated by scripts/game_dialog/gen_ai_costs.py: do not edit. The AI costs card (wcs/ai/DialogAICosts.py);'
             ' the page is AICosts.Page, control ids are listed in that module. -->',
             '<window type="dialog">', '    <defaultcontrol always="true">{}</defaultcontrol>'.format(PAGE_IDS['overview']),
             '    <controls>'] + g.image(g.WHITE_TEX, 0, 0, 1920, 1080, '        ', color='C8000000',
                                          animations=[('effect="fade" start="0" end="100" time="300"', 'WindowOpen'),
                                                      ('effect="fade" start="100" end="0" time="220"', 'WindowClose')]) + card(indent) + [
        '    </controls>', '</window>']
    return '\n'.join(lines) + '\n'


if __name__ == '__main__':
    text = build()
    with open(OUT, 'w', encoding='utf-8') as handle:
        handle.write(text)
    print('wrote', os.path.relpath(OUT), len(text.splitlines()), 'lines')
