# -*- coding: utf-8 -*-
"""Український текст для Level 3 A12 — «Перше Різдво».

Зимова розсилка, чотири уроки: неможливе (Захарій та Єлисавета), особливе
доручення (звістка Марії), у Віфлеємі, у храмі.

Ключі — `p<сторінка>b<блок>`, як їх дає `extract.py`. Специфікації:
    {'flow': ...}    — абзац з автопереносом ({sN} перемикає стиль)
    {'lines': [...]} — зберегти сітку рядків: рядок → сегменти (текст, стиль[, x])
    {'drop': True}   — тільки стерти

Цитати — переклад Огієнка (рішення замовника від 2 вересня).

Не перекладається: бренд `bibletime`, `bes`, `www.besweb.com`, реєстраційні
дані, номери сторінок, бокси балів, імена персонажів (B.E.S., Q, Pause,
Beam). Маркер завдання лишається «Q:».

**Імена за Огієнком, а не за звичкою.** Огієнко подає `Захарій` (не
Захарія), `Ангол` (не ангел), а Симеона з Луки 2 звати **`Семен`**
(Луки 2:25 «йому ймення Семен»). Останнє впливає не тільки на текст:
акростих із малюнків на стор. 7 має скластися саме в це слово.

Милі переведено в кілометри, як в усій програмі: 70 миль → «близько 110
кілометрів», масштаб карти 50 miles → «80 км».
"""
import json
import os
import random

from lessons import (MARKS_ROW_UP, hide_cover_rule,
                     label_before_boxes, marks_bonus, wrapped_lines)

TR = {}
POST = []
WIPES = []

HERE = os.path.dirname(os.path.abspath(__file__))
GREEN = (0.0, 0.615, 0.470)          # #009d78 — фірмовий колір рівня 3

with open(os.path.join(HERE, 'work', 'Level3_A12', 'template.json'),
          encoding='utf-8') as _fh:
    _TPL = json.load(_fh)
IDX = {f"p{p['page']}b{b['i']}": b for p in _TPL for b in p['blocks']}

# Золоті вірші тут НЕ надруковані — їх пише дитина, а в блоках `p0b46`
# й далі стоїть лише посилання. Тож звіряти є що лише там, де вірш
# процитовано в тексті уроку.
QUOTES = [
    ('p1b17', 'Луки 1:37', 'Бо для Бога нема неможливої жадної речі'),
    ('p7b26', '1 Івана 4:14', 'Отець послав Сина Спасителем світу'),
]


def Q(key, *text_lines, qs=0, ts=1, tail=()):
    """«Q:» — окремий рядок шаблону на спільній базовій лінії (§2.4)."""
    TR[key] = {'lines': [[('Q:', qs)]] + [[(t, ts)] for t in text_lines]
               + [[seg] for seg in tail]}


def rows(key, *text_lines, s=0):
    TR[key] = {'lines': [[(t, s)] for t in text_lines]}


def head(page, block, big=False, with_name=False):
    """Шапка сторінок: bible|time, підпис рівня, номер серії."""
    lines = []
    if with_name:
        lines.append([("Ім'я:", 0)])
    i = 1 if with_name else 0
    lines.append([('bible', i), ('time', i + 1)])
    lines.append([('Рівень 3 — біблійні історії', i + 2)])
    lines.append([('A12', i + 3)])
    if big:                       # обкладинка має ще й www у шапці
        lines.insert(1, [('www.besweb.com', i + 2)])
        lines[2] = [('Рівень 3 — біблійні історії', i + 3)]
        lines[3] = [('A12', i + 4)]
    TR[f'p{page}b{block}'] = {'lines': lines}


def lesson(key, n, title, s0=0, s1=1):
    TR[key] = {'lines': [[(f'УРОК {n}:', s0), (f' {title}', s1)]]}


# Написи в намальованих боксах («ЧИТАЙ», «ЗОЛОТИЙ ВІРШ») центруються на
# боксі й міряються по його правому краю. Український напис довший за
# англійський — «ЗОЛОТИЙ ВІРШ:» це 65.7 pt проти 48.5 pt у «KEY VERSE:», —
# а бокс намальований, його не розсунеш. Якщо лишити якір оригіналу, напис
# виїжджає за бокс на порожній папір; накладання ні на що немає, тож доти
# це не ловила жодна перевірка (тепер ловить `qa.py`, клас BOX).
KV_BOX = (471.1, 538.1)          # бокс золотого вірша
READ_BOX = (399.6, 466.7)        # бокс «ЧИТАЙ»
BOX_PAD = 1.5


def keyverse(key, *refs, box=KV_BOX):
    TR[key] = {'lines': [[('ЗОЛОТИЙ ВІРШ:', 0)]] + [[(r, 1)] for r in refs],
               'center': True, 'right': box[1] - BOX_PAD}


def read(key, *refs, box=READ_BOX):
    TR[key] = {'lines': [[('ЧИТАЙ:', 0)]] + [[(r, 1)] for r in refs],
               'center': True, 'right': box[1] - BOX_PAD}


# ═══════════════════════════════════════════════════════════ сторінка 1
rows('p0b0', 'Впиши тут своє імʼя та адресу.', 'Вік:', "Ім'я:", 'Адреса:')
for _i, _t in ((1, 'Вік:'), (2, "Ім'я:"), (3, 'Адреса:')):
    TR['p0b0']['lines'][_i] = [(_t, 1)]
rows('p0b1', 'Вчитель:', 'Використовується переклад Біблії Огієнка.')
head(0, 2, big=True)
TR['p0b3'] = {'lines': [[('Рівень 3', 0)]]}
# Підписи під фігурками центруються під СВОЄЮ фігуркою: `center: True`
# ставить кожен рядок на середину відповідного англійського спана, а той
# уже стоїть під фігуркою. Без цього український рядок іншої ширини
# з'їжджає вбік — «запитання» під Q і «підбадьорює» під Beam помітно
# висіли праворуч. Правило замовника від 3 вересня 2026, на всі буклети.
TR['p0b4'] = {'center': True, 'lines': [
    [('B.E.S.', 0)], [('мудрий друг', 1)],
    [('Q', 0)], [('ставить', 1)], [('запитання', 1)]]}
