#!/usr/bin/python

import graphite, sys
from argparse import ArgumentParser

def runtests(chars, modes, orders, levels) :
    # print chars
    t = []
    for c in chars :
        try :
            x = charmap[c]
        except KeyError : 
            return (True, [], [], 0)
        t.append(x)
    test = u"".join(t)
    #if u"\u202B" in test : print "Testing: {}".format(chars)
    if args.debug : print "Testing: {} - dir({})".format(chars, str(modes))
    if modes & 2 :
        (r, o, d) = runonetest(test, 0, orders, levels)
        if not r : return (r, o, d, 'l')
    if modes & 4 :
        (r, o, d) = runonetest(test, 1, orders, levels)
        if not r : return (r, o, d, 'r')
    return (True, [], [], 1)

def runonetest(test, rtl, orders, levels) :
    seg = graphite.Segment(font, face, "", test, rtl)
    orgs = map(lambda x : x.original, seg.slots)
    if rtl : orgs.reverse()
    i = 0
    for o in orgs :
        if i < len(orders) and o == orders[i] :
            i += 1
        elif o in orders :
            return (False, orgs, orders)
    return (True, orgs, orders)

ignores = ['B', 'S']
charmap = {
    'L' : u"A",
    'R' : u"\u08F1",
    'EN' : u"3",
    'ES' : u"-",
    'ET' : u"%",
    'AN' : u"\u0663",
    'CS' : u".",
#    'B' : u"",    # delete for ignore
#    'S' : u"",
    'WS' : u" ",
    'ON' : u"=",
    'LRE' : u"\u202A",
    'LRO' : u"\u202D",
    'AL' : u"\u0627",
    'RLE' : u"\u202B",
    'RLO' : u"\u202E",
    'PDF' : u"\u202C",
    'NSM' : u"\u064B",
    'BN' : u"\u200B",
    'FSI' : u"\u2068",
    'LRI' : u"\u2066",
    'RLI' : u"\u2067",
    'PDI' : u"\u2069",
    'OPP' : u"\u0028",
    'CLP' : u"\u0029",
    'OPS' : u"\u005B",
    'CLS' : u"\u005D",
    'OPB' : u"\u007B",
    'CLB' : u"\u007D"
}

ctmap = {
    '05D0' : 'R',
    '05D1' : 'R',
    '05D2' : 'R',
    '05D3' : 'R',
    '05D4' : 'R',
    '05D5' : 'R',
    '0020' : 'WS',
    '0021' : 'ON',
    '0025' : 'ET',
    '0026' : 'ON',
    '0028' : 'OPP',
    '0029' : 'CLP',
    '002D' : 'ES',
    '002E' : 'CS',
    '002F' : 'CS',
    '0030' : 'EN',
    '0031' : 'EN',
    '0032' : 'EN',
    '0041' : 'L',
    '0042' : 'L',
    '005B' : 'OPS',
    '005D' : 'CLS',
    '0061' : 'L',
    '0062' : 'L',
    '0063' : 'L',
    '0064' : 'L',
    '0065' : 'L',
    '0066' : 'L',
    '0067' : 'L',
    '0068' : 'L',
    '006B' : 'L',
    '006F' : 'L',
    '0073' : 'L',
    '007B' : 'OPB',
    '007D' : 'CLB',
    '061C' : 'AL',
    '0627' : 'AL',
    '0628' : 'AL',
    '0629' : 'AL',
    '062A' : 'AL',
    '062B' : 'AL',
    '062C' : 'AL',
    '0661' : 'AN',
    '0662' : 'AN',
    '202A' : 'LRE',
    '202D' : 'LRO',
    '202B' : 'RLE',
    '202E' : 'RLO',
    '202C' : 'PDF',
    '064B' : 'NSM',
    '200B' : 'BN',
    '2068' : 'FSI',
    '2066' : 'LRI',
    '2067' : 'RLI',
    '2069' : 'PDI',
    '2329' : 'OPS',
    '232A' : 'CLS',
    '2680' : 'ON',
    '2681' : 'ON',
    '2682' : 'ON',
    '2683' : 'ON',
    '3008' : 'OPS',
    '3009' : 'CLS'
}


#tf = open("BidiTest.txt")
#face = graphite.Face("Scheherazade-R.ttf")
p = ArgumentParser()
p.add_argument('fontname', help='font file')
p.add_argument('-t','--test', help='BidiTest.txt type file')
p.add_argument('-c','--chartest', help='BidiCharacterTest.txt type file')
p.add_argument('-d','--debug', action='store_true', help="Debug output")
args = p.parse_args()
face = graphite.Face(args.fontname)
font = graphite.Font(face, 16)

passes = 0
fails = 0
if args.test :
    tf = open(args.test)
    for l in tf.readlines() :
        if l.startswith('#') or len(l) < 2 : continue
        elif l.startswith('@Levels:') :
            levels = l[8:].split()
        elif l.startswith('@Reorder:') :
            orders = map(int, l[9:].split())
        else :
            (chars, modes) = l.split(';')
            (res, orgs, right, d) = runtests(chars.split(), int(modes), orders, levels)
            if not res :
                print "Failed: {0} : {1} vs {2} - {3}".format(l.strip(), orgs, right, d)
                fails += 1
            elif d :
                passes += 1
    tf.close()

if args.chartest :
    tc = open(args.chartest)
    for l in tc.readlines() :
        if l.startswith('#') or len(l) < 2 : continue
        else :
            (charlist, modes, level, levels, orders) = l.split(';')
            chars = map(lambda x: ctmap[x], charlist.split())
            orders = map(int, orders.split())
            levels = levels.split()
            (res, orgs, right, d) = runtests(chars, (int(modes) + 1) * 2, orders, levels)
            if not res :
                print "Failed: {0} : {1} vs {2} - {3}".format(charlist, orgs, right, d)
                fails += 1
            elif d :
                passes += 1
    tc.close()
print "{0} tests passed, {1} failed.".format(passes, fails)

        
