#!/usr/bin/env python3
import re
from string import ascii_uppercase

from bs4 import BeautifulSoup


def main():
    for c in ascii_uppercase:
        with open(f"src/{c}-html.html") as f:
            for entry in get_entries(BeautifulSoup(f, 'html.parser')):
                print(entry)


magic = '☺☺☺☺☺'
newline  = '\uEAB1'
double_newline  = newline + ' ' + newline


def get_entries(soup):
    entries = []

    def append_entry(english, taiwanese, chinese):
        english = english.strip()
        taiwanese = poj_to_tailo(taiwanese.strip())
        chinese = chinese.strip()

        if not english:
            english = 'FIXME'
        if not taiwanese:
            taiwanese = 'FIXME'
        if not chinese:
            chinese = 'FIXME'

        # Lines starting with '-' indicate examples...
        if not english.startswith('-'):
            part = ':' if ': ' in english else ','
            english, _, extra = english.partition(part)
            if extra:
                extra = extra.strip() + newline
            entries.append(english + '\t' + extra + chinese + newline + taiwanese)
        # ...which are appended to the previous entry
        else:
            english = english.lstrip('- ')
            entries[-1] += double_newline + english + newline + chinese + newline + taiwanese


    class_english = set()
    class_taiwanese = set()
    class_chinese = set()
    class_ignore = set()

    for style in soup.find_all('style'):
        for line in style.text.split():
            match = re.match('\.(ft[0-9]+){', line)
            if not match:
                continue

            ft = match.group(1)

            if 'Arial' in line:
                class_english.add(ft)
            elif 'TaiCooperLtBTLight' in line:
                class_taiwanese.add(ft)
            elif 'MingLiU' in line:
                class_chinese.add(ft)
            else:
                class_ignore.add(ft)


    english = ''
    taiwanese = ''
    chinese = ''
    lastcls = None

    for p in soup.find_all('p'):
        cls = p['class'][0]

        if cls in class_ignore:
            continue

        if p.text in ('.', ',', '…', '\xA0', '(phonetic)'):
            cls = lastcls

        if cls in class_english:
            if lastcls in class_english:
                for br in p('br'):
                    br.replaceWith(magic)
                english = join_lines(english, p.text.replace('-' + magic, '').replace(magic, ''))
            else:
                if lastcls is not None:
                    append_entry(english, taiwanese, chinese)
                english = join_lines('', p.text)
                taiwanese = ''
                chinese = ''

        elif cls in class_chinese:
            chinese = join_lines(chinese, p.text)
        elif cls in class_taiwanese:
            taiwanese = join_lines(taiwanese, p.text, True)
        else:
            assert False

        lastcls = cls

    append_entry(english, taiwanese, chinese)

    return entries


def join_lines(left, right, only_merge_parenthetical=False):
    if left and left[-1] == '-':
        if only_merge_parenthetical:
            if left.count('(') > left.count(')'):
                left = left[:-1]
        else:
                left = left[:-1]

    return left + right.replace('\xA0', ' ')


poj = re.compile(r'''
        (?<=[^a-zA-Z0-9])
        [abceghijklmnopstu]+
        (?P<tone>[235789])?\1?
        [abceghijklmnopstu]*
        (?=[^a-zA-Z0-9])
    ''', re.VERBOSE | re.IGNORECASE)

parens = re.compile('\([^)]+\)')


def poj_to_tailo(string):
    string = string.replace('*+', '+*')
    string = string.replace('+*h', 'onnh')
    string = string.replace('+*', 'onn')
    string = string.replace('*h', 'nnh')
    string = string.replace('h*', 'nnh')
    string = re.sub('\*(?=[A-Za-z])', 'nn-', string)
    string = string.replace('*', 'nn')
    string = string.replace('+h', 'oh')
    string = re.sub('\+(?=[A-Za-z])', 'o-', string)
    string = string.replace('+', 'o')
    string = ' ' + string + ' '
    search_start = 1

    while match := poj.search(string, search_start):
        word = match[0]
        match_start, match_end = match.span()
        search_start = match_end

        def in_parens():
            for p in parens.finditer(string):
                if match_start > p.start() and match_end < p.end():
                    return True
            return False

        if in_parens():
                continue

        if tone := match['tone']:
            word = word.replace(tone, '') + tone
        elif word[-1] in 'ptkh':
            word += '4'
        else:
            word += '1'

        word = word.replace('Ch', 'Ts')
        word = word.replace('ch', 'ts')
        word = word.replace('Ek', 'Ik')
        word = word.replace('ek', 'ik')
        word = word.replace('Eng', 'Ing')
        word = word.replace('eng', 'ing')
        word = re.sub('O([ae])', r'U\1', word)
        word = re.sub('o([ae])', r'u\1', word)

        string = string[:match_start] + word + string[match_end:]

    return string[1:-1]


if __name__ == '__main__':
    main()