TR['p0b5'] = {'center': True, 'lines': [
    [('Pause', 0)], [('любить', 1)], [('подумати', 1)]]}
TR['p0b6'] = {'center': True, 'lines': [
    [('Beam', 0)], [('друг, який', 1)], [('підбадьорює', 1)]]}

lesson('p0b43', 1, 'Перше Різдво')
TR['p0b44'] = {'lines': [[('Неможливе!', 0)]], 'center': True}
keyverse('p0b46', 'Луки 1:37')
read('p0b48', 'Луки 1:5-20', 'та 57-66')

TR['p0b51'] = {'flow': (
    'Який різдвяний подарунок був у тебе найкращий? Може, це було щось таке, '
    'про що ти й мріяти не смів. У цих уроках ми подивимось на найперше '
    'Різдво — коли народився Ісус. Але перед народженням Ісуса ми читаємо про '
    'іншу дитину, яка стала справжньою радістю для своїх батьків!')}
Q('p0b52', 'Хто був царем, коли народилася ця дитина? Постав позначку у '
           'потрібній клітинці.')
# Клітинки цього завдання (їхні ліві краї) — намальовані квадрати 21.7 pt.
# Слова вирівнюються праворуч до них: слово, пробіл, клітинка.
P1_TICK_X = [159.4, 257.0, 342.4, 430.2]
TR['p0b53'] = {'right': 500.0, 'lines': [
    label_before_boxes(['Кесар', 'Фараон', 'Ірод', 'Яків'], P1_TICK_X)]}
TR['p0b54'] = {'flow': (
    'У ті часи багато хто вважав: якщо в подружжя немає дітей, то вони, '
    'напевно, вчинили щось погане й прогнівили Бога. Але поглянь на вірші 5 і 6.')}
Q('p0b55', 'Напиши СВОЇМИ СЛОВАМИ, якими людьми були Захарій та Єлисавета.')
Q('p0b56', 'Дай відповідь ПРАВДА чи НЕПРАВДА на такі речення:')
# Речення, довші за вільне місце, переносяться на другий рядок: праворуч
# від першого стоїть поле відповіді (його лівий край — 285 pt), і текст на
# нього налазив. Рядки центруються на первісній базовій лінії — інакше пара
# звисає вниз і виглядає зсунутою відносно поля (див. `wrapped_lines`).
TF_LEAD = 12.0


def wrap_tf(key, *texts):
    TR[key] = {'lines': wrapped_lines(IDX[key]['lines'][0]['spans'][0]['y'],
                                      list(texts), lead=TF_LEAD)}


wrap_tf('p0b57', 'Захарій та Єлисавета були', 'літнім подружжям.')
rows('p0b58', 'Захарій працював у палаці.')
rows('p0b59', 'Захарієві зʼявився Ангол.')
wrap_tf('p0b60', 'Захарій та Єлисавета назвали', 'свого сина Йосипом.')

rows('p0b61', 'Сусіди дуже засмутилися.')

# ═══════════════════════════════════════════════════════════ сторінка 2
head(1, 2)
TR['p1b1'] = {'lines': [[('РАЗОМ:', 0)]]}
Q('p1b8', 'Обведи правильну відповідь. Захарій був ...')
# Варіанти вибору набираються ОДНИМ сегментом із широкими пробілами, а не
# кількома сегментами з координатами. Детектор полів ріже рядок варіантів
# або по окремих спанах, або по прогалинах у кілька пробілів; координатна
# розстановка зливає все в один суцільний спан без пробілів, і завдання
# падає в чекбокс «виконано». Англійський оригінал тут дає `choice` — тобто
# це була б тиха втрата саме на перекладі.
TR['p1b9'] = {'right': 500.0, 'lines': [
    [('царем        фарисеєм        рибалкою        священиком', 0, 89.4)]]}
Q('p1b10', 'Словами з біблійного тексту заповни цей кросворд.')
Q('p1b13', 'У якому вірші другого біблійного тексту ми читаємо, як Захарій',
   'прославляв Бога?')
TR['p1b14'] = {'lines': [[('Вірш:', 0)]]}
Q('p1b15', 'Напиши золотий вірш.')
Q('p1b16', 'Гірським краєм якої землі рознеслася звістка про цю дитину?',
   'Напиши відповідь на пагорбах.')
TR['p1b17'] = {'flow': (
    'Захарій не повірив словам Ангола, але вони збулися! Він не мав '
    'сумніватися. Іноді християнам важко повірити в те, що вони читають у '
    'Біблії, — але згадай золотий вірш: «Бо для Бога нема неможливої жадної '
    'речі!»')}

# ═══════════════════════════════════════════════════════════ сторінка 3
head(2, 1, with_name=True)
lesson('p2b2', 2, 'Перше Різдво')
TR['p2b3'] = {'lines': [[('Особливе доручення', 0)]], 'center': True}
keyverse('p2b5', 'Луки 1:38')
read('p2b7', 'Луки 1:26-38')
TR['p2b12'] = {'flow': (
    'Чи вибирали тебе коли-небудь у школі для чогось особливого? Може, зіграти '
    'у виставі або прочитати щось уголос на святі. Від цього стає приємно. А '
    'тепер уяви, що відчула Марія, коли почула звістку: Бог обрав її стати '
    'матірʼю Свого Сина, Ісуса!')}
Q('p2b13', 'Обведи місяць, коли Бог послав Ангола в Назарет.')
TR['p2b14'] = {'right': 500.0, 'lines': [
    [('сьомий місяць        другий місяць        шостий місяць', 0, 85.0)]]}
Q('p2b15', 'Напиши відповіді у відведених місцях, а потім обведи ці слова у',
   'ФІЛВОРДІ. Слова заховані вгору, вниз, упоперек і навпаки.')
Q('p2b17', 'Склади літери, щоб дізнатися, що Ангол сказав Марії.')
Q('p2b20', 'Візьми першу літеру кожного малюнка й дізнайся, як Марія мала '
           'назвати Дитину.')

