#!/usr/bin/env python
#
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Noto-specific data about division of ranges between fonts.
"""

__author__ = "roozbeh@google.com (Roozbeh Pournader)"


CJK_RANGES_TXT = """
# Core
3400..4DBF; CJK Unified Ideographs Extension A
4E00..9FFF; CJK Unified Ideographs
F900..FAFF; CJK Compatibility Ideographs
20000..2A6DF; CJK Unified Ideographs Extension B
2A700..2B73F; CJK Unified Ideographs Extension C
2B740..2B81F; CJK Unified Ideographs Extension D
2F800..2FA1F; CJK Compatibility Ideographs Supplement
AC00..D7AF; Hangul Syllables
1100..11FF; Hangul Jamo
A960..A97F; Hangul Jamo Extended-A
D7B0..D7FF; Hangul Jamo Extended-B
3130..318F; Hangul Compatibility Jamo

3040..309F; Hiragana
1B000..1B0FF; Kana Supplement
30A0..30FF; Katakana
31F0..31FF; Katakana Phonetic Extensions

3100..312F; Bopomofo
31A0..31BF; Bopomofo Extended

# Others
3000..303F; CJK Symbols and Punctuation
3190..319F; Kanbun
31C0..31EF; CJK Strokes
3200..32FF; Enclosed CJK Letters and Months
FE10..FE1F; Vertical Forms
FE30..FE4F; CJK Compatibility Forms
FE50..FE6F; Small Form Variants
FF00..FFEF; Halfwidth and Fullwidth Forms

