"""A wrapper around the data provided by the ISO 10383 specification.

:copyright: (c) 2024 Tanner Corcoran
:license: Apache 2.0, see LICENSE for more details.

"""

__author__ = "Tanner Corcoran"
__license__ = "Apache 2.0 License"
__copyright__ = "Copyright (c) 2024 Tanner Corcoran"


import sys
import enum
import pathlib
import datetime
import dataclasses
from typing import (
    Any,
    BinaryIO,
    TypeVar,
    Union,
)
from collections.abc import Callable
if sys.version_info >= (3, 11):
    from typing import Self
else:
    from typing_extensions import Self


_T = TypeVar("_T")
_E = TypeVar("_E", bound=enum.Enum)


class MCC(enum.Enum):
    """Market Category Code (MCC)"""
    appa = 0
    atss = 1
    casp = 2
    dcms = 3
    idqs = 4
    mltf = 5
    nspd = 6
    otfs = 7
    othr = 8
    rmkt = 9
    rmos = 10
    sefs = 11
    sint = 12
    trfs = 13


class ISOCC(enum.Enum):
    """ISO Country Code"""
    ae = 0
    ag = 1
    al = 2
    am = 3
    ao = 4
    ar = 5
    at = 6
    au = 7
    az = 8
    ba = 9
    bb = 10
    bd = 11
    be = 12
    bg = 13
    bh = 14
    bm = 15
    bo = 16
    br = 17
    bs = 18
    bw = 19
    by = 20
    ca = 21
    ch = 22
    ci = 23
    cl = 24
    cm = 25
    cn = 26
    co = 27
    cr = 28
    cv = 29
    cw = 30
    cy = 31
    cz = 32
    de = 33
    dk = 34
    do = 35
    dz = 36
    ec = 37
    ee = 38
    eg = 39
    es = 40
    fi = 41
    fj = 42
    fo = 43
    fr = 44
    gb = 45
    ge = 46
    gg = 47
    gh = 48
    gi = 49
    gr = 50
    gt = 51
    gy = 52
    hk = 53
    hn = 54
    hr = 55
    hu = 56
    id = 57
    ie = 58
    il = 59
    in_ = 60
    iq = 61
    ir = 62
    is_ = 63
    it = 64
    jm = 65
    jo = 66
    jp = 67
    ke = 68
    kg = 69
    kh = 70
    kn = 71
    kr = 72
    kw = 73
    ky = 74
    kz = 75
    la = 76
    lb = 77
    li = 78
    lk = 79
    lt = 80
    lu = 81
    lv = 82
    ly = 83
    ma = 84
    md = 85
    me = 86
    mg = 87
    mk = 88
    mn = 89
    mt = 90
    mu = 91
    mv = 92
    mw = 93
    mx = 94
    my = 95
    mz = 96
    na = 97
    ng = 98
    ni = 99
    nl = 100
    no = 101
    np = 102
    nz = 103
    om = 104
    pa = 105
    pe = 106
    pg = 107
    ph = 108
    pk = 109
    pl = 110
    ps = 111
    pt = 112
    py = 113
    qa = 114
    ro = 115
    rs = 116
    ru = 117
    rw = 118
    sa = 119
    sc = 120
    sd = 121
    se = 122
    sg = 123
    si = 124
    sk = 125
    sv = 126
    sy = 127
    sz = 128
    th = 129
    tn = 130
    tr = 131
    tt = 132
    tw = 133
    tz = 134
    ua = 135
    ug = 136
    us = 137
    uy = 138
    uz = 139
    vc = 140
    ve = 141
    vn = 142
    vu = 143
    za = 144
    zm = 145
    zw = 146
    zz = 147


class _City(int):
    _name: str

    def __new__(cls, id: int, name: str) -> Self:
        inst = int.__new__(cls, id)
        inst._name = name
        return inst

    @property
    def name(self) -> str:
        return self._name