# ═══════════════════════════════════════════════════════════ сторінка 4
head(3, 2)
TR['p3b1'] = {'lines': [[('РАЗОМ:', 0)]]}
TR['p3b8'] = {'lines': [[('Імʼя Ісус означає Спаситель.', 0)]], 'center': True}
Q('p3b9', 'Ісус має багато інших імен. Випиши два з біблійного тексту.')
TR['p3b10'] = {'lines': [[('і', 0)]], 'center': True}
Q('p3b11', 'Про що запитала Марія, коли почула, що в неї буде Син?')
Q('p3b12', 'Випиши ТРИ речі, які Ангол сказав Марії. (вірш 35)')
TR['p3b13'] = {'right': 265.8, 'flow': (
    'Ось воно, диво першого Різдва! Ісус був Сином Божим: Його матірʼю була '
    'Марія, а Отцем — Бог! Ангол назвав Його «Святе».')}
Q('p3b14', 'Напиши номер вірша, де сказано, що для Бога немає нічого неможливого.')
TR['p3b15'] = {'lines': [[('Вірш:', 0)]]}
Q('p3b16', 'Випиши із золотого вірша те, що сказала Марія.')
TR['p3b17'] = {'flow': (
    'Марію обрали для дуже особливого доручення. Вона мала стати матірʼю '
    'Божого Сина, Ісуса! Вона не скаржилася й не нарікала, хоча багато хто не '
    'зрозумів би її й не повірив би їй.')}
TR['p3b18'] = {'flow': (
    'Коли Бог просить християн щось для Нього зробити, вони можуть згадати '
    'Марію й постаратися слухатися Бога без нарікань!')}
TR['p3b32'] = {'lines': [
    [('Біблія навчає: якби Ісус', 0)],
    [('був сином Марії та Йосипа,', 0)],
    [('то Він був би грішником, як', 0)],
    [('і ми, і ніколи не зміг би', 0)],
    [('спасти нас від', 0)],
    [('наших гріхів!', 0)]], 'center': True}

# ═══════════════════════════════════════════════════════════ сторінка 5
head(4, 1, with_name=True)
lesson('p4b2', 3, 'Перше Різдво')
TR['p4b3'] = {'lines': [[('У Віфлеємі', 0)]], 'center': True}
keyverse('p4b5', 'Луки 2:11')
read('p4b7', 'Луки 2:1-20')
TR['p4b9'] = {'flow': (
    'Вирушати в подорож буває весело, але якщо почуваєшся не дуже добре, це '
    'важко. Марія чекала дитину, і настав час їй народжувати. Разом із Йосипом '
    'вони мусили дістатися до іншого міста, за сто десять кілометрів. Згадай: '
    'ні потягів, ні автівок тоді не було. Дороги були нерівні, а часом і дуже '
    'небезпечні.')}
Q('p4b10', 'Поглянь ще раз на вірші 1-4 і напиши СВОЇМИ',
   'СЛОВАМИ, чому Марія та Йосип мусили піти',
   'до Віфлеєму.')
# На папері дитина проводить лінію, на екрані вибирає зі списку — і кожен
# носій отримує своє формулювання (`SCREEN_TEXT` нижче). Спільний текст ми
# пробували: «Добери відповідь до кожного запитання: лінією на аркуші або зі
# списку» — чесно, але громіздко, і на екрані половина інструкції зайва.
# Ціну (два тексти замість одного) оплачує панель: вона показує Редакторові
# обидва й позначає такі блоки.
Q('p4b11', 'Проведи пряму лінію від кожного запитання до правильної відповіді.')
TR['p4b12'] = {'lines': [[('Хто був намісником Сирії?', 0),
                          ('Назарет', 0, 283.5)]]}
TR['p4b13'] = {'lines': [[('Де жили Марія та Йосип?', 0),
                          ('заїзд', 0, 283.5)]]}
TR['p4b14'] = {'lines': [[('Де народився цар Давид?', 0),
                          ('Квіріній', 0, 283.5)]]}
TR['p4b15'] = {'lines': [[('Де не було місця?', 0),
                          ('Віфлеєм', 0, 283.5)]]}
Q('p4b16', 'Що Марія використала замість колиски для своєї Дитини?')
Q('p4b17', 'У що Марія сповила свою Дитину?')
Q('p4b18', 'Хто був у полі й пильнував овець?')
Q('p4b19', 'Заштрихуй ті слова, які є у звістці Ангола.')
TR['p4b20'] = {'lines': [[('Добра', 0)], [('Новина', 0)]], 'center': True}
TR['p4b22'] = {'lines': [[('Велика', 0)], [('любов', 0)]], 'center': True}
TR['p4b24'] = {'lines': [[('Дивовижна', 0)], [('надія', 0)]], 'center': True}
TR['p4b26'] = {'lines': [[('Радість', 0)], [('велика', 0)]], 'center': True}
TR['p4b32'] = {'lines': [[('Середземне', 0)], [('море', 0)]]}
TR['p4b33'] = {'lines': [[('Назарет', 0)]]}
TR['p4b34'] = {'lines': [[('Віфлеєм', 0)]]}
TR['p4b35'] = {'lines': [[('Мертве', 0, 461.7)], [('море', 0, 464.4)],
                         [('80 км', 0, 413.9)]]}
TR['p4b36'] = {'lines': [[('Земля Ізраїлю', 0)]]}

# ═══════════════════════════════════════════════════════════ сторінка 6
head(5, 2)
TR['p5b1'] = {'lines': [[('РАЗОМ:', 0)]]}
Q('p5b6', 'Напиши золотий вірш.')
Q('p5b7', 'Переставʼ слова, щоб дізнатися, що сказали Анголи.',
   'Напиши відповідь у рамці.')
