#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Одноразове перетворення дампа Біблії Огієнка у формат проєкту.

Вихідний файл — плаский перелік із 31 170 записів
`{"pk":…, "translation":"UBIO", "book":1, "chapter":1, "verse":1, "text":…}`,
такі дампи лежать у відкритих репозиторіях. Формат зручний для бази даних і
незручний для нас: щоб дістати один вірш, довелося б щоразу перебирати весь
перелік або будувати покажчик у пам'яті.

На виході — адресація прямим шляхом `books[USFM].chapters["1"]["21"]`.
Ключі **рядкові** навмисно: у деяких місцях вірші об'єднані («17-18»), і
числовий ключ такого не втримав би.

    .venv/bin/python ua_build/bible_convert.py \\
        data/bible_ohienko.src.json data/bible_ohienko.json

Текст переноситься **дослівно**. Відомі помилки оцифрування не виправляються
тут — вони живуть окремою таблицею в `bible.py`, щоб файл лишався звіряним із
джерелом, а кожне виправлення мало видиму причину.
"""
import argparse
import json
import re

# Порядок канону, коди USFM і назви книг так, як їх пише Огієнко.
# `aliases` — те, як книгу називаємо МИ в буклетах: посилання в уроках
# набрані коротко («Приповідок 21: 1», «2 Самуїла 7: 16»), і саме за ними
# доведеться шукати.
BOOKS = [
    (1,  'GEN', 'Буття',            ['Буття']),
    (2,  'EXO', 'Вихід',            ['Вихід']),
    (3,  'LEV', 'Левит',            ['Левит']),
    (4,  'NUM', 'Числа',            ['Числа']),
    (5,  'DEU', 'Повторення Закону', ['Повторення Закону', 'Повторення']),
    (6,  'JOS', 'Ісус Навин',       ['Ісуса Навина', 'Ісус Навин']),
    (7,  'JDG', 'Книга Суддів',     ['Суддів']),
    (8,  'RUT', 'Рут',              ['Рут']),
    (9,  '1SA', 'Перша Самуїлова',  ['1 Самуїла', '1 Самуїлової']),
    (10, '2SA', 'Друга Самуїлова',  ['2 Самуїла', '2 Самуїлової']),
    (11, '1KI', 'Перша царів',      ['1 Царів']),
    (12, '2KI', 'Друга царів',      ['2 Царів']),
    (13, '1CH', 'Перша хронік',     ['1 Хронік']),
    (14, '2CH', 'Друга хронік',     ['2 Хронік']),
    (15, 'EZR', 'Ездра',            ['Ездри', 'Ездра']),
    (16, 'NEH', 'Неемія',           ['Неемії', 'Неемія']),
    (17, 'EST', 'Естер',            ['Естер']),
    (18, 'JOB', 'Йов',              ['Йова', 'Йов']),
    (19, 'PSA', 'Псалми',           ['Псалом', 'Псалми', 'Псалмів']),
    (20, 'PRO', 'Приповістей',      ['Приповідок', 'Приповістей']),
    (21, 'ECC', 'Екклезіяст',       ['Екклезіяста', 'Екклезіяст']),
    (22, 'SNG', 'Пісня над піснями', ['Пісня над піснями']),
    (23, 'ISA', 'Ісая',             ['Ісаї', 'Ісая']),
    (24, 'JER', 'Єремія',           ['Єремії', 'Єремія']),
    (25, 'LAM', 'Плач Єремії',      ['Плач Єремії']),
    (26, 'EZK', 'Єзекіїль',         ['Єзекіїля', 'Єзекіїль']),
    (27, 'DAN', 'Даниїл',           ['Даниїла', 'Даниїл']),
    (28, 'HOS', 'Осія',             ['Осії', 'Осія']),
    (29, 'JOL', 'Йоіл',             ['Йоіла', 'Йоіл']),
    (30, 'AMO', 'Амос',             ['Амоса', 'Амос']),
    (31, 'OBA', 'Овдій',            ['Овдія', 'Овдій']),
    (32, 'JON', 'Йона',             ['Йони', 'Йона']),
    (33, 'MIC', 'Михей',            ['Михея', 'Михей']),
    (34, 'NAM', 'Наум',             ['Наума', 'Наум']),
    (35, 'HAB', 'Авакум',           ['Авакума', 'Авакум']),
    (36, 'ZEP', 'Софонія',          ['Софонії', 'Софонія']),
    (37, 'HAG', 'Огій',             ['Огія', 'Огій']),
    (38, 'ZEC', 'Захарій',          ['Захарія', 'Захарій']),
    (39, 'MAL', 'Малахії',          ['Малахії']),
    (40, 'MAT', 'Вiд Матвiя',       ['Матвія']),
    (41, 'MRK', 'Вiд Марка',        ['Марка']),
    (42, 'LUK', 'Вiд Луки',         ['Луки']),
    (43, 'JHN', 'Вiд Івана',        ['Івана']),
    (44, 'ACT', 'Дії святих апостолів', ['Дії', 'Діяння']),
    (45, 'ROM', 'До римлян',        ['Римлян']),
    (46, '1CO', 'Перше до коринтян', ['1 Коринтян']),
    (47, '2CO', 'Друге до коринтян', ['2 Коринтян']),
    (48, 'GAL', 'До галатів',       ['Галатів']),
    (49, 'EPH', 'До ефесян',        ['Ефесян']),
    (50, 'PHP', 'До филипʼян',  ['Филипʼян', 'Филип’ян', "Филип'ян"]),
    (51, 'COL', 'До колосян',       ['Колосян']),
    (52, '1TH', 'Перше до солунян', ['1 Солунян']),
    (53, '2TH', 'Друге до солунян', ['2 Солунян']),
    (54, '1TI', 'Перше до Тимофія', ['1 Тимофія']),
    (55, '2TI', 'Друге до Тимофія', ['2 Тимофія']),
    (56, 'TIT', 'До Тита',          ['Тита']),
    (57, 'PHM', 'До Филимона',      ['Филимона']),
    (58, 'HEB', 'До євреїв',        ['Євреїв']),
    (59, 'JAS', 'Якова',            ['Якова']),
    (60, '1PE', 'Перше Петра',      ['1 Петра']),
    (61, '2PE', 'Друге Петра',      ['2 Петра']),
    (62, '1JN', 'Перше Івана',      ['1 Івана']),
    (63, '2JN', 'Друге Івана',      ['2 Івана']),
    (64, '3JN', 'Третє Івана',      ['3 Івана']),
    (65, 'JUD', 'Юда',              ['Юди', 'Юда']),
    (66, 'REV', 'Обʼявлення',   ['Обʼявлення', 'Об’явлення', "Об'явлення"]),
]

TAG_RE = re.compile(r'</?[a-zA-Z][^>]*>')


def clean(text):
    """Прибрати розмітку й звести апостроф до того, яким набрано буклети.

    У дампі апостроф скрізь ASCII (`'`, 3727 разів), а в уроках — `ʼ`
    (U+02BC). Звести треба тут, один раз: інакше дослівна звірка цитати
    ловитиме розбіжність на кожному «зв'язку».
    """
    text = TAG_RE.sub('', text)
    text = text.replace("'", 'ʼ').replace('’', 'ʼ')
    return re.sub(r'\s+', ' ', text).strip()


def convert(src, out):
    rows = json.load(open(src, encoding='utf-8'))
    by_num = {n: (code, name) for n, code, name, _al in BOOKS}
    books = {}
    for n, code, name, aliases in BOOKS:
        books[code] = {'n': n, 'name': name, 'aliases': aliases, 'chapters': {}}
    seen, tags = 0, 0
    for r in rows:
        code, _name = by_num[int(r['book'])]
        ch = str(r['chapter'])
        vs = str(r['verse'])
        t = r['text']
        if TAG_RE.search(t):
            tags += 1
        books[code]['chapters'].setdefault(ch, {})[vs] = clean(t)
        seen += 1

    doc = {
        'translation': 'Огієнко',
        'edition': '1962, Українське Біблійне Товариство',
        'source': 'відкритий дамп UBIO (31 170 віршів), перетворено '
                  'ua_build/bible_convert.py',
        'apostrophe': 'U+02BC (ʼ) — як у буклетах',
        'books': books,
    }
    with open(out, 'w', encoding='utf-8') as fh:
        json.dump(doc, fh, ensure_ascii=False, indent=0, sort_keys=False)
    return seen, tags, books


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument('src')
    ap.add_argument('out')
    a = ap.parse_args()
    seen, tags, books = convert(a.src, a.out)
    ch = sum(len(b['chapters']) for b in books.values())
    print(f'віршів {seen}, розділів {ch}, книг {len(books)}; '
          f'знято розмітки в {tags} віршах')
    print('->', a.out)


if __name__ == '__main__':
    main()
