"""Extrage din dumpul dexonline cele două tabele de care avem nevoie:
lexemele (lemele limbii) și formele flexionare (9,2 milioane de forme → lemă).

Nu importăm dumpul într-un server MySQL; îl citim ca text, decomprimat în flux,
și parsăm instrucțiunile INSERT ale tabelelor căutate.

Ieșiri:
  raw/dex_lexemes.tsv   id, formă, modelType, modelNumber, stopWord
  raw/dex_forms.tsv     formă, lexemeId, inflectionId
  raw/dex_inflections.tsv  id, descriere
"""
import gzip, io, os, re, sys

HERE = os.path.dirname(os.path.abspath(__file__))
RAW = os.path.join(HERE, "..", "raw")
SRC = os.path.join(RAW, "dex-database.sql.gz")


def tuples(stmt):
    """Desparte lista VALUES (...),(...) a unui INSERT MySQL în tupluri de câmpuri.

    Parsare caracter cu caracter, fiindcă valorile conțin virgule, paranteze și
    ghilimele escapate.
    """
    i = stmt.index("VALUES") + 6
    n = len(stmt)
    while i < n:
        while i < n and stmt[i] in " \t\r\n,;":
            i += 1
        if i >= n or stmt[i] != "(":
            return
        i += 1
        row, buf, inq, esc = [], [], False, False
        while i < n:
            c = stmt[i]
            if inq:
                if esc:
                    buf.append(c); esc = False
                elif c == "\\":
                    esc = True
                elif c == "'":
                    inq = False
                else:
                    buf.append(c)
            else:
                if c == "'":
                    inq = True
                elif c == ",":
                    row.append("".join(buf)); buf = []
                elif c == ")":
                    row.append("".join(buf))
                    i += 1
                    break
                elif c not in " \t\r\n":
                    buf.append(c)
            i += 1
        yield row


WANT = {"Lexeme", "InflectedForm", "Inflection", "ModelType"}


def main():
    out = {
        "Lexeme": open(os.path.join(RAW, "dex_lexemes.tsv"), "w", encoding="utf8"),
        "InflectedForm": open(os.path.join(RAW, "dex_forms.tsv"), "w", encoding="utf8"),
        "Inflection": open(os.path.join(RAW, "dex_inflections.tsv"), "w", encoding="utf8"),
        "ModelType": open(os.path.join(RAW, "dex_modeltypes.tsv"), "w", encoding="utf8"),
    }
    counts = dict.fromkeys(WANT, 0)
    pat = re.compile(r"^INSERT INTO `([A-Za-z_]+)` VALUES ")
    # Dumpul are un INSERT pe linie foarte lungă; citim linie cu linie.
    with gzip.open(SRC, "rt", encoding="utf8", errors="replace") as fh:
        for line in fh:
            m = pat.match(line)
            if not m:
                continue
            tbl = m.group(1)
            if tbl not in WANT:
                continue
            for r in tuples(line):
                try:
                    if tbl == "Lexeme":
                        # id, form, formNoAccent, formUtf8General, reverse, number,
                        # description, noAccent, consistentAccent, frequency,
                        # hyphenations, pronunciations, stopWord, compound, modelType,
                        # modelNumber, ...
                        # `form` poartă accentul tonic ca apostrof (c'asă); luăm
                        # varianta fără accent, care e ortografia obișnuită.
                        out[tbl].write(f"{r[0]}\t{r[2]}\t{r[14]}\t{r[15]}\t{r[12]}\n")
                    elif tbl == "InflectedForm":
                        # id, form, formNoAccent, formUtf8General, lexemeId, inflectionId
                        out[tbl].write(f"{r[2]}\t{r[4]}\t{r[5]}\n")
                    else:  # Inflection / ModelType: id, descriere
                        out[tbl].write(f"{r[0]}\t{r[1]}\n")
                except IndexError:
                    continue
                counts[tbl] += 1
            if counts["InflectedForm"] and counts["InflectedForm"] % 2000000 < 30000:
                print(f"  ... {counts['InflectedForm']:,} forme", flush=True)
    for f in out.values():
        f.close()
    for k, v in counts.items():
        print(f"{v:>10,}  {k}")


if __name__ == "__main__":
    main()