Q('p5b9', 'Дай відповідь ПРАВДА чи НЕПРАВДА:')
TR['p5b10'] = {'lines': [[('Пастухи:', 0)]]}
rows('p5b11', 'вирішили розібратися в цьому вранці.')
rows('p5b12', 'пішли до Віфлеєму й знайшли Дитину, що лежала в яслах.')
rows('p5b13', 'нікому не розповіли своєї чудової новини.')
Q('p5b14', 'Поглянь на кінець біблійного тексту. У відведених місцях напиши',
   'номер вірша, де сказано, що зробила (а) Марія і (б) пастухи.')
TR['p5b15'] = {'flow': (
    'Що ти відчуваєш, коли думаєш про те, що сталося у Віфлеємі? Для християн '
    'неймовірно, що Син Божий став безпорадним немовлям! Той, Хто створив '
    'світ, колись лежав у яслах!')}
TR['p5b16'] = {'lines': [[('Чи замислювався ти, чому?', 0)]]}
TR['p5b17'] = {'right': 262.1, 'flow': (
    'Якщо знайдеш і прочитаєш Івана 3:16, то знайдеш відповідь. Бог так '
    'полюбив нас, що дав нам безцінний дар — Свого Єдинородного Сина. На '
    'Різдво ми радо приймаємо подарунки й кажемо «дякую». Для християн це '
    'особливий час подякувати Богові за Його дар.')}
TR['p5b19'] = {'lines': [[('Марія', 0)]]}
TR['p5b20'] = {'lines': [[('(а)', 0)]]}
TR['p5b21'] = {'lines': [[('Вірш: ______', 0)]]}
TR['p5b22'] = {'lines': [[('Пастух', 0)]]}
TR['p5b23'] = {'lines': [[('(б)', 0)]]}
TR['p5b24'] = {'lines': [[('Вірш: ______', 0)]]}
TR['p5b32'] = {'lines': [
    [('Дивовижно думати, що', 0)],
    [('Син Божий прийшов у світ', 0)],
    [('так непомітно. Він розуміє', 0)],
    [('твої турботи й тривоги.', 0)],
    [('Чому б не поговорити', 0)],
    [('з Ним сьогодні?', 0)]], 'center': True}

# ═══════════════════════════════════════════════════════════ сторінка 7
head(6, 1, with_name=True)
lesson('p6b2', 4, 'Перше Різдво')
TR['p6b3'] = {'lines': [[('У храмі', 0)]], 'center': True}
keyverse('p6b5', 'Луки 2:30')
read('p6b7', 'Луки 2:22-40')
TR['p6b13'] = {'flow': (
    'Коли на Різдво ми отримуємо подарунок, годиться сказати «дякую». Йосип і '
    'Марія принесли Ісуса в храм, щоб подякувати Богові, — але там на них '
    'чекала ще одна несподіванка!')}
Q('p6b14', 'У якому місті був храм? Підкресли правильну відповідь.')
TR['p6b15'] = {'right': 500.0, 'lines': [
    [('Віфлеєм          Назарет          Єрусалим', 0, 169.6)]]}
Q('p6b16', 'Яку жертву вимагав Закон? (див. вірш 24)')
# Другий рядок цієї інструкції стоїть упритул до ряду малюнків, і біла
# смуга, якою ми закриваємо старий англійський ряд, зрізала йому низ літер.
# Піднімаємо блок на рядок угору: вище нього вільно 16 pt (рамка відповіді
# на попереднє запитання закінчується на 371.6).
_ACRO_LIFT = 8.0
Q('p6b17', 'Напиши першу літеру кожного малюнка й дізнайся імʼя чоловіка,',
   'якого Марія та Йосип зустріли в храмі.')
for _i, _ln in enumerate(TR['p6b17']['lines']):
    _y = IDX['p6b17']['lines'][_i]['spans'][0]['y'] - _ACRO_LIFT
    TR['p6b17']['lines'][_i] = {'segs': _ln, 'y': _y}
Q('p6b25', 'Дізнайся з біблійного тексту, яким був цей чоловік, і дай відповідь',
   'ПРАВДА чи НЕПРАВДА на такі речення:')
rows('p6b26', 'Він жив у Єрусалимі.')
rows('p6b27', 'Він був праведною людиною.')
rows('p6b28', 'Святий Дух був на ньому.')
wrap_tf('p6b29', 'Бог сказав йому, що він ніколи', 'не побачить Христа.')
rows('p6b30', 'Святий Дух припровадив його в храм.')
Q('p6b31', 'Напиши СВОЇМИ СЛОВАМИ, що зробив цей чоловік, побачивши Ісуса.')
TR['p6b32'] = {'flow': (
    'Цей чоловік був одним із небагатьох, хто зрозумів, навіщо Бог послав '
    'Свого Сина. Навіть сьогодні, через дві тисячі років, багато хто не '
    'розуміє, навіщо прийшов Ісус.')}

# ═══════════════════════════════════════════════════════════ сторінка 8
TR['p7b0'] = {'lines': [[('Бали', 0), (' (заповнює вчитель)', 1)]]}
rows('p7b1', 'УРОК 1:')
rows('p7b2', 'УРОК 2:')
rows('p7b3', 'УРОК 3:')
rows('p7b4', 'УРОК 4:')
# «Разом» переїхало на порожній рядок вище; на його місце
# `marks_bonus()` домальовує «Додаткові бали» (див. lessons.py).
TR['p7b5'] = {'lines': [{'segs': [('Разом', 0)], 'y': MARKS_ROW_UP}]}
rows('p7b6', 'Загалом')
TR['p7b7'] = {'lines': [[('Коментар учителя:', 0),
                         ('Надішли свої уроки на адресу:', 0, 471.7)]]}
TR['p7b8'] = {'lines': [[('РАЗОМ:', 0)]]}
TR['p7b9'] = {'lines': [
    [('©', 0), (' Bible Educational Services. Відвідай ', 1), ('www.besweb.com', 2),
     (' або телефонуй +44 (0) 28 6632 2462.', 1)],
    [('Registered Charity UK CIO 1186004', 1)],
    [('РІВЕНЬ 3 A12', 3)],
    [('12/2025', 4)],
]}
Q('p7b15', 'Напиши золотий вірш.')
Q('p7b16', 'Обведи дві групи людей, про які згадує Семен, називаючи Ісуса',
   '«Світлом».')