class City(enum.Enum):
    aabenraa                  = _City(0, "Aabenraa")
    aalborg                   = _City(1, "Aalborg")
    abidjan                   = _City(2, "Abidjan")
    abu_dhabi                 = _City(3, "Abu Dhabi")
    accra                     = _City(4, "Accra")
    ahmedabad                 = _City(5, "Ahmedabad")
    aichi                     = _City(6, "Aichi")
    alberta                   = _City(7, "Alberta")
    algiers                   = _City(8, "Algiers")
    almaty                    = _City(9, "Almaty")
    amman                     = _City(10, "Amman")
    amsterdam                 = _City(11, "Amsterdam")
    ankara                    = _City(12, "Ankara")
    antananarivo              = _City(13, "Antananarivo")
    antwerpen                 = _City(14, "Antwerpen")
    astana                    = _City(15, "Astana")
    asti                      = _City(16, "Asti")
    asuncion                  = _City(17, "Asuncion")
    athens                    = _City(18, "Athens")
    atlanta                   = _City(19, "Atlanta")
    auckland                  = _City(20, "Auckland")
    aylesbury                 = _City(21, "Aylesbury")
    baghdad                   = _City(22, "Baghdad")
    baku                      = _City(23, "Baku")
    bangalore                 = _City(24, "Bangalore")
    bangkok                   = _City(25, "Bangkok")
    banja_luka                = _City(26, "Banja Luka")
    barcelona                 = _City(27, "Barcelona")
    basseterre                = _City(28, "Basseterre")
    bedminster                = _City(29, "Bedminster")
    beijing                   = _City(30, "Beijing")
    beirut                    = _City(31, "Beirut")
    belgrade                  = _City(32, "Belgrade")
    bergamo                   = _City(33, "Bergamo")
    bergen                    = _City(34, "Bergen")
    berlin                    = _City(35, "Berlin")
    bermuda                   = _City(36, "Bermuda")
    berne                     = _City(37, "Berne")
    biella                    = _City(38, "Biella")
    bilbao                    = _City(39, "Bilbao")
    bishkek                   = _City(40, "Bishkek")
    blantyre                  = _City(41, "Blantyre")
    boca_raton                = _City(42, "Boca Raton")
    bogota                    = _City(43, "Bogota")
    bologna                   = _City(44, "Bologna")
    boston                    = _City(45, "Boston")
    bradford                  = _City(46, "Bradford")
    bratislava                = _City(47, "Bratislava")
    bremen                    = _City(48, "Bremen")
    bridgetown                = _City(49, "Bridgetown")
    brussels                  = _City(50, "Brussels")
    bryanston_sandton         = _City(51, "Bryanston - Sandton")
    bucharest                 = _City(52, "Bucharest")
    budaors                   = _City(53, "Budaors")
    budapest                  = _City(54, "Budapest")
    buenos_aires              = _City(55, "Buenos Aires")
    cairo                     = _City(56, "Cairo")
    calcutta                  = _City(57, "Calcutta")
    calgary                   = _City(58, "Calgary")
    caracas                   = _City(59, "Caracas")
    casablanca                = _City(60, "Casablanca")
    charlotte                 = _City(61, "Charlotte")
    chatham                   = _City(62, "Chatham")
    chicago                   = _City(63, "Chicago")
    chisinau                  = _City(64, "Chisinau")
    chittagong                = _City(65, "Chittagong")
    chiyoda_ku                = _City(66, "Chiyoda-Ku")
    cluj_napoca               = _City(67, "Cluj Napoca")
    colombo                   = _City(68, "Colombo")
    copenhagen                = _City(69, "Copenhagen")
    cordoba                   = _City(70, "Cordoba")
    corrientes                = _City(71, "Corrientes")
    curitiba                  = _City(72, "Curitiba")
    cybercity_ebene           = _City(73, "Cybercity, Ebene")
    dalian                    = _City(74, "Dalian")
    damascus                  = _City(75, "Damascus")
    dar_es_salaam             = _City(76, "Dar Es Salaam")
    delhi                     = _City(77, "Delhi")
    dhaka                     = _City(78, "Dhaka")
    dnipropetrovsk            = _City(79, "Dnipropetrovsk")
    doha                      = _City(80, "Doha")
    douala                    = _City(81, "Douala")
    dubai                     = _City(82, "Dubai")
    dublin                    = _City(83, "Dublin")
    duesseldorf               = _City(84, "Duesseldorf")
    ebene                     = _City(85, "Ebene")
    ebene_city                = _City(86, "Ebene City")
    eden_island               = _City(87, "Eden Island")
    edinburgh                 = _City(88, "Edinburgh")
    ekaterinburg              = _City(89, "Ekaterinburg")
    el_salvador               = _City(90, "El Salvador")
    esch_sur_alzette          = _City(91, "Esch-Sur-Alzette")
    eschborn                  = _City(92, "Eschborn")
    espirito_santo            = _City(93, "Espirito Santo")
    espoo                     = _City(94, "Espoo")
    fiac                      = _City(95, "Fiac")
    firenze                   = _City(96, "Firenze")
    florence                  = _City(97, "Florence")
    frankfurt                 = _City(98, "Frankfurt")
    frankfurt_am_main         = _City(99, "Frankfurt Am Main")
    fukuoka                   = _City(100, "Fukuoka")
    gaborone                  = _City(101, "Gaborone")
    gandhinagar               = _City(102, "Gandhinagar")
    geneva                    = _City(103, "Geneva")
    genova                    = _City(104, "Genova")
    georgetown                = _City(105, "Georgetown")
    gibraltar                 = _City(106, "Gibraltar")
    gift_city_gandhinagar     = _City(107, "Gift City, Gandhinagar")
    glenview                  = _City(108, "Glenview")
    great_neck                = _City(109, "Great Neck")
    greenwich                 = _City(110, "Greenwich")
    grindsted                 = _City(111, "Grindsted")
    guatemala                 = _City(112, "Guatemala")
    guayaquil                 = _City(113, "Guayaquil")
    guaynabo                  = _City(114, "Guaynabo")
    guildford                 = _City(115, "Guildford")
    hamburg                   = _City(116, "Hamburg")
    hamilton                  = _City(117, "Hamilton")
    hannover                  = _City(118, "Hannover")
    hanoi                     = _City(119, "Hanoi")
    harare                    = _City(120, "Harare")
    helsinki                  = _City(121, "Helsinki")
    hiroshima                 = _City(122, "Hiroshima")
    ho_chi_minh_city          = _City(123, "Ho Chi Minh City")
    hong_kong                 = _City(124, "Hong Kong")
    horsens                   = _City(125, "Horsens")
    hove                      = _City(126, "Hove")
    illinois                  = _City(127, "Illinois")
    indore_madhya_pradesh     = _City(128, "Indore Madhya Pradesh")
    islamabad                 = _City(129, "Islamabad")
    istanbul                  = _City(130, "Istanbul")
    izmir                     = _City(131, "Izmir")
    jaen                      = _City(132, "Jaen")
    jakarta                   = _City(133, "Jakarta")
    jersey_city               = _City(134, "Jersey City")
    johannesburg              = _City(135, "Johannesburg")
    kampala                   = _City(136, "Kampala")
    kansas_city               = _City(137, "Kansas City")
    karachi                   = _City(138, "Karachi")
    kathmandu                 = _City(139, "Kathmandu")
    kharkov                   = _City(140, "Kharkov")
    khartoum                  = _City(141, "Khartoum")
    kiel                      = _City(142, "Kiel")
    kiev                      = _City(143, "Kiev")
    kigali                    = _City(144, "Kigali")
    kingston                  = _City(145, "Kingston")
    kingstown                 = _City(146, "Kingstown")
    klagenfurt_am_woerthersee = _City(147, "Klagenfurt Am Woerthersee")
    kobe                      = _City(148, "Kobe")
    kongsvinger               = _City(149, "Kongsvinger")
    krakow                    = _City(150, "Krakow")
    kuala_lumpur              = _City(151, "Kuala Lumpur")
    kuwait                    = _City(152, "Kuwait")
    kyoto                     = _City(153, "Kyoto")
    la_paz                    = _City(154, "La Paz")
    labuan                    = _City(155, "Labuan")
    lagos                     = _City(156, "Lagos")
    lahore                    = _City(157, "Lahore")
    lane_cove                 = _City(158, "Lane Cove")
    lao                       = _City(159, "Lao")
    larnaca                   = _City(160, "Larnaca")
    leipzig                   = _City(161, "Leipzig")
    lenexa                    = _City(162, "Lenexa")
    leuven                    = _City(163, "Leuven")
    lima                      = _City(164, "Lima")
    limassol                  = _City(165, "Limassol")
    linz                      = _City(166, "Linz")
    lisbon                    = _City(167, "Lisbon")
    ljubljana                 = _City(168, "Ljubljana")
    london                    = _City(169, "London")
    los_angeles               = _City(170, "Los Angeles")
    luanda                    = _City(171, "Luanda")
    lusaka                    = _City(172, "Lusaka")
    luxembourg                = _City(173, "Luxembourg")
    luzern                    = _City(174, "Luzern")
    madras                    = _City(175, "Madras")
    madrid                    = _City(176, "Madrid")
    makati_city               = _City(177, "Makati City")
    male                      = _City(178, "Male")
    managua                   = _City(179, "Managua")
    manama                    = _City(180, "Manama")
    manila                    = _City(181, "Manila")
    maputo                    = _City(182, "Maputo")
    maringa                   = _City(183, "Maringa")
    mbabane                   = _City(184, "Mbabane")
    melbourne                 = _City(185, "Melbourne")
    mendoza                   = _City(186, "Mendoza")
    mexico                    = _City(187, "Mexico")
    miami                     = _City(188, "Miami")
    milan                     = _City(189, "Milan")
    minneapolis               = _City(190, "Minneapolis")
    minsk                     = _City(191, "Minsk")
    montevideo                = _City(192, "Montevideo")
    montreal                  = _City(193, "Montreal")
    moorpark                  = _City(194, "Moorpark")
    moscow                    = _City(195, "Moscow")
    mount_pleasant            = _City(196, "Mount Pleasant")
    muenchen                  = _City(197, "Muenchen")
    mumbai                    = _City(198, "Mumbai")
    munich                    = _City(199, "Munich")
    muscat                    = _City(200, "Muscat")
    nablus                    = _City(201, "Nablus")
    nacka                     = _City(202, "Nacka")
    nagoya                    = _City(203, "Nagoya")
    nairobi                   = _City(204, "Nairobi")
    narberth                  = _City(205, "Narberth")
    nasau                     = _City(206, "Nasau")
    new_jersey                = _City(207, "New Jersey")
    new_york                  = _City(208, "New York")
    new_york_ny               = _City(209, "New York, Ny")
    newcastle                 = _City(210, "Newcastle")
    nicosia                   = _City(211, "Nicosia")
    nicosia_lefkosia          = _City(212, "Nicosia (Lefkosia)")
    nigita                    = _City(213, "Nigita")
    nizhniy_novgorod          = _City(214, "Nizhniy Novgorod")
    north_bergen              = _City(215, "North Bergen")
    not_applicable            = _City(216, "Not Applicable")
    novosibirsk               = _City(217, "Novosibirsk")
    nyon                      = _City(218, "Nyon")
    odessa                    = _City(219, "Odessa")
    oldenburg                 = _City(220, "Oldenburg")
    osaka                     = _City(221, "Osaka")
    oslo                      = _City(222, "Oslo")
    oststeinbek               = _City(223, "Oststeinbek")
    padova                    = _City(224, "Padova")
    palma_de_mallorca         = _City(225, "Palma De Mallorca")
    panama                    = _City(226, "Panama")
    paris                     = _City(227, "Paris")
    pasig_city                = _City(228, "Pasig City")
    philadelphia              = _City(229, "Philadelphia")
    phnom_penh                = _City(230, "Phnom Penh")
    phoenix                   = _City(231, "Phoenix")
    podgorica                 = _City(232, "Podgorica")
    polokwane                 = _City(233, "Polokwane")
    port_louis                = _City(234, "Port Louis")
    port_moresby              = _City(235, "Port Moresby")
    port_of_spain             = _City(236, "Port Of Spain")
    port_vila                 = _City(237, "Port Vila")
    porto                     = _City(238, "Porto")
    prague                    = _City(239, "Prague")
    praia                     = _City(240, "Praia")
    princeton                 = _City(241, "Princeton")
    purchase                  = _City(242, "Purchase")
    quito                     = _City(243, "Quito")
    randers                   = _City(244, "Randers")
    red_bank                  = _City(245, "Red Bank")
    regensburg                = _City(246, "Regensburg")
    reggio_emilia             = _City(247, "Reggio Emilia")
    reykjavik                 = _City(248, "Reykjavik")
    riga                      = _City(249, "Riga")
    rio_de_janeiro            = _City(250, "Rio De Janeiro")
    riyadh                    = _City(251, "Riyadh")
    rodgau                    = _City(252, "Rodgau")
    rome                      = _City(253, "Rome")
    rosario                   = _City(254, "Rosario")
    rostov                    = _City(255, "Rostov")
    s_hertogenbosch           = _City(256, "S-Hertogenbosch")
    sabadell                  = _City(257, "Sabadell")
    saint_petersburg          = _City(258, "Saint-Petersburg")
    salzburg                  = _City(259, "Salzburg")
    samara                    = _City(260, "Samara")
    san_carlos                = _City(261, "San Carlos")
    san_francisco             = _City(262, "San Francisco")
    san_jose                  = _City(263, "San Jose")
    san_pedro_sula            = _City(264, "San Pedro Sula")
    santa_fe                  = _City(265, "Santa Fe")
    santander                 = _City(266, "Santander")
    santiago                  = _City(267, "Santiago")
    santo_domingo             = _City(268, "Santo Domingo")
    sao_paulo                 = _City(269, "Sao Paulo")
    sapporo                   = _City(270, "Sapporo")
    sarajevo                  = _City(271, "Sarajevo")
    schwerin                  = _City(272, "Schwerin")
    sea_girt                  = _City(273, "Sea Girt")
    seoul                     = _City(274, "Seoul")
    shanghai                  = _City(275, "Shanghai")
    shenzhen                  = _City(276, "Shenzhen")
    shimonoseki               = _City(277, "Shimonoseki")
    sibiu                     = _City(278, "Sibiu")
    silkeborg                 = _City(279, "Silkeborg")
    singapore                 = _City(280, "Singapore")
    skopje                    = _City(281, "Skopje")
    sliema                    = _City(282, "Sliema")
    sofia                     = _City(283, "Sofia")
    split                     = _City(284, "Split")
    st_albans                 = _City(285, "St Albans")
    st_john                   = _City(286, "St John")
    st_peter_port             = _City(287, "St. Peter Port")
    stamford                  = _City(288, "Stamford")
    stockholm                 = _City(289, "Stockholm")
    stuttgart                 = _City(290, "Stuttgart")
    surabaya                  = _City(291, "Surabaya")
    suva                      = _City(292, "Suva")
    sydney                    = _City(293, "Sydney")
    taipei                    = _City(294, "Taipei")
    taiwan                    = _City(295, "Taiwan")
    tallinn                   = _City(296, "Tallinn")
    tashkent                  = _City(297, "Tashkent")
    tbilisi                   = _City(298, "Tbilisi")
    tegucigalpa               = _City(299, "Tegucigalpa")
    tehran                    = _City(300, "Tehran")
    tel_aviv                  = _City(301, "Tel Aviv")
    the_hague                 = _City(302, "The Hague")
    the_woodlands             = _City(303, "The Woodlands")
    tirana                    = _City(304, "Tirana")
    tokyo                     = _City(305, "Tokyo")
    torino                    = _City(306, "Torino")
    toronto                   = _City(307, "Toronto")
    torshavn                  = _City(308, "Torshavn")
    tripoli                   = _City(309, "Tripoli")
    tromso                    = _City(310, "Tromso")
    trondheim                 = _City(311, "Trondheim")
    tucuman                   = _City(312, "Tucuman")
    tunis                     = _City(313, "Tunis")
    ulaan_baatar              = _City(314, "Ulaan Baatar")
    unterschleisshem          = _City(315, "Unterschleisshem")
    utrecht                   = _City(316, "Utrecht")
    vaduz                     = _City(317, "Vaduz")
    valencia                  = _City(318, "Valencia")
    valletta                  = _City(319, "Valletta")
    valparaiso                = _City(320, "Valparaiso")
    vancouver                 = _City(321, "Vancouver")
    varazdin                  = _City(322, "Varazdin")
    victoria                  = _City(323, "Victoria")
    victoria_falls            = _City(324, "Victoria Falls")
    vienna                    = _City(325, "Vienna")
    vila                      = _City(326, "Vila")
    vilnius                   = _City(327, "Vilnius")
    vladivostok               = _City(328, "Vladivostok")
    warsaw                    = _City(329, "Warsaw")
    washington                = _City(330, "Washington")
    washington_new_york       = _City(331, "Washington/New York")
    willemstad                = _City(332, "Willemstad")
    wilmington                = _City(333, "Wilmington")
    windhoek                  = _City(334, "Windhoek")
    winnipeg                  = _City(335, "Winnipeg")
    winter_park               = _City(336, "Winter Park")
    wroclaw                   = _City(337, "Wroclaw")
    wuxi                      = _City(338, "Wuxi")
    yerevan                   = _City(339, "Yerevan")
    zagreb                    = _City(340, "Zagreb")
    zaragoza                  = _City(341, "Zaragoza")
    zhengzhou                 = _City(342, "Zhengzhou")
    zilina                    = _City(343, "Zilina")
    zurich                    = _City(344, "Zurich")

    # added after initial package release
    milton_keynes             = _City(345, "Milton Keynes")
    hradec_kralove            = _City(346, "Hradec Kralove")

    value: _City

    def __new__(cls, value: _City) -> Self:
        member = object.__new__(cls)
        member._value_ = value

        if int(value) in cls._value2member_map_:
            raise ValueError(f"Duplicate value: {value!r}")
        if value.name in cls._value2member_map_:
            raise ValueError(f"Duplicate value: {value.name!r}")
        
        cls._value2member_map_[value] = member
        cls._value2member_map_[value.name] = member

        return member


