"""
Fix glyph anchors for Roboto VF.

Script uses lxml since ufoLib rearranges data.

The script will do the following:

1. Deletes anchors used for design puposes e.g making glyphs built with
   components
2. Renames anchors so no custom MarkWriterFeature is needed for fontmake
3. Ensures each mark glyph only has 1 anchor which starts with an '_'
"""
from __future__ import print_function
import sys
from lxml import etree
import copy
import os
from glob import glob


DUPLICATE_ANCHOR_GLYPHS = [
    "A",
    "A",
    "A.smcp",
    "A.smcp",
    "A.unic",
    "A.unic",
    "AE",
    "AE",
    "AE.smcp",
    "AE.smcp",
    "B",
    "B",
    "B.smcp",
    "B.smcp",
    "C",
    "C",
    "C.smcp",
    "C.smcp",
    "D",
    "D",
    "D.smcp",
    "D.smcp",
    "E",
    "E",
    "E.smcp",
    "E.smcp",
    "E.unic",
    "E.unic",
    "Eng",
    "Eng",
    "Eng.smcp",
    "Eng.smcp",
    "Epsilon1",
    "Epsilon1",
    "Esh",
    "Esh",
    "F",
    "F",
    "F.smcp",
    "F.smcp",
    "G",
    "G",
    "G.smcp",
    "G.smcp",
    "Gamma",
    "Gamma",
    "Gamma.smcp",
    "Gamma.smcp",
    "Gbar",
    "Gbar",
    "Gsmallcap",
    "Gsmallcap",
    "Gsmallcaphook",
    "Gsmallcaphook",
    "H",
    "H",
    "H.smcp",
    "H.smcp",
    "Hbar",
    "Hbar",
    "Hbar.smcp",
    "Hbar.smcp",
    "I",
    "I",
    "I.smcp",
    "I.smcp",
    "Ibar",
    "Ibar",
    "Ismallcap",
    "Ismallcap",
    "J",
    "J",
    "J.smcp",
    "J.smcp",
    "K",
    "K",
    "K.smcp",
    "K.smcp",
    "L",
    "L",
    "L.smcp",
    "L.smcp",
    "Lslash",
    "Lslash",
    "Lslash.smcp",
    "Lslash.smcp",
    "Lsmallcap",
    "Lsmallcap",
    "M",
    "M",
    "M.smcp",
    "M.smcp",
    "M.unic",
    "M.unic",
    "N",
    "N",
    "N.smcp",
    "N.smcp",
    "N.unic",
    "N.unic",
    "Nsmallcap",
    "Nsmallcap",
    "O",
    "O",
    "O.smcp",
    "O.smcp",
    "OE",
    "OE",
    "OEsmallcap",
    "OEsmallcap",
    "Ohorn",
    "Ohorn",
    "Oslash",
    "Oslash",
    "Oslash.smcp",
    "Oslash.smcp",
    "P",
    "P",
    "P.smcp",
    "P.smcp",
    "Q",
    "Q",
    "Q.smcp",
    "Q.smcp",
    "R",
    "R",
    "R.alt",
    "R.alt",
    "R.smcp",
    "R.smcp",
    "Rsmallcap",
    "Rsmallcap",
    "Rsmallcapinv",
    "Rsmallcapinv",
    "S",
    "S",
    "S.smcp",
    "S.smcp",
    "Schwa",
    "Schwa",
    "T",
    "T",
    "T.smcp",
    "T.smcp",
    "Thorn.smcp",
    "Thorn.smcp",
    "U",
    "U",
    "U.smcp",
    "U.smcp",
    "U.unic",
    "U.unic",
    "Uhorn",
    "Uhorn",
    "V",
    "V",
    "V.smcp",
    "V.smcp",
    "W",
    "W",
    "W.smcp",
    "W.smcp",
    "X",
    "X",
    "X.smcp",
    "X.smcp",
    "Y",
    "Y",
    "Y.smcp",
    "Y.smcp",
    "Ysmallcap",
    "Ysmallcap",
    "Z",
    "Z",
    "Z.smcp",
    "Z.smcp",
    "Zbar",
    "Zbar",
    "a",
    "a",
    "a_uni02DE",
    "a_uni02DE",
    "ae",
    "ae",
    "alpha",
    "alpha",
    "ascript",
    "ascript",
    "ascriptturn",
    "ascriptturn",
    "aturn",
    "aturn",
    "b",
    "b",
    "babygamma",
    "babygamma",
    "bbar",
    "bbar",
    "bbar_uni1ABE",
    "bbar_uni1ABE",
    "bhook",
    "bhook",
    "bullseye",
    "bullseye",
    "c",
    "c",
    "ccurl",
    "ccurl",
    "cstretch",
    "cstretch",
    "d",
    "d",
    "dcroat",
    "dcroat",
    "dcroat_uni1ABE",
    "dcroat_uni1ABE",
    "dhook",
    "dhook",
    "dotlessi",
    "dotlessi",
    "drthook",
    "drthook",
    "dyogh",
    "dyogh",
    "dz",
    "dz",
    "dzcurl",
    "dzcurl",
    "e",
    "e",
    "eng",
    "eng",
    "eng_uni1ABE",
    "eng_uni1ABE",
    "epsilon",
    "epsilon",
    "epsilon1",
    "epsilon1",
    "epsilon1rev",
    "epsilon1rev",
    "epsilon1revclosed",
    "epsilon1revclosed",
    "epsilon1revhook",
    "epsilon1revhook",
    "epsilonclosed",
    "epsilonclosed",
    "erev",
    "erev",
    "esh",
    "esh",
    "eshcurl",
    "eshcurl",
    "eshshortrev",
    "eshshortrev",
    "eta",
    "eta",
    "f",
    "f",
    "finalkaf",
    "finalkaf",
    "finalmem",
    "finalmem",
    "finalnun",
    "finalnun",
    "g",
    "g",
    "gamma1",
    "gamma1",
    "gbar",
    "gbar",
    "gbar_uni1ABE",
    "gbar_uni1ABE",
    "gcursive",
    "gcursive",
    "ghook",
    "ghook",
    "glottalstop",
    "glottalstop",
    "glottalstopbar",
    "glottalstopbar",
    "glottalstopbarrev",
    "glottalstopbarrev",
    "glottalstopinv",
    "glottalstopinv",
    "glottalstoprevinv",
    "glottalstoprevinv",
    "h",
    "h",
    "henghook",
    "henghook",
    "hhook",
    "hhook",
    "hturn",
    "hturn",
    "i",
    "i",
    "ibar",
    "ibar",
    "iota",
    "iota",
    "iota1",
    "iota1",
    "j",
    "j",
    "jcrosstail",
    "jcrosstail",
    "jdotlessbar",
    "jdotlessbar",
    "jhookdblbar",
    "jhookdblbar",
    "k",
    "k",
    "k.alt",
    "k.alt",
    "kgreenlandic",
    "kgreenlandic",
    "kturn",
    "kturn",
    "l",
    "l",
    "lbar",
    "lbar",
    "lbelt",
    "lbelt",
    "lmidtilde",
    "lmidtilde",
    "longs",
    "longs",
    "lrthook",
    "lrthook",
    "lslash",
    "lslash",
    "lyogh",
    "lyogh",
    "m",
    "m",
    "mhook",
    "mhook",
    "mturn",
    "mturn",
    "mturndescend",
    "mturndescend",
    "n",
    "n",
    "nlfthook",
    "nlfthook",
    "nrthook",
    "nrthook",
    "o",
    "o",
    "oe",
    "oe",
    "ohorn",
    "ohorn",
    "omega",
    "omega",
    "omegaclosed",
    "omegaclosed",
    "oopen",
    "oopen",
    "oslash",
    "oslash",
    "p",
    "p",
    "philatin",
    "philatin",
    "psi",
    "psi",
    "q",
    "q",
    "qhook",
    "qhook",
    "r",
    "r",
    "rdescend",
    "rdescend",
    "rfishhook",
    "rfishhook",
    "rfishhookrev",
    "rfishhookrev",
    "rho",
    "rho",
    "rrthook",
    "rrthook",
    "rturn",
    "rturn",
    "rturnascend",
    "rturnascend",
    "rturnrthook",
    "rturnrthook",
    "s",
    "s",
    "schwa",
    "schwa",
    "schwahook",
    "schwahook",
    "srthook",
    "srthook",
    "t",
    "t",
    "tccurl",
    "tccurl",
    "tesh",
    "tesh",
    "trthook",
    "trthook",
    "ts",
    "ts",
    "tturn",
    "tturn",
    "u",
    "u",
    "ubar",
    "ubar",
    "uhorn",
    "uhorn",
    "uni0069.ccmp",
    "uni0069.ccmp",
    "uni006A.ccmp",
    "uni006A.ccmp",
    "uni012F.ccmp",
    "uni012F.ccmp",
    "uni0237",
    "uni0237",
    "uni023D",
    "uni023D",
    "uni0243",
    "uni0243",
    "uni0244",
    "uni0244",
    "uni0248",
    "uni0248",
    "uni0249",
    "uni0249",
    "uni0249.ccmp",
    "uni0249.ccmp",
    "uni024C",
    "uni024C",
    "uni024D",
    "uni024D",
    "uni024E",
    "uni024E",
    "uni024F",
    "uni024F",
    "uni0268.ccmp",
    "uni0268.ccmp",
    "uni0292",
    "uni0292",
    "uni0293",
    "uni0293",
    "uni029D.ccmp",
    "uni029D.ccmp",
    "uni02A9",
    "uni02A9",
    "uni02AB",
    "uni02AB",
    "uni02AC",
    "uni02AC",
    "uni02AE",
    "uni02AE",
    "uni02B2.ccmp",
    "uni02B2.ccmp",
    "uni03D2",
    "uni03D2",
    "uni03D6",
    "uni03D6",
    "uni03F3.ccmp",
    "uni03F3.ccmp",
    "uni0404",
    "uni0404",
    "uni0404.smcp",
    "uni0404.smcp",
    "uni0416",
    "uni0416",
    "uni0416.smcp",
    "uni0416.smcp",
    "uni0417",
    "uni0417",
    "uni0417.smcp",
    "uni0417.smcp",
    "uni0418",
    "uni0418",
    "uni0418.smcp",
    "uni0418.smcp",
    "uni0423",
    "uni0423",
    "uni0423.smcp",
    "uni0423.smcp",
    "uni0427",
    "uni0427",
    "uni0427.smcp",
    "uni0427.smcp",
    "uni042B",
    "uni042B",
    "uni042B.smcp",
    "uni042B.smcp",
    "uni042D",
    "uni042D",
    "uni042D.smcp",
    "uni042D.smcp",
    "uni042E",
    "uni042E",
    "uni042E.smcp",
    "uni042E.smcp",
    "uni042F",
    "uni042F",
    "uni042F.smcp",
    "uni042F.smcp",
    "uni0432",
    "uni0432",
    "uni0433",
    "uni0433",
    "uni0434",
    "uni0434",
    "uni0436",
    "uni0436",
    "uni0437",
    "uni0437",
    "uni0438",
    "uni0438",
    "uni043A",
    "uni043A",
    "uni043B",
    "uni043B",
    "uni043C",
    "uni043C",
    "uni043D",
    "uni043D",
    "uni043F",
    "uni043F",
    "uni0442",
    "uni0442",
    "uni0444",
    "uni0444",
    "uni0446",
    "uni0446",
    "uni0447",
    "uni0447",
    "uni0448",
    "uni0448",
    "uni0449",
    "uni0449",
    "uni044B",
    "uni044B",
    "uni044D",
    "uni044D",
    "uni044E",
    "uni044E",
    "uni044F",
    "uni044F",
    "uni0454",
    "uni0454",
    "uni0456.ccmp",
    "uni0456.ccmp",
    "uni0458.ccmp",
    "uni0458.ccmp",
    "uni0460",
    "uni0460",
    "uni0461",
    "uni0461",
    "uni046F",
    "uni046F",
    "uni0472",
    "uni0472",
    "uni0473",
    "uni0473",
    "uni0474",
    "uni0474",
    "uni0475",
    "uni0475",
    "uni047B",
    "uni047B",
    "uni047F",
    "uni047F",
    "uni0480",
    "uni0480",
    "uni0481",
    "uni0481",
    "uni048A",
    "uni048A",
    "uni048B",
    "uni048B",
    "uni04A8",
    "uni04A8",
    "uni04A8.smcp",
    "uni04A8.smcp",
    "uni04A9",
    "uni04A9",
    "uni04BA",
    "uni04BA",
    "uni04BA.smcp",
    "uni04BA.smcp",
    "uni04D8",
    "uni04D8",
    "uni04D8.smcp",
    "uni04D8.smcp",
    "uni04E8.smcp",
    "uni04E8.smcp",
    "uni0504",
    "uni0504",
    "uni0506",
    "uni0506",
    "uni050A",
    "uni050A",
    "uni050C",
    "uni050C",
    "uni050D",
    "uni050D",
    "uni050E",
    "uni050E",
    "uni0510",
    "uni0510",
    "uni1D00",
    "uni1D00",
    "uni1D01",
    "uni1D01",
    "uni1D02",
    "uni1D02",
    "uni1D03",
    "uni1D03",
    "uni1D04",
    "uni1D04",
    "uni1D05",
    "uni1D05",
    "uni1D06",
    "uni1D06",
    "uni1D07",
    "uni1D07",
    "uni1D08",
    "uni1D08",
    "uni1D09",
    "uni1D09",
    "uni1D0A",
    "uni1D0A",
    "uni1D0B",
    "uni1D0B",
    "uni1D0C",
    "uni1D0C",
    "uni1D0D",
    "uni1D0D",
    "uni1D0E",
    "uni1D0E",
    "uni1D0F",
    "uni1D0F",
    "uni1D10",
    "uni1D10",
    "uni1D14",
    "uni1D14",
    "uni1D15",
    "uni1D15",
    "uni1D18",
    "uni1D18",
    "uni1D19",
    "uni1D19",
    "uni1D1A",
    "uni1D1A",
    "uni1D1B",
    "uni1D1B",
    "uni1D1C",
    "uni1D1C",
    "uni1D20",
    "uni1D20",
    "uni1D21",
    "uni1D21",
    "uni1D22",
    "uni1D22",
    "uni1D23",
    "uni1D23",
    "uni1D24",
    "uni1D24",
    "uni1D25",
    "uni1D25",
    "uni1D26",
    "uni1D26",
    "uni1D27",
    "uni1D27",
    "uni1D28",
    "uni1D28",
    "uni1D29",
    "uni1D29",
    "uni1D2A",
    "uni1D2A",
    "uni1D2B",
    "uni1D2B",
    "uni1D62.ccmp",
    "uni1D62.ccmp",
    "uni1D6B",
    "uni1D6B",
    "uni1D6C",
    "uni1D6C",
    "uni1D6D",
    "uni1D6D",
    "uni1D6E",
    "uni1D6E",
    "uni1D6F",
    "uni1D6F",
    "uni1D70",
    "uni1D70",
    "uni1D71",
    "uni1D71",
    "uni1D72",
    "uni1D72",
    "uni1D73",
    "uni1D73",
    "uni1D74",
    "uni1D74",
    "uni1D75",
    "uni1D75",
    "uni1D76",
    "uni1D76",
    "uni1D77",
    "uni1D77",
    "uni1D79",
    "uni1D79",
    "uni1D7A",
    "uni1D7A",
    "uni1D7C",
    "uni1D7C",
    "uni1D7D",
    "uni1D7D",
    "uni1D7E",
    "uni1D7E",
    "uni1D7F",
    "uni1D7F",
    "uni1D80",
    "uni1D80",
    "uni1D81",
    "uni1D81",
    "uni1D82",
    "uni1D82",
    "uni1D83",
    "uni1D83",
    "uni1D84",
    "uni1D84",
    "uni1D85",
    "uni1D85",
    "uni1D86",
    "uni1D86",
    "uni1D87",
    "uni1D87",
    "uni1D88",
    "uni1D88",
    "uni1D89",
    "uni1D89",
    "uni1D8A",
    "uni1D8A",
    "uni1D8B",
    "uni1D8B",
    "uni1D8C",
    "uni1D8C",
    "uni1D8D",
    "uni1D8D",
    "uni1D8E",
    "uni1D8E",
    "uni1D8F",
    "uni1D8F",
    "uni1D90",
    "uni1D90",
    "uni1D91",
    "uni1D91",
    "uni1D92",
    "uni1D92",
    "uni1D93",
    "uni1D93",
    "uni1D94",
    "uni1D94",
    "uni1D95",
    "uni1D95",
    "uni1D96",
    "uni1D96",
    "uni1D96.ccmp",
    "uni1D96.ccmp",
    "uni1D97",
    "uni1D97",
    "uni1D98",
    "uni1D98",
    "uni1D99",
    "uni1D99",
    "uni1D9A",
    "uni1D9A",
    "uni1DA4.ccmp",
    "uni1DA4.ccmp",
    "uni1DA8.ccmp",
    "uni1DA8.ccmp",
    "uni1E2C",
    "uni1E2C",
    "uni1E2D",
    "uni1E2D",
    "uni1E2E",
    "uni1E2E",
    "uni1E2F",
    "uni1E2F",
    "uni2071.ccmp",
    "uni2071.ccmp",
    "uni2C7C.ccmp",
    "uni2C7C.ccmp",
    "upsilon",
    "upsilon",
    "upsilonlatin",
    "upsilonlatin",
    "v",
    "v",
    "vscript",
    "vscript",
    "vturn",
    "vturn",
    "w",
    "w",
    "wturn",
    "wturn",
    "x",
    "x",
    "y",
    "y",
    "yturn",
    "yturn",
    "z",
    "z",
    "zbar",
    "zbar",
    "zcurl",
    "zcurl",
    "zrthook",
    "zrthook"
    # mkmk
    "uni0351",
    "uni0350",
    "uni0357",
    "uni035B",
    "uni0343",
    "uni0342",
    "acuterightnosp",
    "graveleftnosp",
    "uni0346",
    "diaeresistonosnosp",
    "uni034A",
    "overscoredblnosp",
    "tildevertsupnosp",
    "xsupnosp",
    "anglesupnosp",
    "uni030C_uni1ABB",
    "dieresisnosp_uni1ABB",
    "uni034C",
    "tildecomb_uni1ABB",
    "uni0352",
    "uni034B",
    "macroncomb_uni1ABB",
    "tildecomb_uni1ABC",
    "tildevertsupnosp",
    "overscoredblnosp",
    "xsupnosp",
    "anglesupnosp",
    "uni0357",
    "uni0352",
    "uni0350",
    "uni0351",
    "uni035B",
    "uni0346",
    "diaeresistonosnosp",
    "acuterightnosp",
    "uni034C",
    "uni034B",
    "tildecomb_uni1ABC",
    "dieresisnosp_uni1ABB",
    "tildecomb_uni1ABB",
    "uni0342",
    "uni0343",
    "graveleftnosp",
    "uni030C_uni1ABB",
    "macroncomb_uni1ABB",
    "uni034A"
]