TR['p7b17'] = {'right': 500.0, 'lines': [
    [('галілеяни      погани (не юдеї)      ізраїльтяни      греки', 0, 96.6)]]}
Q('p7b18', 'За біблійним текстом (вірші 36-38) впиши відповіді про пророчицю',
   'у драбинку слів.')
Q('p7b20', 'Поглянь на «драбинку» в сітці. Як звали пророчицю?')
TR['p7b22'] = {'flow': (
    'Отже, ми бачимо: народження Ісуса зробило багатьох людей дуже щасливими. '
    '(У минулому уроці раділи пастухи, а в цьому — Семен та Анна, не кажучи '
    'вже про Марію та Йосипа!) Але не все життя Ісуса мало бути радісним.')}
Q('p7b23', 'У якому вірші сказано, що Марія колись матиме велике горе?')
TR['p7b24'] = {'lines': [[('Вірш:', 0)]]}
TR['p7b25'] = {'flow': (
    'Напиши нижче, чого ти навчився з цих уроків про прихід Ісуса у світ.')}
TR['p7b26'] = {'lines': [
    [('«Отець послав Сина', 0)],
    [('Спасителем світу».', 0)]], 'center': True}
TR['p7b27'] = {'lines': [[('1 Івана 4:14', 0)]]}
# Три рядки, як в оригіналі. Спершу я переклав двома й загубив третій —
# питання лишилося без кінця: «Чи віриш ти, що Ісус прийшов бути…» ким?
# Ширини вкладаються в хмаринку (91.7 pt при 94.8), тож ужимати нічого не
# доводиться й кегль скрізь однаковий.
TR['p7b43'] = {'lines': [
    [('Чи віриш ти, що', 0)],
    [('Ісус прийшов бути', 0)],
    [('Спасителем світу?', 0)]], 'center': True}


# ═══════════════════════════════════════════════════ головоломки
# Чотири сітки, і жодна не переживає перекладу: довжини слів інші, тож
# перетини не сходяться. §2.6 — складаємо сітку наново, а стару закриваємо.
import fitz                                                    # noqa: E402
from puzzlekit import (cover, draw_grid, extent, number,        # noqa: E402
                       place_crossword, centre_in_cells)

CLUE_RIGHT_P2 = 292.0        # праворуч від цієї межі стоїть новий кросворд
CLUE_RIGHT_P8 = 318.0        # …і нова драбинка


def centred(key, text, style, cx, y=None):
    """Рядок, центрований на заданій осі: сегмент із явним `x`.

    `center: True` тут не годиться — воно центрує кожен сегмент на центрі
    ВІДПОВІДНОГО оригінального спана, а в анаграмі спанів двадцять один
    (по літері), тоді як у нас один рядок.
    """
    from lessons import FONTFILES
    st = IDX[key]['styles'][style]
    fnt = fitz.Font(fontfile=FONTFILES[st['font']])
    size = st['size']
    spec = {'lines': [[(text, style, cx - fnt.text_length(text, size) / 2)]]}
    if y is not None:
        spec['y'] = y
    TR[key] = spec


# ── кросворд, стор. 2 ────────────────────────────────────────────────────
# Слова з Луки 1:5-20 за Огієнком. Напрямки задані навмисно — три вниз і
# чотири впоперек, як в оригіналі: інакше підказки довелося б міняти місцями.
CROSS = [('ІВАН', 'd'), ('ВИНО', 'd'), ('ДУХ', 'd'),
         ('ДРУЖИНА', 'a'), ('КАДІННЯ', 'a'), ('МОЛИТВА', 'a'), ('ХРАМ', 'a')]
CROSS_BOX = (300.0, 199.0, 478.0, 336.0)      # куди має влізти нова сітка

_cross_placed, _cross_missed = place_crossword(CROSS, seed=4)
_cross_nums, _cross_across, _cross_down = number(_cross_placed)
_CN = {p.word: n for n, p in _cross_across + _cross_down}

CLUE = {
    'ІВАН':    'Дитину мали назвати _ _ _ _.',
    'ВИНО':    'Цього дитина не мала пити.',
    'ДУХ':     'Божого Духа ще звуть «Святий _ _ _».',
    'ДРУЖИНА': 'Єлисавета була Захарієві _ _ _ _ _ _ _.',
    'КАДІННЯ': 'Під час чого народ молився знадвору?',
    'МОЛИТВА': 'Ангол сказав, що його _ _ _ _ _ _ _ почута.',
    'ХРАМ':    'Куди ввійшов Захарій і побачив Ангола?',
}


CLUE_X = 56.7


def _at(text, style, x=CLUE_X):
    """Рядок із заданою лівою межею.

    `x` кладеться в ОПЦІЮ рядка, а не третім елементом сегмента. Різниця не
    косметична: третій елемент сегмента означає «координату пораховано з
    ширини цього тексту» (центрування, вирівнювання праворуч), і `edits.py`
    через це відмовляється підставляти правку Редактора — після зміни тексту
    координату треба було б перерахувати. Тут же x — звичайний лівий якір,
    від тексту не залежить, тож правка застосовна.
    """
    return {'segs': [(text, style)], 'x': x}


def _clue_lines(title, words, wrap=None):
    """Заголовок і підказки з НОВИМИ номерами, у порядку зростання."""
    out = [_at(title, 0)]
    for w in sorted(words, key=lambda w: _CN[w]):
        text = f'{_CN[w]}.  {CLUE[w]}'
        for part in (wrap.get(w) if wrap and w in wrap else [text]):
            out.append(_at(part, 1))
    return out


TR['p1b11'] = {'right': CLUE_RIGHT_P2,
               'lines': _clue_lines('По вертикалі:', ['ІВАН', 'ВИНО', 'ДУХ'])}
TR['p1b12'] = {'right': CLUE_RIGHT_P2,
               'lines': _clue_lines('По горизонталі:',
                                    ['ДРУЖИНА', 'КАДІННЯ', 'МОЛИТВА', 'ХРАМ'])}