3300..33FF; CJK Compatibility
2FF0..2FFF; Ideographic Description Characters
2E80..2EFF; CJK Radicals Supplement
2F00..2FDF; Kangxi Radicals
"""

SYMBOL_RANGES_TXT = """
20A0..20CF; Currency Symbols
20D0..20FF; Combining Diacritical Marks for Symbols
2100..214F; Letterlike Symbols
2190..21FF; Arrows
2200..22FF; Mathematical Operators
2300..23FF; Miscellaneous Technical
2400..243F; Control Pictures
2440..245F; Optical Character Recognition
2460..24FF; Enclosed Alphanumerics
2500..257F; Box Drawing
2580..259F; Block Elements
25A0..25FF; Geometric Shapes
2600..26FF; Miscellaneous Symbols
2700..27BF; Dingbats
27C0..27EF; Miscellaneous Mathematical Symbols-A
27F0..27FF; Supplemental Arrows-A
2800..28FF; Braille Patterns
2900..297F; Supplemental Arrows-B
2980..29FF; Miscellaneous Mathematical Symbols-B
2A00..2AFF; Supplemental Mathematical Operators
2B00..2BFF; Miscellaneous Symbols and Arrows
2E00..2E7F; Supplemental Punctuation
4DC0..4DFF; Yijing Hexagram Symbols
A700..A71F; Modifier Tone Letters
FFF0..FFFF; Specials
10100..1013F; Aegean Numbers
10140..1018F; Ancient Greek Numbers
10190..101CF; Ancient Symbols
101D0..101FF; Phaistos Disc
1D000..1D0FF; Byzantine Musical Symbols
1D100..1D1FF; Musical Symbols
1D200..1D24F; Ancient Greek Musical Notation
1D300..1D35F; Tai Xuan Jing Symbols
1D360..1D37F; Counting Rod Numerals
1D400..1D7FF; Mathematical Alphanumeric Symbols
1F000..1F02F; Mahjong Tiles
1F030..1F09F; Domino Tiles
1F0A0..1F0FF; Playing Cards
1F100..1F1FF; Enclosed Alphanumeric Supplement
1F200..1F2FF; Enclosed Ideographic Supplement
1F700..1F77F; Alchemical Symbols
"""

UNDER_DEVELOPMENT_RANGES_TXT = """
0F00..0FFF; Tibetan
"""

DEEMED_UI_SCRIPTS_SET = frozenset(
    {
        "Armn",  # Armenian
        "Cher",  # Cherokee
        "Ethi",  # Ethiopic
        "Geor",  # Georgian
        "Hebr",  # Hebrew
        "Sinh",  # Sinhala
        "Zmth",  # Math
        "Zsye",  # Emoji
    }
)

# A mapping from scripts to ttfautohint script ids.
# Most of the keys correspond to scripts we hinted for phase 2.
# Additions are 'Cher' (which we didn't hint in phase 2), and
# 'Latn', 'Grek', and 'Cyrl' (which we combine into LGC and don't
# break out into seprate scripts).
# A few scripts hinted in phase 2 are not listed by ttfautohint as
# supported: 'Cham', 'Orya', 'Thaa', and 'Tibt'; these map to None.
#
# ttfautohint supports two version of Georgian identified by 'geor'
# and 'geok', we assume 'geor'.
HINTED_SCRIPTS = {
    "Arab": "arab",  # Arabic
    "Armn": "armn",  # Armenian
    "Beng": "beng",  # Bengali
    "Cham": None,  # Cham
    "Cher": "cher",  # Cherokee (not hinted in phase2)
    "Cyrl": "cyrl",  # Cyrillic (part of LGC)
    "Deva": "deva",  # Devanagari
    "Ethi": "ethi",  # Ethiopic
    "Geor": "geor",  # Georgian (Mkhedruli, not Khutsuri)
    "Grek": "grek",  # Greek (part of LGC)
    "Gujr": "gujr",  # Gujarati
    "Guru": "guru",  # Gurmukhi
    "Hebr": "hebr",  # Hebrew
    "Khmr": "khmr",  # Khmer
    "Knda": "knda",  # Kannada
    "LGC": "no-script",  # LGC, autohint but not to any particular script
    "Laoo": "lao",  # Lao (only one 'o' for ttfautohint)
    "Latn": "latn",  # Latin (part of LGC)
    "MONO": "no-script",  # MONO, autohint like lgc
    "Mlym": "mlym",  # Malayalam
    "Mymr": "mymr",  # Myanmar
    "Orya": None,  # Oriya
    "Sinh": "sinh",  # Sinhala
    "Taml": "taml",  # Tamil
    "Telu": "telu",  # Telugu
    "Thaa": None,  # Thaana
    "Thai": "thai",  # Thai
    "Tibt": None,  # Tibetan
}


# Range spec matches "Noto Nastaliq requirements" doc, Tier 1.
URDU_RANGES = """
    0600..0604,060b..0614,061b,061c,061e..061f,0620,0621..063a,
    0640..0659,065e..066d,0670..0673,0679,067a..067b,067c,067d,
    067e,067f..0680,0681,0683..0684,0685..0686,0687,0688..0689,
    068a,068b,068c..068d,068e,068f,0691,0693,0696,0698,0699,
    069a,069e,06a6,06a9,06ab,06af..06b0,06b1,06b3,06b7,06ba,
    06bb,06bc,06be,06c0..06c4,06cc..06cd,06d0,06d2..06d5,
    06dd..06de,06e9,06ee..06ef,06f0..06f9,06ff,0759,075c,0763,
    0767..0769,076b..077d,08ff,fbb2..fbc1,fd3e..fd3f,fdf2,
    fdfa..fdfd"""

# Only these two characters are required for Urdu from the Arabic
# extra characters needed.
URDU_EXTRA = "2010..2011"


def _char_set(compact_set_text):
    result = set()
    prev = -1
    for part in compact_set_text.split(","):
        sep_index = part.find("..")
        if sep_index == -1:
            cp = int(part, base=16)
            assert cp > prev
            # print('%04x' % cp)
            result.add(cp)
            prev = cp
        else:
            start = int(part[:sep_index], base=16)
            end = int(part[sep_index + 2 :], base=16)
            # print('%04x..%04x' % (start, end))
            assert start > prev
            assert end > start
            for cp in range(start, end + 1):
                result.add(cp)
            prev = end
    return result


def urdu_set():
    return _char_set(URDU_RANGES) | _char_set(URDU_EXTRA)


def ascii_letters():
    return _char_set("0041..005a,0061..007a")


def char_range(start, end):
    return list(range(start, end + 1))


COPTIC_EPACT = char_range(0x102E0, 0x102FB)
ARABIC_MATH = char_range(0x1EE00, 0x1EEF1)

P3_EXTRA_CHARACTERS_NEEDED = {
    # nothing additional outside block
    "Ahom": [],
    # According to Roozbeh (and existing fonts) the following punctuation and
    # digits are used with and interact with Arabic characters.
    "Arab": char_range(0x0030, 0x0039)
    + [
        # exclamation mark, comma, full stop, colon, NBS, guillimets
        0x0021,
        0x002C,
        0x002E,
        0x003A,
        0x00A0,
        0x00AB,
        0x00BB,
        0x06DD,  # Arabic end of Ayah
        0x2010,
        0x2011,  # Hyphen and non-breaking hyphen need different shapes
        0x204F,
        0x2E41,  # For Sindhi
        0xFD3E,
        0xFD3F,
    ],  # ornate left and right paren (in Noto Naskh)
    # like Arabic, but Sindi is not written in Nastaliq so omitted.
    "Aran": char_range(0x0030, 0x0039)
    + [
        # exclamation mark, comma, full stop, colon, NBS, guillimets
        0x0021,
        0x002C,
        0x002E,
        0x003A,
        0x00A0,
        0x00AB,
        0x00BB,
        0x06DD,  # Arabic end of Ayah
        0x2010,
        0x2011,  # Hyphen and non-breaking hyphen need different shapes
        0xFD3E,
        0xFE3F,
    ],  # ornate left and right paren (in Noto Naskh)
    # Characters referenced in Armenian encoding cross ref page as shown in
    # see http://www.unicode.org/L2/L2010/10354-n3924-armeternity.pdf
    # also see http://man7.org/linux/man-pages/man7/armscii-8.7.html
    # left and right paren, comma, hyphen-minus, period, section,
    # no break space, left and right guillimet, hyphen, em dash, ellipsis
    # presentation forms FB13-FB17
    "Armn": [
        0x0028,
        0x0029,
        0x002C,
        0x002D,
        0x002E,
        0x00A0,
        0x00A7,
        0x00AB,
        0x00BB,
        0x2010,
        0x2014,
        0x2026,
    ],
    "Avst": [
        0x2E30,
        0x2E31,  # From Core Specification and NamesList.txt
        0x200C,
    ],  # www.unicode.org/L2/L2007/07006r-n3197r-avestan.pdf
    # From http://www.unicode.org/L2/L2014/14064r-n4537r-cherokee.pdf section 8
    "Cher": [
        0x0300,
        0x0301,
        0x0302,
        0x0304,
        0x030B,
        0x030C,
        0x0323,
        0x0324,
        0x0330,
        0x0331,
    ],
    # From Core Specification:
    # period, colon, semicolon, middle dot
    # combining: grave, macron, overline, dot above, double overline
    # greek numeral sign, greek lower numeral sign, comb macrons (lh, rh, cj)
    # from http://std.dkuug.dk/JTC1/SC2/WG2/docs/n2636.pdf
    # oblique double hyphen, diaeresis, apostrophe, comb. circumflex, acute,
    # hyphen-minus, hyphen
    "Copt": [
        0x002E,
        0x003A,
        0x003B,
        0x00B7,
        0x0300,
        0x0304,
        0x0305,
        0x0307,
        0x033F,
        0x0374,
        0x0375,
        0xFE24,
        0xFE25,
        0xFE26,
        0x2E17,
        0x0308,
        0x2019,
        0x0302,
        0x0301,
        0x002D,
        0x2010,
    ],
    # Elbasan
    # see http://www.unicode.org/L2/L2011/11050-n3985-elbasan.pdf
    # adds combining overbar and greek numerals for ones and tens, and
    # both stigma/digamma for 6.
    # greek capital alpha beta gamma delta epsilon stigma/digamma zeta eta theta
    # iota kappa lambda mu nu xi omicron pi koppa
    "Elba": [
        0x00B7,
        0x0305,
        0x0391,
        0x0392,
        0x0393,
        0x0394,
        0x0395,
        0x03DA,
        0x03DD,
        0x0396,
        0x0397,
        0x0398,
        0x0399,
        0x039A,
        0x039B,
        0x039C,
        0x039D,
        0x039E,
        0x039F,
        0x03A0,
        0x03DE,
    ],
    # Ethiopic
    # See http://abyssiniagateway.net/fidel/l10n/
    # Recommends combining diaeresis 'for scholarly use', should look Ethiopian.
    # Also claims hyphen is not used, but a wikipedia page in Amharic does use
    # it, see
    # https://am.wikipedia.org/wiki/1_%E1%8A%A5%E1%88%BD%E1%88%98-%E1%8B%B3%E1%8C%8B%E1%8A%95
    # Western numerals and punctuation should look heavier to match the Ethiopic.
    # A keyboard standard is here:
    # See http://www.mcit.gov.et/documents/1268465/1282796/Keyboard+Layout+Standard/a8aa75ca-e125-4e25-872e-380e2a9b2313
    # digits
    # combining diaeresis (from abyssiniagateway site)
    # plus sign, comma, hyphen-minus, period, forward-slash
    # equals sign, question mark, left and right single and double curly quotes
    # left and right pointing double angle quotation marks, vertical three dot
    #   (plus sign to here all from keyboard doc)
    # exclamation point, left paren, right paren, ellipsis (web sites use them)
    # hyphen (used in hyphenated names in Amharaic, see wikipedia page)
    "Ethi": char_range(0x0030, 0x0039)
    + [
        0x0308,
        0x002B,
        0x002C,
        0x002D,
        0x002E,
        0x002F,
        0x003D,
        0x003F,
        0x2018,
        0x2019,
        0x201C,
        0x201D,
        0x00AB,
        0x00BB,
        0x22EE,
        0x0021,
        0x0028,
        0x0029,
        0x2026,
        0x2010,
    ],
    # Georgian
    # see example news article: http://www.civil.ge/geo/article.php?id=29970
    # ascii digits,
    # exclamation mark, percent, open/close paren, comma, hyphen-minus,
    # period, colon, semicolon, no break space (appears to be used in numbers)
    # em-dash, left double quotation mark, double low-9 quotation mark, ellipsis
    # see core standard:
    # middle dot, word separator middle dot, archaic punctuation (includes two
    # dot punctuation at 205A)
    "Geor": char_range(0x0030, 0x0039)
    + [
        0x0021,
        0x0025,
        0x0028,
        0x0029,
        0x002C,
        0x002D,
        0x002E,
        0x003A,
        0x003B,
        0x00A0,
        0x2014,
        0x201C,
        0x201E,
        0x2026,
        0x00B7,
        0x2E31,
    ]
    + char_range(0x2056, 0x205E)
    + char_range(0x2E2A, 0x2E2D),
    # Hatran
    # see http://www.unicode.org/L2/L2012/12312-n4324-hatran.pdf (most info, but
    # not latest assignment, which doesn't have all digits shown here)
    # single and double vertical line, also ZWNJ in case ligatures need breaking
    # might want to ligate hatran digit 1 forms 11 (2), 111 (3), 1111 (4) to
    # look as the suggested (dropped) digits were represented in the doc.
    "Hatr": [0x007C, 0x2016, 0x200C],
    # Anatolian Hieroglyphs
    # see http://www.unicode.org/L2/L2012/12213-n4282-anatolian.pdf
    "Hluw": [0x200B],
    # Old Hungarian
    # see  http://www.unicode.org/L2/L2012/12168r-n4268r-oldhungarian.pdf
    # letters with LTR override mirror reverse (!) "which has to be handled by
    # the rendering engine"
    # ZWJ, middle dot, two dot punctuation, tricolon, vertical four dots
    # plus 'standard European punctuation:'
    # exclamation, comma, hyphen-minus, period, colon,
    # double high-reversed-9 quote, reversed semicolon, reversed question mark,
    #   reversed comma, double low-reversed-9 quote,
    # hyphen (the official one)
    "Hung": [
        0x200D,
        0x2E31,
        0x205A,
        0x205D,
        0x205E,
        0x0021,
        0x002C,
        0x002D,
        0x002E,
        0x003A,
        0x201F,
        0x204F,
        0x2E2E,
        0x2E41,
        0x2E42,
        0x2010,
    ],
    # latin 1 and 2
    "LGC": char_range(0x20, 0x7E) + char_range(0xA0, 0xFF),
    "Lisu": [0x02BC, 0x02CD],  # From Core Specification
    # Meriotic Cursive
    # see http://www.unicode.org/L2/L2009/09188r-n3646-meroitic.pdf
    # colon, horizontal ellipsis, tricolon
    "Merc": [0x003A, 0x2026, 0x205D],
    # Multani
    # see http://www.unicode.org/L2/L2012/12316-multani.pdf
    # Digits unified with Gurmukhi, but 6 and 7 look like Devanagari, it says.
    # Glyphic variant of section mark 0x112A9, but how would we represent it...
    "Mult": char_range(0x0A66, 0x0A6F),
    # Sharada
    # see http://www.unicode.org/L2/L2009/09074-sharada.pdf
    # also see http://www.unicode.org/L2/L2015/15255-sharada-vocalic-vs.pdf
    # which requests a change in the representative glyphs of 111ba and 111bb
    # (below vowel signs)
    # Seems self-contained, no other punctuation.
    "Shrd": [],
    # Siddham
    # see http://www.unicode.org/L2/L2012/12234r-n4294-siddham.pdf
    # most use in Aast Asia
    "Sidd": [],
    # Sign Writing
    # As with music notation, we can't lay this out.  Generative glyphs for lots
    # of hand positions...
    "Sgnw": [],
    "Sylo": [0x2055],  # From Core Specification
    # From Core Specification
    "Syrc": [
        0x0303,
        0x0304,
        0x0307,
        0x0308,
        0x030A,
        0x0320,
        0x0323,
        0x0324,
        0x0325,
        0x032D,
        0x032E,
        0x0330,
        0x060C,
        0x061B,
        0x061F,
        0x0640,
    ]
    + char_range(0x064B, 0x0652),
    # From Core Specification & http://www.unicode.org/L2/L2001/01369-n2372.pdf
    "Tale": [0x0300, 0x0301, 0x0307, 0x0308, 0x030C],
    # From Core Specificaion and
    # http://www.unicode.org/L2/L2010/10407-ext-tamil-follow2.pdf
    "Taml": [0x00B2, 0x00B3, 0x2074, 0x2082, 0x2083, 0x2084],
    # From Core Specification and
    # http://www.unicode.org/L2/L2010/10451-patani-proposal.pdf
    "Thai": [0x02BC, 0x02D7, 0x0303, 0x0331],
    "Zmth": ARABIC_MATH,
    # Azerbaijani manat, Russian ruble, and Georgian Lari
    # Roozbeh says Coptic Epact doesn't belong in the Arabic fonts, though it's
    # used with Arabic.
    "Zsym": [0x20BC, 0x20BD, 0x20BE] + COPTIC_EPACT,
}

EXTRA_CHARACTERS_NEEDED = {
    "Arab": [
        0x2010,
        0x2011,  # Hyphen and non-breaking hyphen need different shapes
        0x204F,
        0x2E41,
    ],  # For Sindhi
    "Avst": [0x2E30, 0x2E31],  # From Core Specification and NamesList.txt
    # From http://www.unicode.org/L2/L2014/14064r-n4537r-cherokee.pdf section 8
    "Cher": [
        0x0300,
        0x0301,
        0x0302,
        0x0304,
        0x030B,
        0x030C,
        0x0323,
        0x0324,
        0x0330,
        0x0331,
    ],
    # From Core Specification
    "Copt": [
        0x0300,
        0x0304,
        0x0305,
        0x0307,
        0x033F,
        0x0374,
        0x0375,
        0xFE24,
        0xFE25,
        0xFE26,
    ],
    # latin 1 and 2
    "LGC": char_range(0x20, 0x7E) + char_range(0xA0, 0xFF),
    "Lisu": [0x02BC, 0x02CD],  # From Core Specification
    "Sylo": [0x2055],  # From Core Specification
    # From Core Specification
    "Syrc": [
        0x0303,
        0x0304,
        0x0307,
        0x0308,
        0x030A,
        0x0320,
        0x0323,
        0x0324,
        0x0325,
        0x032D,
        0x032E,
        0x0330,
        0x060C,
        0x061B,
        0x061F,
        0x0640,
    ]
    + char_range(0x064B, 0x0652),
    # From Core Specification & http://www.unicode.org/L2/L2001/01369-n2372.pdf
    "Tale": [0x0300, 0x0301, 0x0307, 0x0308, 0x030C],
    # From Core Specificaion and
    # http://www.unicode.org/L2/L2010/10407-ext-tamil-follow2.pdf
    "Taml": [0x00B2, 0x00B3, 0x2074, 0x2082, 0x2083, 0x2084],
    # From Core Specification and
    # http://www.unicode.org/L2/L2010/10451-patani-proposal.pdf
    "Thai": [0x02BC, 0x02D7, 0x0303, 0x0331],
    # Azerbaijani manat, Russian ruble, and Georgian Lari
    "Zsym": [0x20BC, 0x20BD, 0x20BE],
}

LGC_CHARACTERS_NOT_NEEDED = frozenset(
    char_range(0x0370, 0x0373)
    + [0x0376, 0x0377, 0x03CF, 0x0951, 0x0952, 0x1E9C, 0x1E9D, 0x1E9F]
    + char_range(0x1EFA, 0x1EFF)
    + [0x2071]
    + char_range(0x2095, 0x209C)
    + char_range(0x2160, 0x2183)
    + char_range(0x2185, 0x2188)
    + char_range(0x2C6E, 0x2C70)
    + char_range(0x2C78, 0x2C7F)
    + char_range(0x2DE0, 0x2DFF)
    + char_range(0xA640, 0xA673)
    + char_range(0xA67C, 0xA697)
    + char_range(0xA722, 0xA787)
    + [0xA78D, 0xA78E, 0xA790, 0xA791]
    + char_range(0xA7A0, 0xA7A9)
    + char_range(0xA7FA, 0xA7FF)
    + [0xA92E, 0xFB00, 0xFB05, 0xFB06]
)

P3_CHARACTERS_NOT_NEEDED = {
    "Arab": char_range(0x10E60, 0x10E7E) + COPTIC_EPACT + ARABIC_MATH,
    "Latn": LGC_CHARACTERS_NOT_NEEDED,
    "LGC": LGC_CHARACTERS_NOT_NEEDED,
}

CHARACTERS_NOT_NEEDED = {
    "Arab": char_range(0x10E60, 0x10E7E),
    "Latn": LGC_CHARACTERS_NOT_NEEDED,
    "LGC": LGC_CHARACTERS_NOT_NEEDED,
}

ACCEPTABLE_AS_COMBINING = {
    0x02DE,  # MODIFIER LETTER RHOTIC HOOK
}


def get_extra_characters_needed(script, phase):
    try:
        if phase == 2:
            return set(EXTRA_CHARACTERS_NEEDED[script])
        if phase == 3:
            return set(P3_EXTRA_CHARACTERS_NEEDED[script])
    except KeyError:
        pass
    return set()


def get_characters_not_needed(script, phase):
    try:
        if phase == 2:
            return set(CHARACTERS_NOT_NEEDED[script])
        if phase == 3:
            return set(P3_CHARACTERS_NOT_NEEDED[script])
    except KeyError:
        pass
    return set()