def duplicate_anchor(glyph, src, dst):
    outline = glyph.find('outline')
    src_anc = glyph.xpath("//point[@name='{}']".format(src))[0]
    dst_anc = glyph.xpath("//point[@name='{}']".format(dst))

    if not dst_anc:
        dst_anc = copy.deepcopy(src_anc.getparent())
        dst_anc.getchildren()[0].attrib['name'] = dst
        outline.append(dst_anc)


def rename_anchor(glyph, src, dst):
    anc = glyph.xpath("//point[@name='{}']".format(src))
    if anc:
        anc[0].attrib['name'] = dst


def delete_anchor(glyph, anc_name):
    anc = glyph.xpath("//point[@name='{}']".format(anc_name))
    if anc:
        anc = anc[0].getparent()
        anc.getparent().remove(anc)


def _delete_design_anchors(glyph):
    anchors_to_delete = [
        "_ogonek",
        "_rhalfring",
        "_right",
        "_tonos",
        "_top",
        "_bottom",
        "_bottomu",
        "_caron",
        "_cross",
        "_dot",
        "_left",
        "ogonek",
        "rhalfring",
        "right",
        "tonos",
        "bottomu",
        "caron",
        "cross",
        "dot",
        "left"
    ]
    for anchor in anchors_to_delete:
        delete_anchor(glyph, anchor)