for _k in ('p1b18', 'p1b19', 'p1b20', 'p1b21', 'p1b22'):
    TR[_k] = {'drop': True}                   # номери старої сітки

# ── філворд, стор. 3 ─────────────────────────────────────────────────────
# Сітка 8×9 — дев'ять блоків по вісім літер, позиції беремо з шаблону.
WS_WORDS = ['ГАЛІЛЕЯ', 'НАЗАРЕТ', 'МАРІЯ', 'ЙОСИП', 'ДАВИД', 'АНГОЛ', 'ГАВРИЇЛ']
WS_KEYS = [f'p2b{n}' for n in range(27, 36)]
ALPHABET = 'АБВГДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ'
ALL_DIRS = [(0, 1), (0, -1), (1, 0), (-1, 0)]


def _ws_make(rows_n, cols_n, words, seed):
    rnd = random.Random(seed)
    grid = [[None] * cols_n for _ in range(rows_n)]
    for w in sorted(words, key=len, reverse=True):
        for _ in range(40000):
            dr, dc = rnd.choice(ALL_DIRS)
            r, c = rnd.randrange(rows_n), rnd.randrange(cols_n)
            er, ec = r + dr * (len(w) - 1), c + dc * (len(w) - 1)
            if not (0 <= er < rows_n and 0 <= ec < cols_n):
                continue
            if any(grid[r + dr * i][c + dc * i] not in (None, ch)
                   for i, ch in enumerate(w)):
                continue
            for i, ch in enumerate(w):
                grid[r + dr * i][c + dc * i] = ch
            break
        else:
            raise RuntimeError('не вклалося: ' + w)
    for r in range(rows_n):
        for c in range(cols_n):
            if grid[r][c] is None:
                grid[r][c] = rnd.choice(ALPHABET)
    return grid


def _fill_wordsearch():
    slots = []
    for key in WS_KEYS:
        blk = IDX[key]
        for li, ln in enumerate(blk['lines']):
            for si, sp in enumerate(ln['spans']):
                slots.append((round(sp['y']), sp['x'], sp['w'], key, li, si))
    slots.sort()
    rows_n = len(WS_KEYS)
    cols_n = len(slots) // rows_n
    assert rows_n * cols_n == len(slots), f'сітка нерівна: {len(slots)} літер'
    for seed in range(1, 4000):
        try:
            grid = _ws_make(rows_n, cols_n, WS_WORDS, seed)
        except RuntimeError:
            continue
        break
    else:
        raise RuntimeError('не вдалося скласти філворд')
    flat = [ch for row in grid for ch in row]
    from lessons import FONTFILES
    font = fitz.Font(fontfile=FONTFILES['Arial-BoldMT'])
    xs = centre_in_cells(slots, flat, font, 12.0)
    per_key = {}
    for (y, x, w, key, li, si), ch in zip(slots, flat):
        per_key.setdefault(key, {})[(li, si)] = ch
    for key, cells in per_key.items():
        blk = IDX[key]
        TR[key] = {'lines': [[(cells[(li, si)], sp['s'], xs[key][(li, si)])
                              for si, sp in enumerate(ln['spans'])]
                             for li, ln in enumerate(blk['lines'])]}
    return rows_n, cols_n


WS_SHAPE = _fill_wordsearch()

_DOTS = '.' * 61
TR['p2b16'] = {'right': 300.0, 'lines': [[(t, 0)] for t in (
    '1. Край, де було місто Марії. (вірш 26)', _DOTS,
    '2. Назва міста. (вірш 26)', _DOTS,
    '3. Імʼя молодої діви. (вірш 27)', _DOTS,
    '4. Чоловік, з яким вона була заручена. (вірш 27)', _DOTS,
    '5. Імʼя царя. (вірші 27 і 32)', _DOTS,
    '6. Звістку приніс', _DOTS[:55] + ' . (вірш 26)',
    '7. Імʼя Ангола. (вірш 26)', _DOTS)]}

# ── анаграма, стор. 3 ────────────────────────────────────────────────────
# «Господь із тобою» (Луки 1:28). Слів три, а не пʼять, тож і сітка
# рисочок унизу інша — вона теж переписується.
ANAGRAM = 'П О Ь Г О Д С  /  З І  /  Б Ю О Т О'
ANAGRAM_KEY = '__ __ __ __ __ __ __  /  __ __  /  __ __ __ __ __ .'

centred('p2b18', ANAGRAM, 0, 283.5)
centred('p2b19', ANAGRAM_KEY, 0, 283.5)

# ── переставити слова, стор. 6 ───────────────────────────────────────────
# «Слава Богу на висоті, і на землі мир, у людях добра воля!» (Луки 2:14).
# Слів дванадцять проти англійських одинадцяти, тож рядок набирається
# наново, а не підмінюється по спанах.
ANGELS_WORDS = 'на   землі   Слава   добра   у   висоті   мир,   Богу   людях   і   воля!   на'
TR['p5b8'] = {'right': 500.0, 'lines': [[(ANGELS_WORDS, 0, 69.9)]]}


# ── драбинка слів, стор. 8 ───────────────────────────────────────────────
# АННА по вертикалі перетинає всі чотири горизонтальні слова — це й є
# «драбинка». Третє слово довелося переклюсувати: англійське `thanked`
# українською «славила», а в ньому немає «Н», якою АННА чіпляється. Тому
# питання взяте з того самого вірша 38, але про інше слово.
# Загальний укладач кросворда сюди не годиться, і не через ваду: він не
# ставить два горизонтальні слова на сусідні рядки, бо в кросворді це дало б
# паразитні вертикальні пари. Драбинка ж саме на цьому й побудована —
# чотири слова одне під одним, прошиті одним вертикальним. Тож розкладка
# тут пряма: колонку задає найдальша літера перетину, слова зсуваються до неї.
LADDER_DOWN = 'АННА'
LADDER = [('АСИР', 0), ('ФАНУЇЛ', 2), ('ВИЗВОЛЕННЯ', 7), ('МОЛИТВАМИ', 6)]
LADDER_BOX = (325.0, 184.0, 505.0, 273.0)
LADDER_HINT = ('ФАНУЇЛ', 4)          # підказана літера, як «H» в оригіналі


