# generate a json data structure that can be queried for info on a codepoint

import urllib.request
import sys

def compressCategory(abbrev):
    return [
        "Lu",
        "Ll",
        "Lt",
        "LC",
        "Lm",
        "Lo",
        "L",
        "Mn",
        "Mc",
        "Me",
        "M",
        "Nd",
        "Nl",
        "No",
        "N",
        "Pc",
        "Pd",
        "Ps",
        "Pe",
        "Pi",
        "Pf",
        "Po",
        "P",
        "Sm",
        "Sc",
        "Sk",
        "So",
        "S",
        "Zs",
        "Zl",
        "Zp",
        "Z",
        "Cc",
        "Cf",
        "Cs",
        "Co",
        "Cn",
        "C"
    ].index(abbrev)

def parse_file(url):
    """parse a basic unicode database file into a list of lists representing rows of colums"""

    response = urllib.request.urlopen(url)
    text = response.read().decode('utf-8')

    rows = text.splitlines()

    rows = [row for row in rows if row.strip()]           # remove empty lines
    rows = [row for row in rows if row[0] != '#']         # remove comments
    rows = [row.split(';') for row in rows]               # extract fields for each row
    rows = [[col.strip() for col in row] for row in rows] # remove leading/trailing whitespace

    return rows

################################################################################

blocks = parse_file('https://www.unicode.org/Public/12.1.0/ucd/Blocks.txt')

blocks = [[int(x, 16) for x in block[0].split('..')] + [block[1]] for block in blocks]
compressedBlocks = [[block[0], block[1], i] for (i, block) in enumerate(blocks)]

def getCompressedBlock(codepoint):
    """determine unicode block a given codepoint belongs to"""

    global compressedBlocks

    for block in compressedBlocks:
        if block[0] <= int(codepoint, 16) and int(codepoint, 16) <= block[1]:
            return block[2]
    else:
        return -1

################################################################################

codepoints = parse_file('http://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt')

# extract codepoint, name, block, and category
codepoints = [[row[0], row[1], getCompressedBlock(row[0]), compressCategory(row[2])] for row in codepoints]

################################################################################

# escape single quotes (actually not required)
#codepoints = [[col.replace("'", "\\'") for col in row] for row in codepoints]

print('''
// generated by ../utils/charinfo.py
var codepointData = {
''')
[print("'{}': ['{}',{},{}],".format(*row)) for row in codepoints]
print('''
};

function getBlock(i) {
    if (i == -1) {
        return "none";
    }

    var blocks = [
''')
[print("'{}',".format(block[2])) for block in blocks]
print('''
    ];
    return blocks[i];
}

function getCategory(i) {

    // via https://unicode.org/reports/tr44/#GC_Values_Table
    var categories = [
        "Uppercase_Letter",
        "Lowercase_Letter",
        "Titlecase_Letter",
        "Cased_Letter",
        "Modifier_Letter",
        "Other_Letter",
        "Letter",
        "Nonspacing_Mark",
        "Spacing_Mark",
        "Enclosing_Mark",
        "Mark",
        "Decimal_Number",
        "Letter_Number",
        "Other_Number",
        "Number",
        "Connector_Punctuation",
        "Dash_Punctuation",
        "Open_Punctuation",
        "Close_Punctuation",
        "Initial_Punctuation",
        "Final_Punctuation",
        "Other_Punctuation",
        "Punctuation",
        "Math_Symbol",
        "Currency_Symbol",
        "Modifier_Symbol",
        "Other_Symbol",
        "Symbol",
        "Space_Separator",
        "Line_Separator",
        "Paragraph_Separator",
        "Separator",
        "Control",
        "Format",
        "Surrogate",
        "Private_Use",
        "Unassigned",
        "Other"
    ];

    return categories[i];
}

function getCodepointData(cp) {
    var cpd = codepointData[cp];
    return {"name": cpd[0], "block": getBlock(cpd[1]), "category": getCategory(cpd[2])};
}

''')

# TODO maybe compress common words/phrases (would have zero performance impact once the js file has been generated, but that might take a significant amount longer if i do this sloppily): SMALL LETTER, CAPITAL LETTER, COMBINING, LATIN, GREEK, CYRILLIC, ARABIC, SUBJOINED, HANGUL CHOSEONG, HANGUL JUNGSEONG, CANADIAN SYLLABICS, COMBINING, LETTER, MODIFIER, APL FUNCTIONAL SYMBOL, PARENTHESIZED, BOX DRAWINGS, MATHEMATICAL, BRAILLE PATTERN DOTS-, HIRAGANA LETTER, KATAKANA LETTER, HANGUL LETTER, SQUARE, HEXAGRAM, YI SYLLABLE, VAI SYLLABLE, CJK COMPATIBILITY IDEOGRAPH-, ARABIC LIGATURE, HALFWIDTH, FULLWIDTH, CUNEIFORM SIGN, EGYPTIAN HIEROGLYPH, ANATOLIAN HIEROGLYPH, BAMUM LETTER PHASE-, TANGUT COMPONENT-