class Status(enum.Enum):
    active = 0
    expired = 1
    updated = 2


@dataclasses.dataclass(frozen=True)
class MICEntry:
    """Represents a single MIC entry"""
    mic: str
    market_name: str
    market_category_code: MCC
    creation_date: datetime.date
    status: Status
    city: Union[City, None] = None
    operating_mic: Union["MICEntry", None] = None
    institution_description: Union[str, None] = None
    legel_entity_name: Union[str, None] = None
    legal_entity_identifier: Union[str, None] = None
    acronym: Union[str, None] = None
    iso_country_code: Union[ISOCC, None] = None
    website: Union[str, None] = None
    last_update_date: Union[datetime.date, None] = None
    last_validation_date: Union[datetime.date, None] = None
    expiry_date: Union[datetime.date, None] = None
    comments: Union[str, None] = None


class MIC(enum.Enum):
    value: MICEntry
    drsp = None
    xcnq = None
    pure = None
    zodm = None
    norx = None
    pose = None
    pund = None
    ucbg = None
    xoch = None
    bblx = None
    spbe = None
    otcm = None
    frex = None
    idxm = None
    mbcp = None
    ocea = None
    osds = None
    ossg = None
    rr4g = None
    truk = None
    ugen = None
    cnod = None
    bglu = None
    gfam = None
    tmcy = None
    ubec = None
    eslo = None
    iotf = None
    seba = None
    ubim = None
    xubs = None
    xump = None
    amlg = None
    bred = None
    dbix = None
    rusx = None
    ungb = None
    xlqc = None
    xmos = None
    cfic = None
    hbfr = None
    klsh = None
    mudx = None
    trax = None
    trnl = None
    xpet = None
    levl = None
    ebxv = None
    strm = None
    abnc = None
    bnpc = None
    pbgr = None
    sidx = None
    sifx = None
    teur = None
    ailt = None
    arax = None
    cgxs = None
    midc = None
    rabl = None
    rmms = None
    rmmx = None
    ceca = None
    dbdc = None
    dbse = None
    dbcx = None
    dbcr = None
    jnsi = None
    xswx = None
    xdlp = None
    xswm = None
    xsls = None
    xseb = None
    xbtr = None
    xvtx = None
    xqod = None
    xqmh = None
    bnpx = None
    btrl = None
    ntuk = None
    eqos = None
    lmnr = None
    eqca = None
    equs = None
    evol = None
    stee = None
    bulk = None
    rbcc = None
    bebg = None
    xtxd = None
    sswm = None
    xosl = None
    merk = None
    xobd = None
    bsab = None
    bspl = None
    bstx = None
    xnom = None
    olbb = None
    sgmu = None
    afex = None
    bnpl = None
    capl = None
    ccmx = None
    msbi = None
    sgmv = None
    sgmw = None
    t212 = None
    tmex = None
    xcbo = None
    cone = None
    ctwo = None
    c2ox = None
    xpom = None
    clst = None
    llat = None
    immh = None
    aqse = None
    enms = None
    fast = None
    ilcm = None
    lele = None
    mcxx = None
    pepw = None
    wflb = None
    wfse = None
    nbfl = None
    nexx = None
    nexg = None
    nexl = None
    nexd = None
    maxd = None
    btbs = None
    axsi = None
    skbb = None
    bdsk = None
    dexe = None
    otpr = None
    sbij = None
    xotp = None
    xbvm = None
    maqe = None
    memx = None
    park = None
    pipr = None
    skyx = None
    glom = None
    trai = None
    cboe = None
    cohr = None
    stfu = None
    stfx = None
    xicb = None
    xlch = None
    clch = None
    buyn = None
    atdf = None
    bghx = None
    csas = None
    ltse = None
    xfex = None
    calh = None
    omip = None
    xlis = None
    dauk = None
    bslb = None
    cfil = None
    rbcm = None
    thre = None
    weed = None
    xwee = None
    bkkt = None
    iuob = None
    xpus = None
    bmli = None
    bmlx = None
    itgl = None
    xamm = None
    amnl = None
    vfgb = None
    vfuk = None
    sebl = None
    viuk = None
    _24ex = None
    bbsx = None
    jlsi = None
    scot = None
    spex = None
    ifad = None
    jlqd = None
    lamp = None
    rcma = None
    eris = None
    mktf = None
    xsgb = None
    ykna = None
    csda = None
    dowm = None
    gsxc = None
    gsxk = None
    gsxt = None
    vagm = None
    bmcm = None
    ewsm = None
    gxgr = None
    gxgm = None
    gxgf = None
    abfi = None
    dash = None
    misx = None
    bajd = None
    neoe = None
    neod = None
    neon = None
    neoc = None
    trpx = None
    kome = None
    trcx = None
    erbx = None
    iber = None
    allt = None
    bilu = None
    cbsk = None
    coda = None
    pdqx = None
    smbd = None
    stfl = None
    xalt = None
    sage = None
    arch = None
    expm = None
    jpms = None
    snuk = None
    arkx = None
    svxi = None
    xals = None
    cgmg = None
    puma = None
    _4axe = None
    ebhu = None
    euch = None
    eurm = None
    eusc = None
    fnuk = None
    uchu = None
    cbnl = None
    ftus = None
    bguk = None
    clve = None
    cpgx = None
    cepl = None
    cepu = None
    dbab = None
    otcn = None
    rtsl = None
    tral = None
    tdgf = None
    ubsb = None
    ubsd = None
    ubsl = None
    bfpt = None
    conc = None
    ifbx = None
    scxo = None
    scxm = None
    syfx = None
    ssil = None
    manl = None
    betx = None
    btlx = None
    ccex = None
    aqeu = None
    aqea = None
    aqxe = None
    bkdm = None
    bnld = None
    cavd = None
    gipb = None
    gspx = None
    icpm = None
    imgi = None
    imrd = None
    imet = None
    imgb = None
    immm = None
    imfd = None
    imce = None
    imed = None
    jleu = None
    smff = None
    sptr = None
    elxe = None
    scag = None
    sgas = None
    smfe = None
    trxe = None
    mhbe = None
    csgi = None
    eucc = None
    brea = None
    xtxe = None
    blue = None
    btam = None
    cabv = None
    rfbk = None
    towr = None
    bpas = None
    flwx = None
    blux = None
    dblx = None
    dhlx = None
    khhu = None
    mcid = None
    ncme = None
    ipnl = None
    iswp = None
    iswn = None
    iswt = None
    msel = None
    ncml = None
    xpuk = None
    csag = None
    gsbe = None
    hreu = None
    stsi = None
    crem = None
    dwfi = None
    bnpp = None
    cibh = None
    csmd = None
    simd = None
    gmes = None
    gmeo = None
    kbll = None
    mhbp = None
    mheu = None
    ubcz = None
    atln = None
    lbcw = None
    agbp = None
    ebsn = None
    eceu = None
    tpic = None
    xtrd = None
    mlex = None
    mler = None
    mles = None
    mlib = None
    athl = None
    bcsc = None
    cfif = None
    jefe = None
    mhbl = None
    nowx = None
    pkop = None
    vusa = None
    vfmi = None
    aban = None
    eqie = None
    eqld = None
    gpbc = None
    rtsx = None
    ohvo = None
    rbcg = None
    rmtf = None
    ucba = None
    ucde = None
    ucit = None
    brga = None
    xnor = None
    bcma = None
    csob = None
    icur = None
    ifxc = None
    ifxa = None
    ifxr = None
    musn = None
    spdx = None
    nibc = None
    uice = None
    xndu = None
    ecsl = None
    msax = None
    msnt = None
    mseu = None
    tpis = None
    brde = None
    cibc = None
    cibp = None
    ftfs = None
    cabk = None
    ccrm = None
    ccxe = None
    deka = None
    icot = None
    issi = None
    jysi = None
    nwnv = None
    otpb = None
    rbhu = None
    renc = None
    tpeu = None
    wsil = None
    ingw = None
    makx = None
    wsin = None
    slhb = None
    sibc = None
    weln = None
    bmlb = None
    welx = None
    xsat = None
    baip = None
    baep = None
    davy = None
    imcm = None
    imcd = None
    liga = None
    mbpl = None
    tpfr = None
    tepi = None
    tpmf = None
    tpsy = None
    wels = None
    cbal = None
    scxa = None
    siab = None
    bksk = None
    cmci = None
    mhbd = None
    csot = None
    muse = None
    nabe = None
    abna = None
    bbie = None
    erst = None
    ikbs = None
    tqex = None
    tqeb = None
    tqem = None
    tqea = None
    apaw = None
    nabl = None
    obkl = None
    twjp = None
    hrtf = None
    smbb = None
    cgmd = None
    hemo = None
    imct = None
    metz = None
    mibl = None
    mubl = None
    mubm = None
    mubp = None
    rbiv = None
    smbg = None
    mube = None
    jpeu = None
    smbe = None
    smbp = None
    leue = None
    leuf = None
    hela = None
    nesi = None
    bhwa = None
    isba = None
    isbv = None
    kbcb = None
    maqi = None
    maqu = None
    fico = None
    lbbw = None
    lbwl = None
    lbws = None
    nuro = None
    xnlx = None
    nurd = None
    tpmg = None
    edga = None
    edgd = None
    edgo = None
    edgx = None
    bats = None
    baty = None
    byxd = None
    bzxd = None
    eddp = None
    bato = None
    bape = None
    base = None
    bcee = None
    bpko = None
    btfe = None
    hrsi = None
    r5fx = None
    sisi = None
    beis = None
    blbb = None
    basx = None
    hrtx = None
    icas = None
    incr = None
    iofb = None
    ocsi = None
    edrf = None
    bnsx = None
    exse = None
    tplf = None
    aixk = None
    lbcm = None
    rlbo = None
    sbex = None
    vtbc = None
    zarx = None
    ipsx = None
    tpde = None
    tsfg = None
    tsff = None
    comm = None
    atlb = None
    ccms = None
    daiw = None
    iinx = None
    opco = None
    tsbx = None
    tmxs = None
    belb = None
    imtf = None
    magm = None
    blxa = None
    gfks = None
    sgoe = None
    ubsa = None
    ubss = None
    ibis = None
    pdqd = None
    tfsd = None
    tras = None
    tsig = None
    utsl = None
    bmfx = None
    cszh = None
    stal = None
    xijp = None
    euwa = None
    exsy = None
    a2xx = None
    fxop = None
    trde = None
    nave = None
    akis = None
    bpsx = None
    igdl = None
    jssi = None
    sebx = None
    twgp = None
    gmgd = None
    gmgl = None
    npex = None
    oapa = None
    ddtx = None
    hpcx = None
    sb1m = None
    sedr = None
    ants = None
    ieng = None
    sgmx = None
    ssbi = None
    dbag = None
    mkap = None
    gsal = None
    gsxh = None
    sigh = None
    swee = None
    swlt = None
    swlv = None
    oddo = None
    odoc = None
    pulx = None
    sant = None
    ubin = None
    cslb = None
    jisi = None
    jefs = None
    vwdx = None
    vtls = None
    bamx = None
    sebs = None
    xabc = None
    gfic = None
    kelr = None
    mlxn = None
    mlax = None
    xbox = None
    nord = None
    otxb = None
    semx = None
    aaca = None
    absi = None
    binv = None
    glmx = None
    gtxe = None
    jpcb = None
    nlbx = None
    rosr = None
    xrot = None
    xllb = None
    xvpb = None
    hbpl = None
    xabg = None
    alsi = None
    sbsi = None
    tdbl = None
    bnpa = None
    bnpf = None
    bnps = None
    iceo = None
    iofi = None
    iofx = None
    iogb = None
    iocd = None
    ioed = None
    iogi = None
    ioir = None
    iomm = None
    iswa = None
    nwms = None
    rbce = None
    xsga = None
    kblm = None
    kotf = None
    lasp = None
    tdon = None
    tsaf = None
    ubis = None
    xiel = None
    xoaa = None
    bana = None
    boal = None
    csec = None
    mlix = None
    mlrq = None
    svex = None
    sves = None
    aapa = None
    cimd = None
    curx = None
    sksi = None
    squa = None
    ssbt = None
    ssfx = None
    afsa = None
    afsi = None
    aria = None
    dvfx = None
    etpa = None
    loui = None
    rabo = None
    bbva = None
    btnl = None
    capi = None
    xrcb = None
    apex = None
    tgat = None
    xgrm = None
    nysi = None
    xmal = None
    casi = None
    cnsi = None
    xosa = None
    cceu = None
    xtxm = None
    gfsm = None
    gfso = None
    aurb = None
    iswr = None
    iswc = None
    iswb = None
    vagl = None
    bcsl = None
    bcsi = None
    gfib = None
    gfif = None
    gfin = None
    gfir = None
    ingb = None
    sfcl = None
    sunb = None
    tpsl = None
    tsmr = None
    vont = None
    bkbr = None
    bkbf = None
    cbka = None
    tpes = None
    tpso = None
    cbkd = None
    cbkf = None
    cbke = None
    cbkg = None
    cgml = None
    cptx = None
    maql = None
    dzbk = None
    xpos = None
    tpel = None
    tefd = None
    temf = None
    temi = None
    tird = None
    temb = None
    temr = None
    tpeo = None
    tegb = None
    tomg = None
    tepf = None
    twhk = None
    twjt = None
    twsg = None
    wood = None
    xrfq = None
    xpac = None
    loyd = None
    scxf = None
    bofs = None
    sunt = None
    swbi = None
    wbkp = None
    bgsi = None
    bplc = None
    bbsi = None
    lssi = None
    biva = None
    bkln = None
    bklf = None
    fisu = None
    jbsi = None
    napa = None
    potc = None
    ppex = None
    baad = None
    inve = None
    emch = None
    vola = None
    xdnb = None
    ifls = None
    exot = None
    hsxe = None
    anzl = None
    echo = None
    fbsi = None
    hsbc = None
    hsbt = None
    natx = None
    stan = None
    vcmo = None
    advt = None
    csin = None
    cssi = None
    dowg = None
    ampx = None
    fxgb = None
    tomx = None
    trsi = None
    btee = None
    ebsm = None
    ebss = None
    rbcb = None
    rbct = None
    gsib = None
    bisi = None
    hudx = None
    imcs = None
    ubsy = None
    xdub = None
    xatl = None
    bilt = None
    mufp = None
    vfil = None
    vfsi = None
    vfxo = None
    ccml = None
    cftw = None
    dapa = None
    vlex = None
    _3579 = None
    mhip = None
    wins = None
    winx = None
    enxl = None
    alxl = None
    masg = None
    tcml = None
    frte = None
    them = None
    ledg = None
    muti = None
    ndcm = None
    ndex = None
    spec = None
    bcrm = None
    bark = None
    mtus = None
    gotc = None
    mfxc = None
    mfxr = None
    mfxa = None
    snsi = None
    vert = None
    apxl = None
    cltd = None
    drct = None
    mtxx = None
    cave = None
    otcb = None
    pinl = None
    pini = None
    pinx = None
    otcq = None
    psgm = None
    pinc = None
    xeee = None
    mtso = None
    mtsc = None
    eluk = None
    elno = None
    _else = None
    eleu = None
    frei = None
    nosi = None
    xbdv = None
    difx = None
    autx = None
    autp = None
    nexs = None
    virt = None
    balt = None
    bltx = None
    cgma = None
    cgmh = None
    cgmi = None
    lqfi = None
    cgmx = None
    citx = None
    citd = None
    lqed = None
    mtxa = None
    ptpg = None
    ufex = None
    tsad = None
    xisl = None
    xkar = None
    xlah = None
    xlgt = None
    peel = None
    xphx = None
    caze = None
    jpbx = None
    jpsi = None
    jsef = None
    arex = None
    csau = None
    cfau = None
    cseu = None
    cscf = None
    cshk = None
    cfhk = None
    csjp = None
    cfjp = None
    edge = None
    ficx = None
    gbot = None
    grif = None
    ibgh = None
    iexg = None
    lmec = None
    nexo = None
    nmrj = None
    nxjp = None
    nxvw = None
    parx = None
    elix = None
    trdx = None
    xbel = None
    xblb = None
    xmun = None
    xnxc = None
    xves = None
    xhon = None
    icus = None
    itsm = None
    jata = None
    kmts = None
    xsur = None
    mtsp = None
    xasm = None
    xiex = None
    xjkt = None
    mtax = None
    xbmk = None
    xbmf = None
    iceu = None
    xa1x = None
    nome = None
    xbsp = None
    necd = None
    fxmt = None
    atsa = None
    xsic = None
    xtlx = None
    xlof = None
    xmic = None
    qmts = None
    xeus = None
    xnyf = None
    bamp = None
    xedx = None
    xtar = None
    urce = None
    xfnx = None
    csfb = None
    xhce = None
    xher = None
    crdl = None
    baik = None
    umts = None
    xpin = None
    xrtr = None
    xplu = None
    xrov = None
    damp = None
    xljs = None
    xrms = None
    _360t = None
    aats = None
    acex = None
    afdl = None
    afet = None
    afse = None
    aixe = None
    aqst = None
    aqsl = None
    aqsn = None
    aqsg = None
    aqsf = None
    aqsd = None
    aqua = None
    asex = None
    xipo = None
    euax = None
    awbx = None
    awex = None
    bace = None
    baml = None
    bapa = None
    bapx = None
    barx = None
    bard = None
    bbsf = None
    bcfs = None
    xmvl = None
    bcmm = None
    bcse = None
    bcxe = None
    lisx = None
    chix = None
    beam = None
    beex = None
    betp = None
    bfex = None
    bgcf = None
    bgcd = None
    fncs = None
    bgci = None
    bhsf = None
    bids = None
    blev = None
    blpx = None
    bpol = None
    bltd = None
    bmex = None
    sbil = None
    sbar = None
    xval = None
    xbar = None
    xlat = None
    xmef = None
    xmpw = None
    xmrv = None
    bmtf = None
    bnyc = None
    boat = None
    bosc = None
    bova = None
    bovm = None
    brix = None
    brnx = None
    bsex = None
    btec = None
    bvca = None
    xcar = None
    bvmf = None
    bvur = None
    cand = None
    canx = None
    cmap = None
    cats = None
    ccfe = None
    ccfx = None
    cclx = None
    cco2 = None
    cded = None
    cdel = None
    cdsl = None
    fxsw = None
    ceti = None
    cgit = None
    cgnd = None
    cgeb = None
    cgqt = None
    cgcm = None
    cggd = None
    chev = None
    blnk = None
    chia = None
    chic = None
    chie = None
    chij = None
    kaix = None
    chis = None
    chiv = None
    clau = None
    clhk = None
    cljp = None
    clmx = None
    clph = None
    cmee = None
    cmet = None
    cmmt = None
    cmsf = None
    coal = None
    comg = None
    cotc = None
    cred = None
    caes = None
    cryd = None
    cryp = None
    cryx = None
    cssx = None
    dasi = None
    dbhk = None
    dbox = None
    dbsx = None
    dcsx = None
    deal = None
    dgcx = None
    dktc = None
    dots = None
    dsmd = None
    dumx = None
    ecag = None
    ecgs = None
    ecal = None
    ecxe = None
    eeal = None
    eese = None
    eftp = None
    egmt = None
    egsi = None
    embx = None
    emid = None
    emir = None
    emdr = None
    encl = None
    eotc = None
    epex = None
    etsc = None
    exeu = None
    excp = None
    exbo = None
    exdc = None
    extr = None
    fair = None
    fgex = None
    finr = None
    finy = None
    ootc = None
    fish = None
    fltb = None
    fmts = None
    frrf = None
    fsef = None
    fshx = None
    fxal = None
    fxcm = None
    g1xx = None
    gemx = None
    getb = None
    gfia = None
    xgfi = None
    gfim = None
    gllc = None
    glps = None
    glpx = None
    gmeg = None
    xgsx = None
    gmex = None
    gmtf = None
    govx = None
    gree = None
    grse = None
    gsci = None
    gsco = None
    gsef = None
    gsil = None
    gssi = None
    gsxl = None
    gtco = None
    gtsx = None
    gtxs = None
    gxma = None
    hchc = None
    hdat = None
    hegx = None
    hkme = None
    hmtf = None
    hrfq = None
    hppo = None
    hsfx = None
    hstc = None
    xhnx = None
    hsxa = None
    hupx = None
    ibal = None
    ibex = None
    icap = None
    plsx = None
    icdx = None
    icel = None
    icxl = None
    ifca = None
    ifeu = None
    ifut = None
    ifsg = None
    ifus = None
    iepa = None
    imcg = None
    imir = None
    imcr = None
    imen = None
    ices = None
    imag = None
    imbd = None
    imex = None
    isda = None
    isex = None
    itgi = None
    ivzx = None
    ixsp = None
    jadx = None
    jefx = None
    jnst = None
    jpmi = None
    jpmx = None
    jses = None
    jsjx = None
    kabu = None
    kccp = None
    kdpw = None
    kleu = None
    knig = None
    knem = None
    knli = None
    kncm = None
    kocn = None
    krme = None
    lasf = None
    lava = None
    lafd = None
    lchc = None
    lica = None
    liqu = None
    liqf = None
    lius = None
    liuh = None
    lifi = None
    lmax = None
    lotc = None
    pldx = None
    lppm = None
    ltaa = None
    lxjp = None
    mael = None
    mxlm = None
    malx = None
    mxnl = None
    maqh = None
    maqj = None
    maqx = None
    matn = None
    matx = None
    mbul = None
    mcur = None
    mdip = None
    meau = None
    mehk = None
    mfgl = None
    mibg = None
    mihi = None
    xmio = None
    mizx = None
    mlve = None
    mleu = None
    msal = None
    msco = None
    mstx = None
    mslp = None
    msip = None
    msms = None
    bvus = None
    mtsb = None
    mtxs = None
    mtxc = None
    mtxm = None
    mytr = None
    n2ex = None
    namx = None
    nasb = None
    nasx = None
    nblx = None
    nbot = None
    ncel = None
    nfsc = None
    ngxc = None
    nilx = None
    nlpx = None
    nmce = None
    nmra = None
    icsh = None
    icsz = None
    ickr = None
    ichk = None
    nxse = None
    ictw = None
    nncs = None
    nodx = None
    noff = None
    nops = None
    nosc = None
    notc = None
    npga = None
    nsxb = None
    nxeu = None
    nxus = None
    nymx = None
    nypc = None
    ofex = None
    ollc = None
    omel = None
    omga = None
    lynx = None
    omic = None
    opex = None
    opra = None
    oslc = None
    otce = None
    otcx = None
    pave = None
    pdex = None
    pfts = None
    pftq = None
    pieu = None
    pipe = None
    pirm = None
    pmts = None
    prse = None
    pvmf = None
    pxil = None
    qmtf = None
    qwix = None
    rbsx = None
    ricx = None
    ricd = None
    roco = None
    rofx = None
    rotc = None
    rpdx = None
    rsex = None
    rtsp = None
    s3fm = None
    secc = None
    secd = None
    sece = None
    secf = None
    sedc = None
    selc = None
    sepe = None
    sgex = None
    sgma = None
    shar = None
    shaw = None
    shad = None
    siga = None
    sigj = None
    sigx = None
    simv = None
    slxt = None
    smex = None
    soho = None
    spim = None
    sprz = None
    spxe = None
    ssex = None
    sstx = None
    stox = None
    xscu = None
    xstx = None
    swap = None
    sxsi = None
    tera = None
    tfex = None
    tfsa = None
    tfsu = None
    tfsv = None
    tlab = None
    tmid = None
    tocp = None
    tpie = None
    tpim = None
    tpse = None
    tpsv = None
    trck = None
    tfss = None
    dbvx = None
    tfsc = None
    oilx = None
    tcme = None
    tfse = None
    treu = None
    trqx = None
    trqd = None
    trux = None
    trwb = None
    twsf = None
    dwsf = None
    trfx = None
    tsef = None
    tweu = None
    twem = None
    twea = None
    tweo = None
    ubsp = None
    ubsg = None
    ubsf = None
    ubst = None
    ubsx = None
    ukex = None
    ukpx = None
    ultx = None
    vega = None
    vfcm = None
    vmfx = None
    wsag = None
    xabj = None
    xace = None
    xads = None
    xaex = None
    xafr = None
    xafx = None
    xalb = None
    xalg = None
    xams = None
    xeui = None
    tnla = None
    xhft = None
    xeue = None
    xant = None
    xaom = None
    xapi = None
    xaqs = None
    xarc = None
    xarm = None
    xasx = None
    asxt = None
    asxb = None
    asxv = None
    asxp = None
    xsfe = None
    xats = None
    xauk = None
    xazx = None
    xbaa = None
    xbab = None
    bajm = None
    xbah = None
    xban = None
    xbav = None
    xbbf = None
    xbbj = None
    xbbk = None
    xbcc = None
    mvcx = None
    xbce = None
    xbcl = None
    xbcm = None
    xbcx = None
    xbcv = None
    xbda = None
    xber = None
    zobx = None
    eqta = None
    eqtb = None
    eqtc = None
    eqtd = None
    xeqt = None
    xbey = None
    xbfo = None
    xbkk = None
    xbkf = None
    xbln = None
    xbnv = None
    xbog = None
    xbol = None
    xbom = None
    bsme = None
    xbot = None
    botv = None
    xbra = None
    xbre = None
    xbrm = None
    xbrn = None
    xbru = None
    xbrd = None
    xbrv = None
    xbse = None
    xbsd = None
    xbtf = None
    xbud = None
    xtnd = None
    xbue = None
    xmev = None
    xbul = None
    abul = None
    xbvc = None
    xbvp = None
    xbvr = None
    xcai = None
    xcal = None
    xcas = None
    xcay = None
    cbsx = None
    xcbf = None
    xcbt = None
    fcbt = None
    xkbt = None
    xcce = None
    xccx = None
    xcde = None
    xcet = None
    xcfe = None
    xcff = None
    xcgs = None
    xchg = None
    xcie = None
    xcme = None
    glbx = None
    xiom = None
    cmes = None
    cbts = None
    nyms = None
    cecs = None
    xcnf = None
    xcol = None
    xcor = None
    xcrc = None
    xcro = None
    xcsc = None
    xcse = None
    mndk = None
    fndk = None
    dndk = None
    mcse = None
    xfnd = None
    xcsx = None
    xcue = None
    xcur = None
    xcxd = None
    xcys = None
    xecm = None
    xdar = None
    xdce = None
    xdes = None
    xdfb = None
    xdfm = None
    xdha = None
    xdpa = None
    xdse = None
    xdsx = None
    xdtb = None
    xdus = None
    xqtx = None
    xdwz = None
    xebi = None
    xecb = None
    xecc = None
    xecs = None
    xelx = None
    xemd = None
    xems = None
    xeti = None
    xetc = None
    xetr = None
    xetb = None
    xeta = None
    xeup = None
    xeur = None
    xfcm = None
    xffe = None
    xfka = None
    xfmn = None
    xfom = None
    xfra = None
    xdbv = None
    fraa = None
    frad = None
    frab = None
    xdbx = None
    xnew = None
    xfta = None
    xgas = None
    xgcl = None
    xgha = None
    xgme = None
    xgmx = None
    xgse = None
    xgtg = None
    xgua = None
    xham = None
    hamm = None
    haml = None
    hamn = None
    xhan = None
    xhel = None
    dhel = None
    mhel = None
    xhir = None
    xhkf = None
    xhkg = None
    shsc = None
    szsc = None
    xgem = None
    xiab = None
    xibe = None
    xice = None
    dnis = None
    isec = None
    dice = None
    mnis = None
    xicx = None
    xidx = None
    xihk = None
    xima = None
    ximc = None
    xime = None
    xins = None
    icbx = None
    mocx = None
    xinv = None
    xipe = None
    xiqs = None
    xist = None
    xeqy = None
    xisx = None
    xjam = None
    xjnb = None
    xjpx = None
    xosj = None
    xjse = None
    altx = None
    xsaf = None
    xsfa = None
    yldx = None
    xjwy = None
    xkac = None
    xkaz = None
    xkce = None
    xkfb = None
    xkgt = None
    xkha = None
    xkhr = None
    xkie = None
    xkis = None
    xkkt = None
    xkls = None
    mesq = None
    xkor = None
    xkrx = None
    xkfe = None
    xkos = None
    xkcm = None
    xkem = None
    xkse = None
    xkst = None
    xkuw = None
    xkyo = None
    xlao = None
    xlbm = None
    xlce = None
    xldn = None
    xlif = None
    xlfx = None
    xlim = None
    mfox = None
    wqxl = None
    xlit = None
    xlju = None
    xlme = None
    xlon = None
    xlsm = None
    xlto = None
    xlus = None
    xlux = None
    emtf = None
    xmab = None
    xmac = None
    xmae = None
    pros = None
    xman = None
    xmap = None
    xmau = None
    xmdg = None
    xmds = None
    xmer = None
    xmex = None
    xmge = None
    xmid = None
    xmif = None
    xmil = None
    mivx = None
    xaim = None
    xdmi = None
    macx = None
    mtaa = None
    xmlx = None
    xmnt = None
    xmnx = None
    xmoc = None
    xmod = None
    xmol = None
    xmoo = None
    xmsw = None
    xmtb = None
    xmts = None
    nmts = None
    plus = None
    xmus = None
    xnaf = None
    xnai = None
    xnam = None
    xnas = None
    xndq = None
    xngs = None
    xncm = None
    xnim = None
    xbos = None
    bosd = None
    xbxo = None
    xpor = None
    xpsx = None
    xbrt = None
    psxd = None
    xpbt = None
    xpho = None
    xphl = None
    xncd = None
    xnec = None
    xnee = None
    xnep = None
    xngm = None
    nmtf = None
    xngo = None
    xnii = None
    xnks = None
    xnql = None
    xnsa = None
    xnse = None
    xnst = None
    xnyc = None
    xnym = None
    xcec = None
    xnye = None
    xnyl = None
    xnys = None
    xase = None
    xnli = None
    nysd = None
    amxo = None
    arcd = None
    arco = None
    xnze = None
    xode = None
    xoff = None
    xome = None
    burg = None
    merd = None
    xoam = None
    burm = None
    xosc = None
    xoad = None
    xosd = None
    nibr = None
    xosm = None
    xost = None
    xotb = None
    xotc = None
    xpae = None
    xpar = None
    xmat = None
    xmon = None
    xphs = None
    xpic = None
    xpow = None
    xpra = None
    xprm = None
    strt = None
    spad = None
    xpri = None
    xpse = None
    xpst = None
    xpty = None
    xpxe = None
    xqui = None
    xrbm = None
    xrio = None
    xris = None
    fnlv = None
    xrmz = None
    xros = None
    xrox = None
    xtuc = None
    xrpm = None
    xrus = None
    xsam = None
    xsap = None
    xsau = None
    xsco = None
    xsef = None
    xses = None
    xsim = None
    xsce = None
    xsge = None
    xsgo = None
    xshe = None
    xshg = None
    xsib = None
    xsme = None
    xsom = None
    xsop = None
    xsps = None
    xsrm = None
    xsse = None
    xstc = None
    xste = None
    xsto = None
    dsto = None
    xstu = None
    euwx = None
    xsva = None
    xswa = None
    xswb = None
    xswo = None
    xtad = None
    xtae = None
    xtaf = None
    xtai = None
    xtal = None
    fnee = None
    xteh = None
    xtfe = None
    xtff = None
    xtfn = None
    xtir = None
    xtka = None
    xtko = None
    xtkt = None
    xtoe = None
    xtra = None
    xtrn = None
    xtrz = None
    xtse = None
    xtsx = None
    xtnx = None
    xtun = None
    xtup = None
    tpsd = None
    tpre = None
    tpeq = None
    xtpe = None
    tben = None
    xtur = None
    xuax = None
    xuga = None
    xukr = None
    xula = None
    xuni = None
    xuse = None
    xvar = None
    xvla = None
    xvpa = None
    xvse = None
    xwar = None
    plpo = None
    plps = None
    wblc = None
    wbcl = None
    wbon = None
    wmtf = None
    wder = None
    wcde = None
    poee = None
    wgas = None
    plpx = None
    xwbo = None
    wbah = None
    wbdm = None
    xvie = None
    xxsc = None
    xxxx = None
    xyie = None
    xykt = None
    xzag = None
    xzce = None
    xzim = None
    zkbx = None
    kmux = None
    ukca = None
    asef = None
    memm = None
    xebs = None
    nspo = None
    otci = None
    gfox = None
    fnft = None
    hgsp = None
    term = None
    patf = None
    bbvx = None
    odxe = None
    hpsx = None
    dbdx = None
    emce = None
    hpso = None
    artx = None
    sptx = None
    tsir = None
    stxs = None
    eufn = None
    tsfx = None
    gfau = None
    cse2 = None
    xigg = None
    smbc = None
    fnxb = None
    bgca = None
    aqxd = None
    xftx = None
    nabp = None
    usob = None
    btun = None
    ecnl = None
    rits = None
    fxsm = None
    fxnm = None
    mswp = None
    cast = None
    xabx = None
    trbx = None
    cilh = None
    uswp = None
    cbae = None
    trdc = None
    usef = None
    nssa = None
    cmcm = None
    eblx = None
    erfq = None
    entw = None
    fusd = None
    xete = None
    xetx = None
    sfox = None
    bjse = None
    neeq = None
    vfex = None
    msdm = None
    lneq = None
    lnfi = None
    ibsi = None
    raja = None
    lpsf = None
    gbsi = None
    tpid = None
    ingu = None
    sisu = None
    sewb = None
    dkwb = None
    nowb = None
    seob = None
    dkob = None
    euob = None
    gbob = None
    noob = None
    otxt = None
    mxop = None
    bocf = None
    fpwb = None
    spax = None
    lebv = None
    lesi = None
    bgem = None
    jleq = None
    gmge = None
    iexc = None
    intl = None
    brmf = None
    cxab = None
    cxai = None
    tmuk = None
    xcbd = None
    u360 = None
    bdpl = None
    vmex = None
    inft = None
    edxm = None
    ibkr = None
    algo = None
    xand = None
    fnds = None
    iffx = None
    qunt = None
    gslo = None
    rtxf = None
    arda = None
    vuba = None
    g360 = None
    acxl = None
    acxc = None
    ximx = None
    atad = None
    gsxn = None
    rule = None
    msxb = None
    xcvd = None
    mslc = None
    xanm = None
    cfim = None
    msxo = None
    xatx = None
    adrk = None
    rfim = None
    bnds = None
    sphr = None
    afts = None
    tmeu = None
    nxfo = None
    tpda = None
    tict = None
    xbry = None
    xmme = None
    gsxm = None
    ntrl = None
    scle = None
    nxbx = None
    accx = None
    potl = None
    npms = None
    lbul = None
    m2ae = None
    rrsi = None
    octl = None
    bxda = None
    bgcj = None
    lmas = None
    gfsg = None
    bgsg = None
    eesx = None
    bnph = None
    spdk = None
    spno = None
    spfi = None
    speu = None
    d2xg = None
    optx = None
    phsi = None
    _360x = None
    etor = None
    vwap = None
    xwap = None
    itsl = None
    jpjx = None
    jefa = None
    odst = None
    rvsa = None
    dwin = None
    rfqu = None
    rfqs = None
    rfqn = None
    dpar = None
    dbru = None
    dlis = None
    dams = None
    ddub = None
    dosl = None
    dmil = None
    cbms = None
    xggi = None
    octc = None
    icps = None
    mssa = None
    vams = None
    ibco = None
    hwhe = None
    xema = None
    xemi = None
    xemb = None
    bbsn = None
    sclb = None
    sfmp = None
    iexa = None
    d2xc = None
    rbcs = None
    lake = None
    nzxc = None
    nzxm = None
    _21xx = None
    xans = None
    tpsb = None
    tdxs = None
    dmad = None
    wflp = None
    xacd = None
    hane = None
    hand = None
    hanc = None
    xgai = None
    bpag = None
    nxte = None
    pvbl = None
    wbma = None
    synk = None
    tpsg = None
    fmxs = None
    xcts = None
    stuh = None
    ocfx = None
    ocxl = None
    ocxe = None
    pgtp = None
    oyld = None
    gsbs = None
    xmti = None
    xnrg = None
    alpx = None
    bpxx = None
    ctdd = None
    ctcc = None
    ctss = None
    fgml = None
    xjax = None
    nzxd = None
    peur = None
    phel = None
    pcse = None
    psto = None
    pfse = None
    mepx = None
    bfsd = None
    opmx = None
    ivwp = None
    onex = None
    onep = None
    gtsm = None
    wmfs = None
    gara = None
    besa = None
    wmsw = None
    wmus = None
    wtrs = None
    lakx = None
    fnfx = None
    nzfx = None
    bacr = None
    stuf = None
    xstp = None
    stue = None
    hcer = None
    gmbg = None
    xglo = None
    wind = None
    fnix = None
    latg = None
    ensl = None
    dbmo = None
    dbln = None
    abxx = None
    fxrs = None
    fxps = None
    xbis = None
    tpee = None
    eqoc = None
    eqod = None
    aqed = None
    eixe = None
    hpcs = None
    noco = None
    mabx = None
    hpco = None
    icor = None
    tper = None
    xsdx = None
    cedx = None
    cbks = None
    xoas = None
    sga2 = None
    ewrm = None
    bbok = None
    blfx = None
    onec = None
    mbsi = None
    pepq = None
    pepy = None
    peph = None
    pepm = None
    grow = None
    eprd = None
    gspl = None
    tlcm = None
    memd = None
    ebso = None
    vndm = None
    wabr = None
    xsca = None
    tmcc = None
    edbt = None
    edgl = None
    etlx = None
    basp = None
    bteq = None
    eqse = None
    vabd = None
    imcc = None
    next = None
    nexn = None
    nexf = None
    xndx = None
    xnmr = None
    sbiu = None
    xsbi = None
    sbiv = None
    eqsl = None
    jser = None
    hesp = None
    hede = None
    pjcx = None
    cima = None
    xzam = None
    cgee = None
    cgec = None
    cgme = None
    cgmc = None
    nexy = None
    trqs = None
    core = None
    cicx = None
    malm = None
    xpsf = None
    xpot = None
    cslp = None
    cgmu = None
    cscl = None
    csvw = None
    ukre = None
    ukor = None
    tuob = None
    bmls = None
    bmsi = None
    sgmz = None
    pfxd = None
    trqc = None
    gsbx = None
    beta = None
    xpol = None
    xpal = None
    aspi = None
    asmt = None
    aspn = None
    cisd = None
    cdsi = None
    resf = None
    ebsf = None
    xdex = None
    dowe = None
    wopo = None
    iebs = None
    mkaa = None
    cget = None
    xeub = None
    nsme = None
    beup = None
    beuf = None
    ceud = None
    beud = None
    ceux = None
    ceuo = None
    beue = None
    xbnd = None
    blkx = None
    plpd = None
    nmsx = None
    xlod = None
    lafx = None
    fltr = None
    bate = None
    batf = None
    batd = None
    btqe = None
    btqg = None
    ebra = None
    xcan = None
    xrmo = None
    xnco = None
    knmx = None
    tnlk = None
    xdrk = None
    vdrk = None
    gfpo = None
    pumx = None
    vwda = None
    bgfu = None
    mczk = None
    hung = None
    emts = None
    mtsa = None
    gmts = None
    mtsg = None
    imts = None
    rmts = None
    amts = None
    port = None
    slkk = None
    vmts = None
    smts = None
    ebsi = None
    rese = None
    ebsd = None
    eusp = None
    xmfx = None
    trfw = None
    teeg = None
    nlax = None
    ubse = None
    ubsi = None
    wbgf = None
    xetv = None
    xetw = None
    xetu = None
    frav = None
    fraw = None
    frau = None
    ipxw = None
    zero = None
    scxs = None
    tpir = None
    xchi = None
    xcis = None
    celp = None
    zbul = None
    imsb = None
    aqxa = None
    jbul = None
    bleq = None
    mcad = None
    ebmx = None
    enxb = None
    xmsm = None
    xesm = None
    ukgd = None
    gbul = None
    tnll = None
    trqm = None
    xblk = None
    iswo = None
    fxrq = None
    fxfm = None
    pbul = None
    xetf = None
    gsei = None
    cbkc = None
    kblc = None
    kbls = None
    kblt = None
    xets = None
    fras = None
    ceue = None
    valx = None
    cesi = None
    tpio = None
    dsme = None
    fsme = None
    xnfi = None
    espd = None
    ssme = None
    jesi = None
    vcrs = None
    brds = None
    xnxd = None
    icxr = None
    mesi = None
    gbwb = None
    mscx = None
    brdl = None
    ftfm = None
    baru = None
    beuo = None
    beut = None
    capa = None
    lisz = None
    iats = None
    ipxp = None
    bgfx = None
    bgfi = None
    iece = None
    temg = None
    teof = None
    tomf = None
    tepg = None
    tepx = None
    tepr = None
    tepm = None
    tsuk = None
    tsmc = None
    tsmg = None
    tsmi = None
    tsmb = None
    icen = None
    nabu = None
    naba = None
    bbis = None
    exyy = None
    exsf = None
    exsp = None
    exsd = None
    exsb = None
    exsh = None
    trqb = None
    finn = None
    xfci = None
    xfda = None
    mtsm = None
    temc = None
    zfxm = None
    bliq = None
    bsfx = None
    bdea = None
    blbs = None
    msrp = None
    mssi = None
    melo = None
    cblc = None
    cioi = None
    xehq = None
    mose = None
    dose = None
    ibeq = None
    emld = None
    belf = None
    asxc = None
    cfbc = None
    sbmf = None
    bmfm = None
    bmfa = None
    jasr = None
    xmce = None
    bond = None
    tfsg = None
    tcds = None
    zapa = None
    iswe = None
    iswv = None
    hpcv = None
    sgmy = None
    ssbm = None
    dbes = None
    teco = None
    xzap = None
    vtps = None
    imco = None
    ensx = None
    inca = None
    ssob = None
    xapa = None
    rest = None
    xrep = None
    lmao = None
    lmae = None
    lmaf = None
    apcl = None
    sedx = None
    cmed = None
    iecl = None
    mdrv = None
    iidx = None
    iblx = None
    rcbx = None
    ifsm = None
    mtss = None
    mtsw = None
    anlp = None
    macb = None
    brfq = None
    bntw = None
    blox = None
    iotc = None
    basi = None
    mlsi = None
    cimv = None
    cimb = None
    cime = None
    inge = None
    ingf = None
    afso = None
    afsx = None
    afsl = None
    xgat = None
    tgsi = None
    cgmt = None
    trqa = None
    auro = None
    bgcm = None
    exsi = None
    sunm = None
    tscb = None
    bgco = None
    gfbm = None
    gfbo = None
    suno = None
    tsre = None
    tscd = None
    tsgb = None
    tsfi = None
    tsed = None
    tsgi = None
    tsmm = None
    tere = None
    tefx = None
    temm = None
    tegi = None
    teir = None
    jseb = None
    esto = None
    onse = None
    xsmp = None
    ebsx = None
    bmea = None
    ebsc = None
    aimx = None
    xlom = None
    sics = None
    tomd = None
    rbsi = None
    rtsi = None
    mund = None
    munc = None
    wipo = None
    iexd = None
    xeye = None
    xhnf = None
    xsbt = None
    ensy = None
    alxb = None
    mlxb = None
    xmli = None
    alxp = None
    sgmt = None
    mtsd = None
    mtsf = None
    isdx = None
    imeq = None
    ndxs = None
    alxa = None
    etfp = None
    bart = None
    baro = None
    bmts = None
    ibul = None
    xeer = None
    xeeo = None
    prme = None
    csbx = None
    cxot = None
    dked = None
    dkfi = None
    noed = None
    seed = None
    pned = None
    uswb = None
    nofi = None
    fied = None
    ebon = None
    euwb = None
    trea = None
    treo = None
    autb = None
    cxrt = None
    ackf = None
    grio = None
    xstf = None
    stuc = None
    stud = None
    xceg = None
    xrsp = None
    hotc = None
    xade = None
    enax = None
    xath = None
    blbf = None
    xmot = None
    motx = None
    munb = None
    muna = None
    xopv = None
    xvia = None
    xwce = None
    nasn = None
    xeas = None
    ceto = None
    expa = None
    nbxo = None
    thrd = None
    xtaa = None
    vrxp = None
    mlco = None
    mlvx = None
    bcdx = None
    barl = None
    chiy = None
    chio = None
    batp = None
    chid = None
    botc = None
    bgcb = None
    send = None
    xdrf = None
    marf = None
    bmcl = None
    merf = None
    xbil = None
    xmad = None
    vtex = None
    nyfx = None
    icsu = None
    astr = None
    fxcl = None
    cgqd = None
    cgdb = None
    cgtr = None
    cxar = None
    cxac = None
    cxap = None
    cxam = None
    cxaq = None
    cxav = None
    cxaf = None
    cxan = None
    cxaw = None
    xcx2 = None
    cmec = None
    auto = None
    emib = None
    exor = None
    exvp = None
    exmp = None
    exlp = None
    exgm = None
    xeda = None
    xeid = None
    xadf = None
    finc = None
    fino = None
    xgdx = None
    xldx = None
    xgcx = None
    hmod = None
    wclk = None
    icah = None
    icse = None
    ictq = None
    iflx = None
    ifll = None
    ifen = None
    iflo = None
    imfx = None
    ifed = None
    vkab = None
    lafl = None
    lcur = None
    liqh = None
    lmad = None
    lmnx = None
    mcxr = None
    mcxs = None
    eprl = None
    mprl = None
    mspl = None
    mstc = None
    nfsd = None
    xstm = None
    nfsa = None
    xqlx = None
    xstv = None
    tru2 = None
    tru1 = None
    bndd = None
    ubsc = None
    xeuc = None
    bera = None
    berb = None
    berc = None
    xmai = None
    bote = None
    eqwb = None
    vpxb = None
    tnlb = None
    xras = None
    fcme = None
    ximm = None
    dcse = None
    xcyo = None
    dusa = None
    dusb = None
    dusc = None
    dusd = None
    xetd = None
    xert = None
    xere = None
    xeum = None
    xdbc = None
    hama = None
    hamb = None
    hanb = None
    hana = None
    mnfi = None
    fnfi = None
    dnfi = None
    fnis = None
    mice = None
    icro = None
    xpms = None
    xfno = None
    xdsm = None
    xise = None
    gmni = None
    xtpz = None
    mcry = None
    xisa = None
    xtk1 = None
    xjas = None
    xtks = None
    xose = None
    xtam = None
    xtk3 = None
    xtk2 = None
    xbes = None
    xkon = None
    fnlt = None
    xljm = None
    mtah = None
    atfx = None
    cmts = None
    tmts = None
    lmts = None
    eacm = None
    bvuk = None
    nasd = None
    xnms = None
    inse = None
    aldp = None
    arcx = None
    xspm = None
    mtch = None
    xsc2 = None
    xsc3 = None
    xsc1 = None
    xscl = None
    xine = None
    xsec = None
    xssc = None
    dnse = None
    fnse = None
    csto = None
    mnse = None
    msto = None
    stub = None
    stua = None
    tpcd = None
    tbla = None
    tpfd = None
    tpsp = None
    rpwc = None
    tbsp = None
    tbsa = None
    bosp = None
    wetp = None
    exaa = None
    ieos = None
    icat = None
    pcds = None