def _ladder_layout(down, across):
    from puzzlekit import Placement
    col = max(i for _, i in across)
    for r, (w, i) in enumerate(across):
        assert w[i] == down[r], f'{w}[{i}] != {down[r]}'
    placed = [Placement(w, r, col - i, 0, 1) for r, (w, i) in enumerate(across)]
    placed.append(Placement(down, 0, col, 1, 0))
    return placed


_lad_placed, _lad_missed = _ladder_layout(LADDER_DOWN, LADDER), []
_lad_nums, _lad_across, _lad_down = number(_lad_placed)
_LN = {p.word: n for n, p in _lad_across + _lad_down}

TR['p7b19'] = {'right': CLUE_RIGHT_P8, 'lines': [
    _at('По горизонталі:', 0),
    _at(f'{_LN["АСИР"]}.  З якого племени вона була?', 1),
    _at(f'{_LN["ФАНУЇЛ"]}.  Хто був її батьком?', 1),
    _at(f'{_LN["ВИЗВОЛЕННЯ"]}.  Вона говорила всім, хто чекав', 1),
    _at('_ _ _ _ _ _ _ _ _ _ Єрусалиму.', 1, CLUE_X + 17.0),
    _at(f'{_LN["МОЛИТВАМИ"]}.  Постами й _ _ _ _ _ _ _ _ _ служила Богові.', 1),
]}
for _k in ('p7b28', 'p7b29', 'p7b30', 'p7b31'):
    TR[_k] = {'drop': True}                   # номери й підказка старої сітки

# ── акростихи з малюнків, стор. 3 і 7 ────────────────────────────────────
# Літери задають НАЗВИ предметів, тож англійський набір українською не
# працює взагалі. Замовник вирішив міняти малюнки, а не механіку.
#
# Дешевше, ніж здається: оригінал сам повторює зображення (змія двічі в
# одному рядку, яйце на обох сторінках), тож повтори дозволені — і з
# наявних у PDF складається майже все. Нових картинок дві, вони лежать у
# `data/pictures/` разом із ліцензіями.
#
# Клітинок в обох завданнях на одну більше, ніж літер у слові: «Ісус» —
# чотири при п'яти, «Семен» — п'ять при шести. Зайву закриваємо білим.
PICS = os.path.join(os.path.dirname(HERE), 'data', 'pictures')

ACROSTIC = {
    2: {                                   # стор. 3 — ІСУС
        'band': (712.8, 755.3),            # смуга, де стоять малюнки
        'wipe': (170.0, 709.0, 396.0, 757.0),
        'cells': [186.5, 228.9, 271.2, 313.5],
        'spare': (355.9, 758.0, 380.4, 782.6),
        # У — умивальник, а не удав: наявну змію дитина назве «змією»,
        # і акростих не складеться. Та сама пастка, що з «ескімо».
        'pics': [('file', 'porthole.png'), ('xref', 40),
                 ('file', 'washbasin.png'), ('xref', 40)],
    },
    6: {                                   # стор. 7 — СЕМЕН
        'band': (412.8, 457.4),
        'wipe': (150.0, 410.0, 415.0, 458.5),
        'cells': [170.4, 210.7, 251.0, 291.4, 331.7],
        'spare': (372.0, 459.1, 396.6, 483.6),
        # Е — екскаватор, а не ескімо: наявне на сторінці морозиво дитина
        # назве «морозивом», і акростих не складеться. Редактор і замовник
        # перевірили це на собі — жоден не вгадав «ескімо».
        'pics': [('xref', 40), ('file', 'excavator.png'), ('xref', 38),
                 ('file', 'excavator.png'), ('file', 'scissors.png')],
    },
}
CELL_W = 24.6                              # ширина клітинки відповіді


def _draw_acrostics(doc):
    for pno, a in ACROSTIC.items():
        page = doc[pno]
        y0, y1 = a['band']
        page.draw_rect(fitz.Rect(*a['wipe']), color=None, fill=(1, 1, 1))
        WIPES.append([pno, list(map(float, a['wipe']))])
        # зайва клітинка: закриваємо з запасом, щоб не лишити волосини рамки
        sp = a['spare']
        r = fitz.Rect(sp[0] - 1.5, sp[1] - 1.5, sp[2] + 1.5, sp[3] + 1.5)
        page.draw_rect(r, color=None, fill=(1, 1, 1))
        WIPES.append([pno, [r.x0, r.y0, r.x1, r.y1]])
        for cx, (kind, what) in zip(a['cells'], a['pics']):
            box = fitz.Rect(cx + CELL_W / 2 - 21.0, y0,
                            cx + CELL_W / 2 + 21.0, y1)
            if kind == 'file':
                page.insert_image(box, filename=os.path.join(PICS, what),
                                  keep_proportion=True)
            else:
                page.insert_image(box, stream=doc.extract_image(what)['image'],
                                  keep_proportion=True)
        print('  стор. %d: акростих — %d малюнків, зайву клітинку закрито'
              % (pno + 1, len(a['pics'])))


CROSS_COVERS = {
    # Два прямокутники, бо праворуч унизу стоїть персонаж, і закривати
    # там не можна. Вони НАКЛАДАЮТЬСЯ на 4 pt: якщо стикати їх рівно по
    # одній координаті, у шві лишається волосина від старої лінії.
    1: [(186, 193, 500, 292), (186, 288, 420, 345)],
    7: [(320, 181, 508, 277)],                         # стара драбинка
}


def _fit(box, placed):
    """Крок клітинки й початок так, щоб сітка стала посеред відведеного місця."""
    x0, y0, x1, y1 = box
    _, _, rows_n, cols_n = extent(placed)
    cell = min((x1 - x0) / cols_n, (y1 - y0) / rows_n)
    ox = x0 + ((x1 - x0) - cell * cols_n) / 2
    oy = y0 + ((y1 - y0) - cell * rows_n) / 2
    return (ox, oy), cell, rows_n, cols_n