def _rename_anchors(glyph):
    anchors = [
        ("_marktop", "_top"),
        ("_markbottom", "_bottom"),
        ("_marktop_dd", "_top_dd"),
        ("_markbottom_dd", "_bottom_dd"),
        ("_markrhotichook", "_rhotichook"),
        ("_marktop0315", "_top0315"),
        ("_markparent_top", "_parent_top"),
        ("_markparenthesses.w1", "_parenthesses.w1"),
        ("_markparenthesses.w2", "_parenthesses.w2"),
        ("_markparenthesses.w3", "_parenthesses.w3"),
        ("mkmktop", "top"),
        ("mkmkbottom_acc", "bottom"),
    ]

    for before_anchor, after_anchor in anchors:
        rename_anchor(glyph, before_anchor, after_anchor)


def _script_already_used(glyph):
    """Check if a user has already executed the script on the .ufo.
    Executing the script multiple times on the same .ufo will lead to
    unforeseen modifications."""
    prev_added_anc = glyph.xpath("//point[@name='parent_top']")
    if prev_added_anc:
        return True
    return False


def main(ufo_path):
    if not ufo_path.endswith('ufo'):
        raise Exception('{} is not a ufo'.format(ufo_path))
    glifs = glob(os.path.join(ufo_path, 'glyphs', '*.glif'))

    # check script has not already been run on this font
    a_glyph = etree.parse(os.path.join(ufo_path, 'glyphs', 'a.glif'))
    if _script_already_used(a_glyph):
        raise Exception('Script has already been used')

    for path in glifs:
        glyph = etree.parse(path)
        glyph_name = glyph.getroot().attrib['name']

        _delete_design_anchors(glyph)
        _rename_anchors(glyph)

        if glyph_name in ['cedilla', 'commaaccent', 'ogonek']:
            delete_anchor(glyph, 'bottom')

        if glyph_name in ['uni1ABB', 'uni1ABC']:
            delete_anchor(glyph, '_top')

        if glyph_name in DUPLICATE_ANCHOR_GLYPHS:
            duplicate_anchor(glyph, "top", "parent_top")
        glyph.write(path)

    print('Fixed anchors: {}'.format(ufo_path))


if __name__ == '__main__':
    if len(sys.argv) != 2:
        raise Exception("Include path to ufo")
    else:
        ufo_path = sys.argv[1]
        main(sys.argv[1])