class _Deserializer:
    @staticmethod
    def _o(
        buf: BinaryIO, deserializer: Callable[..., _T], *args: Any
    ) -> Union[_T, None]:
        b = buf.read(1)
        if b[0]:
            return deserializer(buf, *args)
        return None

    @staticmethod
    def _s(buf: BinaryIO, size: int) -> str:
        length = int.from_bytes(buf.read(size), "big")
        encoded = buf.read(length)
        return encoded.decode("utf-8")

    @staticmethod
    def _d(buf: BinaryIO) -> datetime.date:
        # year       : 15
        # month      : 4
        # day        : 5
        data = int.from_bytes(buf.read(3), "big")
        return datetime.date(
            year=(data >> 9),
            month=((data >> 5) & 0xf),
            day=(data & 0x1f)
        )

    @staticmethod
    def _e(buf: BinaryIO, size: int, enum_class: type[_E]) -> _E:
        e = enum_class._value2member_map_[
            int.from_bytes(buf.read(size), "big")
        ]
        if not isinstance(e, enum_class):
            raise ValueError(
                "'_value2member_map_' contains incorrect enum value"
            )
        return e

    @staticmethod
    def _format_mic(mic: str) -> str:
        mic = mic.lower()
        if (
            mic[0].isdigit()
            or mic in {"else", "from", "pass", "with"}
        ):
            return f"_{mic}"
        return mic

    @classmethod
    def deserialize(
        cls, buf: BinaryIO, existing: dict[str, MICEntry]
    ) -> tuple[str, MICEntry]:
        def _m(value: Union[str, None]) -> Union[MICEntry, None]:
            if value:
                return existing[cls._format_mic(value)]
            return None

        entry = MICEntry(
            mic                     = cls._s(buf, 1),
            market_name             = cls._s(buf, 1),
            market_category_code    = cls._e(buf, 1, MCC),
            creation_date           = cls._d(buf),
            status                  = cls._e(buf, 1, Status),
            city                    = cls._o(buf, cls._e, 2, City),
            operating_mic           = _m(cls._o(buf, cls._s, 1)),
            institution_description = cls._o(buf, cls._s, 1),
            legel_entity_name       = cls._o(buf, cls._s, 1),
            legal_entity_identifier = cls._o(buf, cls._s, 1),
            acronym                 = cls._o(buf, cls._s, 1),
            iso_country_code        = cls._o(buf, cls._e, 1, ISOCC),
            website                 = cls._o(buf, cls._s, 1),
            last_update_date        = cls._o(buf, cls._d),
            last_validation_date    = cls._o(buf, cls._d),
            expiry_date             = cls._o(buf, cls._d),
            comments                = cls._o(buf, cls._s, 2)
        )

        return (cls._format_mic(entry.mic), entry)


def _build_mic(data: pathlib.Path) -> enum.Enum:
    mics: dict[str, MICEntry] = dict()

    # deserialize data file
    with data.open("rb") as infile:
        num_entries = int.from_bytes(infile.read(2), "big")
        for _ in range(num_entries):
            k, v = _Deserializer.deserialize(infile, mics)
            mics[k] = v

    # create and return enum
    return enum.Enum("MIC", mics)


globals()["MIC"] = _build_mic(pathlib.Path(__file__).parent / "_data")
