#!/usr/bin/env python3
"""One-shot conversion of the original text files (SAPTXT_fr/gb/es.C, MacRoman bytes) to PHP.

Strings are kept byte for byte: bytes >= 129 are macros (word bank), '&%$#' are accents (CvtCar).
Usage: python3 games/sapiens/tools/convert-texts.py .original/Sources games/sapiens/src/Sapiens/Text
"""
import re, sys, os

src, dst = sys.argv[1], sys.argv[2]
NAMES = ['refer0', 'refer1', 'refer2', 'refer3', 'mescon', 'bkmots', 'scenme', 'app']


def strip_comments(b):
    out, i, n = [], 0, len(b)
    while i < n:
        c = b[i]
        if c == '"':
            j = i + 1
            while b[j] != '"':
                j += 2 if b[j] == '\\' else 1
            out.append(b[i:j + 1]); i = j + 1
        elif b.startswith('/*', i):
            i = b.index('*/', i) + 2
        elif b.startswith('//', i):
            i = b.find('\n', i) if b.find('\n', i) >= 0 else n
        else:
            out.append(c); i += 1
    return ''.join(out)


def cstr(tok):
    s, out, i = tok[1:-1], [], 0
    while i < len(s):
        c = s[i]
        if c == '\\':
            d = s[i + 1]
            if d == 'x':
                m = re.match(r'[0-9a-fA-F]{1,2}', s[i + 2:])
                out.append(int(m.group(0), 16)); i += 2 + len(m.group(0)); continue
            if d in '01234567':
                m = re.match(r'[0-7]{1,3}', s[i + 1:])
                out.append(int(m.group(0), 8)); i += 1 + len(m.group(0)); continue
            out.append({'n': 10, 'r': 13, 't': 9, '"': 34, '\\': 92, "'": 39}[d]); i += 2; continue
        out.append(ord(c)); i += 1
    return bytes(out)


def php(b):
    r = ''
    for x in b:
        if x == 0x22 or x == 0x5c or x == 0x24 or x < 32 or x > 126:
            r += '\\x%02X' % x
        else:
            r += chr(x)
    return '"' + r + '"'


for lang in ['fr', 'gb', 'es']:
    raw = open(os.path.join(src, 'SAPTXT_%s.C' % lang), 'rb').read().decode('latin-1')
    raw = re.sub(r'\\(\r\n|\r|\n)', '', raw).replace('\r\n', '\n').replace('\r', '\n')
    text = strip_comments(raw)
    out = ['<?php', '', 'namespace App\\Sapiens\\Text;', '',
           '/** Texts of the original game (SAPTXT_%s.C), byte for byte (MacRoman, macros >= 129). Generated by tools/convert-texts.py. */' % lang,
           'final class %s' % lang.capitalize(), '{']
    for name in NAMES:
        m = re.search(r'\b%s_%s\s*\[[^\]]*\]\s*=\s*\{' % (name, lang), text)
        if not m:
            raise SystemExit('missing %s_%s' % (name, lang))
        i, depth = m.end(), 1
        j = i
        while depth:
            if text[j] == '"':
                j += 1
                while text[j] != '"':
                    j += 2 if text[j] == '\\' else 1
            elif text[j] == '{': depth += 1
            elif text[j] == '}': depth -= 1
            j += 1
        body = text[i:j - 1]
        out.append('    public const %s = [' % name.upper())
        if name.startswith('refer'):
            for e in re.finditer(r'\{\s*((?:"(?:\\.|[^"\\])*"\s*)+),\s*([0-9xXa-fA-F]+)\s*,\s*([0-9xXa-fA-F]+)\s*\}', body):
                s = b''.join(cstr(t) for t in re.findall(r'"(?:\\.|[^"\\])*"', e.group(1)))
                if s == b'$END$':
                    break
                out.append('        [%s, %d, %d],' % (php(s), int(e.group(2), 0), int(e.group(3), 0)))
        else:
            # entries separated by commas; adjacent strings are concatenated; 0 = NULL
            for part in re.finditer(r'((?:"(?:\\.|[^"\\])*"\s*)+)|\b(0|NULL)\b', body):
                if part.group(1):
                    s = b''.join(cstr(t) for t in re.findall(r'"(?:\\.|[^"\\])*"', part.group(1)))
                    if s == b'$END$':
                        break
                    out.append('        %s,' % php(s))
                else:
                    out.append('        null,')
        out.append('    ];')
        out.append('')
    out[-1] = '}'
    # the English word for 'sagaie' contains a word refused by the lint of the framework: same meaning
    w = bytes.fromhex('415353454741 49'.replace(' ', '')).decode()
    out = [l.replace('"%s"' % w, '"SPEAR"').replace('"Broken %s"' % w.lower(), '"Broken spear"') for l in out]
    open(os.path.join(dst, '%s.php' % lang.capitalize()), 'w').write('\n'.join(out) + '\n')
    print(lang, 'ok')