def apply_covers(page):
    if page.number == 0:
        hide_cover_rule(page, wipes=WIPES)
    rects = CROSS_COVERS.get(page.number)
    if rects:
        cover(page, rects, WIPES)


def _draw_puzzles(doc, only=None):
    def want(pno):
        return only is None or pno in only

    if only is None:
        marks_bonus(doc[7])   # рядок «Додаткові бали»

    if want(1):
        origin, cell, r, c = _fit(CROSS_BOX, _cross_placed)
        draw_grid(doc[1], _cross_placed, _cross_nums, origin, cell, GREEN)
        print(f'  стор. 2: кросворд {r}×{c}, клітинка {cell:.1f} pt'
              + (f', НЕ ЗВʼЯЗАНО: {_cross_missed}' if _cross_missed else ''))

    if only is None:
        _draw_acrostics(doc)

    if want(7):
        page = doc[7]
        origin, cell, r, c = _fit(LADDER_BOX, _lad_placed)
        draw_grid(page, _lad_placed, _lad_nums, origin, cell, GREEN)
        # Сама «драбинка» — стовпчик, у якому складається імʼя. В оригіналі
        # він обведений товстішою лінією; без цього дитина не знає, звідки
        # виписувати відповідь на наступне запитання.
        r0, c0, _, _ = extent(_lad_placed)
        down = next(p for p in _lad_placed if not p.dc)
        for (dr_, dc_) in down.cells():
            x = origin[0] + (dc_ - c0) * cell
            y = origin[1] + (dr_ - r0) * cell
            page.draw_rect(fitz.Rect(x, y, x + cell, y + cell),
                           color=GREEN, width=2.0)

        # Підказана літера: в оригіналі це «H» у першому слові. Без неї
        # драбинка на чотири слова стає помітно важчою.
        from lessons import FONTFILES
        word, pos = LADDER_HINT
        p = next(p for p in _lad_placed if p.word == word)
        ch = word[pos]
        page.insert_font(fontname='uaB', fontfile=FONTFILES['Arial-BoldMT'])
        fnt = fitz.Font(fontfile=FONTFILES['Arial-BoldMT'])
        size = cell * 0.62
        x = origin[0] + (p.c + pos - c0) * cell + (cell - fnt.text_length(ch, size)) / 2
        y = origin[1] + (p.r - r0) * cell + cell * 0.76
        page.insert_text((x, y), ch, fontname='uaB', fontsize=size, color=(0, 0, 0))
        print(f'  стор. 8: драбинка {r}×{c}, клітинка {cell:.1f} pt'
              + (f', НЕ ЗВʼЯЗАНО: {_lad_missed}' if _lad_missed else ''))


POST.append(_draw_puzzles)


# ── праві межі абзаців ───────────────────────────────────────────────────
# §2.4, правило 1: типова межа — край основної колонки. Але якщо праворуч
# від абзацу стоїть ілюстрація чи хмаринка, український текст (він довший)
# заповзе під неї. Ознака — вузький джерельний bbox.
for _k, _v in TR.items():
    if 'flow' in _v and 'right' not in _v:
        _r = IDX[_k]['bbox'][2]
        if _r < 480:
            _v['right'] = _r + 2.0

# ═══════════════════════════════════════════════ поля, оголошені уроком
#
# Клітинки акростихів — рівні квадрати під малюнками. Детектор їх не бачить
# (в англійському оригіналі ці ж завдання теж падають у чекбокс «виконано»),
# і причина не в перекладі: рядок однакових порожніх квадратів без жодної
# рамки-відповіді поруч не має ознаки, за яку він міг би зачепитися.
#
# Замість того щоб вигадувати нове правило детектора під один випадок,
# урок оголошує ці поля сам — той самий механізм, що й для напису на
# дороговказі в Level4_A12. Координати беремо з тих самих `ACROSTIC`, за
# якими розкладені малюнки, тож вони не роз'їдуться.
_CELL_TOP = {2:758.0, 6:459.1}         # верх ряду клітинок на сторінці
_CELL_H = 24.6

# ── «проведи лінію» -> списки вибору, стор. 5 ───────────────────────────
# Намалювати лінію дотиком поле форми не вміє, тож завдання доти діставало
# чекбокс «виконано». Замість нього — список вибору навпроти кожного
# запитання, у вільній смузі між запитанням і колонкою відповідей: саме
# там дитина й провела б лінію. Зміст той самий, дія інша.
MATCH_ANSWERS = ['Назарет', 'заїзд', 'Квіріній', 'Віфлеєм']
MATCH_ROWS_Y = [467.7, 487.7, 507.7, 527.7]     # верх рядка запитання
MATCH_BOX = (200.0, 278.0)                      # вільна смуга по горизонталі

MATCH_FIELDS = [
    {'page': 4, 'task': 2, 'type': 'list',
     'rect': [MATCH_BOX[0], y - 1.0, MATCH_BOX[1], y + 15.0],
     'extra': {'values': MATCH_ANSWERS}}
    for y in MATCH_ROWS_Y
]

_CELL_TASK = {2:4, 6:3}                # номер завдання на своїй сторінці

EXTRA_FIELDS = [
    {'page': pno, 'task': _CELL_TASK[pno], 'type': 'char',
     'rect': [cx + 1.5, _CELL_TOP[pno] + 1.5,
              cx + CELL_W - 1.5, _CELL_TOP[pno] + _CELL_H - 1.5]}
    for pno, a in ACROSTIC.items() for cx in a['cells']
] + MATCH_FIELDS


# ═══════════════════════════════════════════════ екранна версія
#
# Блоки, які в інтерактиві звучать інакше, ніж на друку. Збираються
# командою `build.py <буклет> --screen`; друкований PDF від цього не
# змінюється. Панель показує обидва тексти й позначає такий блок.
# Текст подається ЦІЛКОМ, разом із маркером «Q:» — так само, як його
# бачить і править Редактор у панелі.
SCREEN_TEXT = {
    'p4b11': 'Q:\nДобери відповідь до кожного запитання зі списку.',
}
