import regex
from ..parser import Parser, perform_substitutions
from ua_extract.enums import DeviceType

MOBILE_DEVICE_TYPES = {
    DeviceType.Camera.value,
    DeviceType.FeaturePhone.value,
    DeviceType.Phablet.value,
    DeviceType.PortableMediaPlayer.value,
    DeviceType.Smartphone.value,
    DeviceType.Tablet.value,
}

# Before using a new brand in on of the regex files, it needs to be added here
DEVICE_BRANDS = {
    '5E': '2E',
    '5IV': '5IVE',
    '2F': 'F2 Mobile',
    '3Q': '3Q',
    'J7': '7 Mobile',
    '2Q': '3GNET',
    '4G': '4Good',
    '27': '3GO',
    '04': '4ife',
    '36': '360',
    '88': '8848',
    '10M': '10moons',
    '41': 'A1',
    'AK1': 'A&K',
    '00': 'Accent',
    'ACC': 'Accesstyle',
    'ACD': 'ACD',
    'AE': 'Ace',
    'AC': 'Acer',
    'ACL': 'Aceline',
    'ACP': 'Acepad',
    '3K': 'Acteck',
    'ACT': 'actiMirror',
    'A9': 'Advan',
    'AD': 'Advance',
    'ADV': 'Advantage Air',
    '76': 'Adronix',
    'ADR': 'Adreamer',
    'AF': 'AfriOne',
    'FY': 'AFFIX',
    'A3': 'AGM',
    'AEE': 'AEEZO',
    'J0': 'AG Mobile',
    'AJI': 'Ajib',
    'AZ': 'Ainol',
    'AIR': 'Airis',
    'AI': 'Airness',
    'ARP': 'Airpha',
    'AT': 'Airties',
    '7U': 'Airtel',
    'AIT': 'AirTouch',
    'U0': 'AIRON',
    '0A': 'AIS',
    'AW': 'Aiwa',
    '85': 'Aiuto',
    'U7': 'AIDATA',
    'AL1': 'AileTV',
    'AL2': 'AI+',
    'AK': 'Akai',
    'Q3': 'AKIRA',
    '1A': 'Alba',
    'AL': 'Alcatel',
    'AL0': 'Alienware',
    '20': 'Alcor',
    'XY': 'Alps',
    'XYA': 'XY Auto',
    'AAU': 'AAUW',
    '7L': 'ALDI NORD',
    '6L': 'ALDI SÜD',
    '3L': 'Alfawise',
    '4A': 'Aligator',
    'ALS': 'All Star',
    'AA': 'AllCall',
    '3A': 'AllDocube',
    'ALL': 'allente',
    'A2': 'Allview',
    'ALI': 'ALLINmobile',
    'A7': 'Allwinner',
    'ALP': 'alpsmart',
    'A1': 'Altech UEC',
    '66': 'Altice',
    'ALM': 'Altimo',
    'A5': 'altron',
    'ALB': 'Altibox',
    'ALT': 'Altus',
    'KN': 'Amazon',
    'AMZ': 'Amazon Basics',
    'AMA': 'AMA',
    'AG': 'AMGOO',
    '9A': 'Amigoo',
    'AO': 'Amoi',
    '3J': 'Amino',
    '54': 'AMCV',
    '60': 'Andowl',
    'ANX': 'ANXONIT',
    'ANL': 'ANCEL',
    'ANC': 'ANBERNIC',
    'AND': 'andersson',
    '6J': 'Angelcare',
    'ANG': 'AngelTech',
    '7A': 'Anry',
    'A0': 'ANS',
    '74': 'Anker',
    '3N': 'Aoson',
    'O8': 'AOC',
    'J2': 'AOYODKG',
    '55': 'AOpen',
    'RW': 'Aoro',
    '9Y': 'Aocos',
    'AOW': 'Aocwei',
    'AP': 'Apple',
    'APS': 'ApoloSign',
    'ARC': 'Arçelik',
    'AR': 'Archos',
    'AB': 'Arian Space',
    'ARI': 'Arival',
    'A6': 'Ark',
    '5A': 'ArmPhone',
    'AN': 'Arnova',
    'AS': 'ARRIS',
    'AQ': 'Aspera',
    'HJ': 'Aquarius',
    '40': 'Artel',
    '21': 'Artizlee',
    '59': 'ArtLine',
    '8A': 'Asano',
    '90': 'Asanzo',
    '1U': 'Astro (UA)',
    'AST': 'astro (MY)',
    'A4': 'Ask',
    'A8': 'Assistant',
    'ASS': 'ASSE',
    'AU': 'Asus',
    '6A': 'AT&T',
    'ATH': 'Athesi',
    'ATE': 'Atlantic Electrics',
    '5Q': 'Atmaca Elektronik',
    'YH': 'ATMAN',
    'ATM': 'ATMPC',
    '2A': 'Atom',
    'AT1': 'Atozee',
    'ATO': 'ATOL',
    'Z2': 'Atvio',
    'ATI': 'Attila',
    'ATU': 'Atouch',
    'AX': 'Audiovox',
    'AJ': 'AURIS',
    'YZ': 'Autan',
    'AUP': 'AUPO',
    'ZA': 'Avenzo',
    'AH': 'AVH',
    'AV': 'Avvio',
    'AVA': 'Avaya',
    'AXE': 'AXEN',
    'AY': 'Axxion',
    'AXX': 'AXXA',
    'AYA': 'AYA',
    'YR': 'AYYA',
    'XA': 'Axioo',
    'AM': 'Azumi Mobile',
    'AZE': 'Azeyou',
    'AZU': 'Azupik',
    'AZO': 'AZOM',
    'WW': 'Awow',
    'AWO': 'AWOX',
    'XU': 'AUX',
    'BAC': 'Backcell',
    'BFF': 'BAFF',
    'BNC': 'BNCF',
    'BO': 'BangOlufsen',
    'BN': 'Barnes & Noble',
    'BAR': 'BARTEC',
    'BAU': 'BAUHN',
    'BB': 'BBK',
    '0B': 'BB Mobile',
    'B6': 'BDF',
    'QD': 'BDQ',
    '8Z': 'BDsharing',
    'BEF': 'Beafon',
    'BE': 'Becker',
    'B5': 'Beeline',
    'B0': 'Beelink',
    'BL': 'Beetel',
    'BEK': 'Beko',
    '2X': 'Benco',
    'BQ': 'BenQ',
    'BQL': 'Bqeel',
    'BS': 'BenQ-Siemens',
    '4Y': 'Benzo',
    'XJ': 'Benesse',
    'BEN': 'BenWee',
    'YB': 'Beista',
    'BY': 'BS Mobile',
    'BZ': 'Bezkam',
    'BEL': 'Bell',
    '9B': 'Bellphone',
    '63': 'Beyond',
    'BG': 'BGH',
    '6B': 'Bigben',
    'B8': 'BIHEE',
    '1B': 'Billion',
    'BA': 'BilimLand',
    'BIL': 'Billow',
    'BH': 'BioRugged',
    'BI': 'Bird',
    'BT': 'Bitel',
    'B7': 'Bitmore',
    'ZB': 'Bittium',
    'BIE': 'Biegedy',
    'BK': 'Bkav',
    '5B': 'Black Bear',
    'BLK': 'Black Box',
    'BF': 'Black Fox',
    'BPC': 'Blackpcs',
    'BLP': 'Blackphone',
    'BLT': 'Blackton',
    'B2': 'Blackview',
    '2Y': 'b2m',
    'BP': 'Blaupunkt',
    'BU': 'Blu',
    'BUS': 'BluSlate',
    'BUZ': 'BuzzTV',
    'B3': 'Bluboo',
    '2B': 'Bluedot',
    'BD': 'Bluegood',
    'LB': 'Bluewave',
    'J8': 'Bluebird',
    'BSS': 'BlueSky',
    '7B': 'Blloc',
    'UB': 'Bleck',
    'Q2': 'Blow',
    'BLI': 'BLISS',
    'BM': 'Bmobile',
    'Y5': 'BMAX',
    'BMX': 'BMXC',
    'B9': 'Bobarry',
    'B4': 'bogo',
    'BOL': 'Bolva',
    'BW': 'Boway',
    'BOO': 'Boost',
    'BOK': 'Bookeen',
    'BOT': 'Botech',
    'BX': 'bq',
    '8B': 'Brandt',
    'BRA': 'BrandCode',
    'BV': 'Bravis',
    'BRV': 'BRAVE',
    'BRG': 'Brigmton',
    'BR': 'Brondi',
    'XF': 'BROR',
    'BJ': 'BrightSign',
    'B1': 'Bush',
    '4Q': 'Bundy',
    'Y8': 'Bubblegum',
    'BMW': 'BMW',
    'BYJ': 'BYJU\'S',
    'BYY': 'BYYBUO',
    'BYD': 'BYD',
    'C9': 'CAGI',
    'CAD': 'CADENA',
    'CAL': 'CALME',
    'CAI': 'Caixun',
    'CT': 'Capitel',
    'GRD': 'G-Guard',
    'GVL': 'G-Vill',
    'G3': 'CG Mobile',
    '37': 'CGV',
    'CP': 'Captiva',
    'CPD': 'CPDEVICE',
    'CF': 'Carrefour',
    'CA1': 'Carbon Mobile',
    'CS': 'Casio',
    'R4': 'Casper',
    'CA': 'Cat',
    'BC': 'Camfone',
    'CJ': 'Cavion',
    'CNM': 'Canaima',
    'CAN': 'Canal+',
    '4D': 'Canal Digital',
    'CNG': 'Canguro',
    'CNT': 'CCIT',
    'CEC': 'Cecotec',
    'CEP': 'CEPTER',
    'CEI': 'Ceibal',
    '02': 'Cell-C',
    'CEL': 'Cellacom',
    '34': 'CellAllure',
    '7C': 'Celcus',
    'CE': 'Celkon',
    'CG': 'Cellution',
    '62': 'Centric',
    'CEN': 'CENTEK',
    'C2': 'Changhong',
    'CHA': 'Chainway',
    'CHG': 'ChiliGreen',
    'CH': 'Cherry Mobile',
    'C3': 'China Mobile',
    'U9': 'China Telecom',
    'CI': 'Chico Mobile',
    'CHC': 'CHCNAV',
    'CIA': 'C Idea',
    'CIP': 'CipherLab',
    'CIT': 'Citycall',
    '1C': 'Chuwi',
    'L8': 'Clarmin',
    '25': 'Claresta',
    'CLA': 'CLAYTON',
    'CLT': 'Clovertek',
    '1J': 'Cloud Mobile',
    'CD': 'Cloudfone',
    'C0': 'Clout',
    'CN': 'CnM',
    'CY': 'Coby Kyros',
    'XC': 'Cobalt',
    'C6': 'Comio',
    'COM': 'CommScope',
    'CL': 'Compal',
    'CQ': 'Compaq',
    'C7': 'ComTrade Tesla',
    '7Z': 'COMPUMAX',
    'C8': 'Concord',
    'CC': 'ConCorde',
    'C5': 'Condor',
    'C5M': 'C5 Mobile',
    'COE': 'Cogeco',
    '4C': 'Conquest',
    'COG': 'CONSUNG',
    '3C': 'Contixo',
    '8C': 'Connex',
    '53': 'Connectce',
    'CON': 'Conceptum',
    'CED': 'Continental Edison',
    '9C': 'Colors',
    'COL': 'COLORROOM',
    'CAA': 'coocaa',
    'CO': 'Coolpad',
    'COO': 'Coopers',
    'CDE': 'COOD-E',
    '4R': 'CORN',
    '1O': 'Cosmote',
    'CW': 'Cowon',
    '75': 'Covia',
    'QG': 'COYOTE',
    'CKK': 'CKK Mobile',
    'YW': 'ClearPHONE',
    '33': 'Clementoni',
    'CR': 'CreNova',
    'CX': 'Crescent',
    'CRE': 'Crestron',
    'CK': 'Cricket',
    'CM': 'Crius Mea',
    'CMF': 'CMF',
    '0C': 'Crony',
    'C1': 'Crosscall',
    '4W': 'Crown',
    'CTR': 'Ctroniq',
    'CU': 'Cube',
    'CB': 'CUBOT',
    'CUI': 'Cuiud',
    'CUL': 'Cultraview',
    'CV': 'CVTE',
    'CWO': 'Cwowdefu',
    'CX0': 'CX',
    'C4': 'Cyrus',
    'D5': 'Daewoo',
    'DA': 'Danew',
    'DAN': 'Dany',
    'DA1': 'DangcapHD',
    'DAR': 'Daria',
    'DT': 'Datang',
    'D7': 'Datawind',
    '7D': 'Datamini',
    '6D': 'Datalogic',
    'D1': 'Datsun',
    'DAS': 'DASS',
    'DAW': 'Dawlance',
    'DB': 'Dbtel',
    'DBP': 'DbPhone',
    'DCO': 'Dcode',
    'DEC': 'DEC',
    'DL': 'Dell',
    'DL0': 'DL',
    'DE': 'Denver',
    'DS': 'Desay',
    'DSD': 'DSDevices',
    'DSI': 'DSIC',
    'DW': 'DeWalt',
    'DX': 'DEXP',
    'DEY': 'DEYI',
    'DEN': 'Denali',
    'DEA': 'DEALDIG',
    'DNK': 'Denka',
    '8D': 'DF',
    'DGT': 'DGTEC',
    'DG': 'Dialog',
    'DIA': 'DIALN',
    'DI': 'Dicam',
    'D4': 'Digi',
    'D3': 'Digicel',
    'DDG': 'Digidragon',
    'DH': 'Digihome',
    'DD': 'Digiland',
    'DIJ': 'DIJITSU',
    'DIG': 'Digit',
    'DIC': 'DIGICOM',
    'Q0': 'DIGIFORS',
    'DIK': 'DIKOM',
    'DQ': 'DISH',
    'DIS': 'Disney',
    'D2': 'Digma',
    '1D': 'Diva',
    'DIV': 'DiverMax',
    'D6': 'Divisat',
    'DIO': 'DIORA',
    'DIF': 'Diofox',
    'DIM': 'DIMO',
    'DIN': 'Dinax',
    'DNA': 'Dinalink',
    '5D': 'DING DING',
    '9D': 'Ditecma',
    'X6': 'DIXON',
    'DM': 'Dream Multimedia',
    'DMO': 'DMOAO',
    'DN': 'DNS',
    'DC': 'DoCoMo',
    'DF': 'Doffler',
    'D9': 'Dolamee',
    'DO': 'Doogee',
    'D0': 'Doopro',
    'DV': 'Doov',
    'DOM': 'Dom.ru',
    'DP': 'Dopod',
    'DPA': 'DPA',
    'JQ': 'Doppio',
    'DR': 'Doro',
    'DOR': 'Dora',
    'ZD': 'DORLAND',
    'DRO': 'Droidlogic',
    'D8': 'Droxio',
    'DJ': 'Dragon Touch',
    'DRA': 'DRAGON',
    'DY': 'Dreamgate',
    'DR1': 'DreamStar',
    'DTA': 'Dtac',
    'DU': 'Dune HD',
    'DUO': 'DuoTV',
    'UD': 'DUNNS Mobile',
    'DUU': 'Duubee',
    'DUR': 'Durabook',
    'DUD': 'DUDU AUTO',
    'DYO': 'Dyon',
    'DYM': 'Dykemann',
    'DTE': 'D-Tech',
    'DLI': 'D-Link',
    'ENO': 'eNOVA',
    'IN4': 'Inno Hit',
    'IN2': 'iNOVA',
    'IN3': 'inovo',
    'INH': 'Inhon',
    'IND': 'Indurama',
    'EB': 'E-Boda',
    'EJ': 'Engel',
    'ENA': 'ENACOM',
    'END': 'ENDURO',
    'ENI': 'ENIE',
    '2E': 'E-Ceros',
    'E8': 'E-tel',
    'ETH': 'E-TACHI',
    'EAS': 'EAS Electric',
    'EP': 'Easypix',
    'EQ': 'Eagle',
    'EGS': 'EagleSoar',
    'EA': 'EBEST',
    'YC': 'EBEN',
    'E4': 'Echo Mobiles',
    'EQ1': 'Equator',
    'ES': 'ECS',
    '35': 'ECON',
    'ECC': 'ECOO',
    'ZZ': 'ecom',
    'ECS': 'EcoStar',
    'EDE': 'Edenwood',
    'EDX': 'Edanix',
    'E6': 'EE',
    'GW': 'EGL',
    'EGO': 'EGOTEK',
    'EFT': 'EFT',
    'EK': 'EKO',
    'EY': 'Einstein',
    'EM': 'Eks Mobility',
    'UE': 'Ematic',
    'EMR': 'Emporia',
    '4K': 'EKT',
    '7E': 'ELARI',
    '03': 'Electroneum',
    'Z8': 'ELECTRONIA',
    'ELG': 'ELE-GATE',
    'EL1': 'Elecson',
    'ELK': 'Elektroland',
    'L0': 'Element',
    'EG': 'Elenberg',
    'EL': 'Elephone',
    'JE': 'Elekta',
    'ELE': 'Elevate',
    'ELS': 'Elista',
    'ELT': 'elit',
    '4E': 'Eltex',
    'ELM': 'Elong Mobile',
    'ED': 'Energizer',
    'E1': 'Energy Sistem',
    '3E': 'Enot',
    'ENT': 'Entity',
    'ENV': 'Envizen',
    'Q1': 'EPIK Learning',
    '8E': 'Epik One',
    'EPK': 'Epic',
    'XP': 'Epson',
    'EPH': 'Ephone',
    'EPL': 'Eplutus',
    'E7': 'Ergo',
    'EC': 'Ericsson',
    '05': 'Erisson',
    'EE': 'Essential',
    'E2': 'Essentielb',
    '6E': 'eSTAR',
    'ETO': 'ETOE',
    'EN': 'Eton',
    'ET': 'eTouch',
    '1E': 'Etuline',
    'EHL': 'Ehlel',
    'EU': 'Eurostar',
    '4J': 'Eurocase',
    'EUR': 'EUROLUX',
    'EUD': 'Eudora',
    'E9': 'Evercoss',
    'EV': 'Evertek',
    'EVE': 'Everest',
    'EV1': 'Everex',
    'EVR': 'Everis',
    'EVF': 'Everfine',
    'E3': 'Evolio',
    'EO': 'Evolveo',
    '0Q': 'Evoo',
    '5U': 'EVPAD',
    'EVV': 'evvoli',
    'E0': 'EvroMedia',
    'EXR': 'Exertis',
    'XE': 'ExMobile',
    '4Z': 'Exmart',
    'EH': 'EXO',
    'EX': 'Explay',
    'EXP': 'Express LUCK',
    'E5': 'Extrem',
    'EXL': 'ExtraLink',
    'EF': 'EXCEED',
    'QE': 'EWIS',
    'EI': 'Ezio',
    'EZ': 'Ezze',
    'UF': 'EYU',
    'EYE': 'Eyemoo',
    '5F': 'F150',
    'FPS': 'F+',
    'F6': 'Facebook',
    'FAC': 'Facetel',
    'FA1': 'Facime',
    'FA': 'Fairphone',
    'FM': 'Famoco',
    'FAM': 'Famous',
    '17': 'FarEasTone',
    '9R': 'FaRao Pro',
    'FAR': 'Farassoo',
    'FB': 'Fantec',
    'FAN': 'Fanvace',
    'FE': 'Fengxiang',
    'FEN': 'Fenoti',
    'F7': 'Fero',
    '67': 'FEONAL',
    'FI': 'FiGO',
    'J9': 'FiGi',
    'FIG': 'Figgers',
    'F9': 'FiiO',
    'F1': 'FinePower',
    'FX': 'Finlux',
    'F3': 'FireFly Mobile',
    'F8': 'FISE',
    'FIS': 'Fision',
    'FIT': 'FITCO',
    'FLM': 'Filimo',
    'FIL': 'FILIX',
    'FIN': 'FINIX',
    'FL': 'Fly',
    'QC': 'FLYCAT',
    'FLY': 'FLYCOAY',
    'FLU': 'Fluo',
    'FN': 'FNB',
    'FOB': 'Fobem',
    'FD': 'Fondi',
    '0F': 'Fourel',
    '44': 'Four Mobile',
    'F0': 'Fonos',
    'F0N': 'FONTEL',
    'F2': 'FORME',
    'FRM': 'Formovie',
    'F5': 'Formuler',
    'FR': 'Forstar',
    'RF': 'Fortis',
    'FRT': 'FortuneShip',
    'FOX': 'FOX',
    'FO': 'Foxconn',
    'FOD': 'FoxxD',
    'FJ': 'FOODO',
    'FOS': 'FOSSiBOT',
    'FRE': 'free',
    'FT': 'Freetel',
    'FTH': 'FRESH',
    'FEY': 'FreeYond',
    'FRU': 'Frunsi',
    'F4': 'F&U',
    '1F': 'FMT',
    'FPT': 'FPT',
    'FG': 'Fuego',
    'FUJ': 'FUJICOM',
    'FU': 'Fujitsu',
    '4F': 'Funai',
    '5J': 'Fusion5',
    'FF': 'Future Mobile Technology',
    'FFF': 'FFF SmartLife',
    'FW': 'FNF',
    'FXT': 'Fxtec',
    'GT': 'G-TiDE',
    'G9': 'G-Touch',
    'GTB': 'G-Tab',
    'GFO': 'Gfone',
    'GTM': 'GTMEDIA',
    'GTX': 'GTX',
    'GDL': 'GDL',
    '0G': 'GFive',
    'GM': 'Garmin-Asus',
    'GA': 'Gateway',
    '99': 'Galaxy Innovations',
    'GA1': 'Galactic',
    'GAT': 'Galatec',
    'GAM': 'Gamma',
    'GAZ': 'Gazer',
    'GAL': 'Gazal',
    'GEA': 'Geanee',
    'GEN': 'Geant',
    'GD': 'Gemini',
    'GN': 'General Mobile',
    'GD1': 'Genius Devices',
    '2G': 'Genesis',
    'GEP': 'Geo Phone',
    'G2': 'GEOFOX',
    'GE': 'Geotel',
    'Q4': 'Geotex',
    'GEO': 'GEOZON',
    'GNO': 'Getnord',
    'GER': 'Gear Mobile',
    'GH': 'Ghia',
    '2C': 'Ghong',
    'GJ': 'Ghost',
    'GG': 'Gigabyte',
    'GS': 'Gigaset',
    '1G': 'Gini',
    'GZ': 'Ginzzu',
    'GI': 'Gionee',
    'GIR': 'GIRASOLE',
    'G4': 'Globex',
    'GL2': 'GlobalSec',
    'GLB': 'Globmall',
    'GME': 'GlocalMe',
    '38': 'GLONYX',
    'U6': 'Glofiish',
    'GLO': 'Glory Star',
    'GNE': 'GN Electronics',
    'G7': 'GoGEN',
    'GC': 'GOCLEVER',
    '5G': 'Gocomma',
    'GB': 'Gol Mobile',
    'GL': 'Goly',
    'GOL': 'GoldMaster',
    'GOS': 'GoldStar',
    'GOB': 'GOLDBERG',
    'GX': 'GLX',
    'G5': 'Gome',
    'G1': 'GoMobile',
    'GO': 'Google',
    'G0': 'Goophone',
    '6G': 'Gooweel',
    'GOO': 'GOODTEL',
    'GO1': 'GOtv',
    'GPL': 'G-PLUS',
    '8G': 'Gplus',
    'GR': 'Gradiente',
    'GRE': 'Graetz',
    'GP': 'Grape',
    'G6': 'Gree',
    'GRA': 'Great Asia',
    '3G': 'Greentel',
    'GRO': 'Green Orange',
    'GRL': 'Green Lion',
    'GR1': 'GroBerwert',
    'GF': 'Gretel',
    '82': 'Gresso',
    'GRB': 'Grünberg',
    'GU': 'Grundig',
    'GV': 'Gtel',
    'CUO': 'Guophone',
    'CUD': 'CUD',
    'GVC': 'GVC Pro',
    'H13': 'H133',
    '9Z': 'H96',
    'HF': 'Hafury',
    '9F': 'HAOVM',
    'HAQ': 'HAOQIN',
    'HA': 'Haier',
    'HEC': 'HEC',
    'XH': 'Haipai',
    'XHU': 'Haixu',
    'HAN': 'Handheld',
    'HE': 'HannSpree',
    'HNS': 'Hanseatic',
    'HA2': 'Hanson',
    'HK': 'Hardkernel',
    'HAR': 'Harper',
    'HA1': 'Hartens',
    'HS': 'Hasee',
    '8H': 'Hamlet',
    'HAM': 'Hammer',
    'HAT': 'Hathway',
    'HAV': 'HAVIT',
    'HEM': 'Hemilton',
    'H6': 'Helio',
    'HQ': 'HERO',
    'ZH': 'Hezire',
    'HEX': 'HexaByte',
    'HEW': 'HeadWolf',
    'HEI': 'Heimat',
    'HL': 'Hi-Level',
    '3H': 'Hi',
    'HIB': 'Hiberg',
    'HBY': 'HiBy',
    'HIH': 'HiHi',
    'HIK': 'HiKing',
    'H2': 'Highscreen',
    'HI1': 'HIGH1ONE',
    'HIG': 'HiGrace',
    '1H': 'Hipstreet',
    'HIR': 'Hiremco',
    'HI': 'Hisense',
    'HIP': 'HIPER',
    'HC': 'Hitachi',
    'H8': 'Hitech',
    'W3': 'HiMax',
    '8X': 'Hi Nova',
    'HKC': 'HKC',
    'HMD': 'HMD',
    '8W': 'HKPro',
    'HOF': 'HOFER',
    'HOC': 'hoco',
    'H1': 'Hoffmann',
    'HOM': 'Homatics',
    'H0': 'Hometech',
    'HLB': 'HOLLEBERG',
    'HM': 'Homtom',
    'HM1': 'HOMII',
    'HOP': 'Hopeland',
    'HZ': 'Hoozo',
    'HOR': 'Horion',
    'H7': 'Horizon',
    '4H': 'Horizont',
    'HO': 'Hosin',
    'H3': 'Hotel TV Company',
    'HV': 'Hotwav',
    'U8': 'Hot Pepper',
    'HOT': 'HOTACK',
    'JH': 'HOTREALS',
    'HW': 'How',
    'WH': 'Honeywell',
    'HNR': 'Honor',
    'HON': 'HongTop',
    'HOG': 'HONKUAHG',
    'HP': 'HP',
    'HDC': 'HDC',
    'HT': 'HTC',
    'QZ': 'Huagan',
    'HD': 'Huadoo',
    'HG': 'Huavi',
    'HU': 'Huawei',
    'HX': 'Humax',
    'HUM': 'Humanware',
    'HME': 'HUMElab',
    'HR': 'Hurricane',
    'H5': 'Huskee',
    'HUG': 'Hugerock',
    'HY': 'Hyrican',
    'HN': 'Hyundai',
    '7H': 'Hyve',
    'HYT': 'Hytera',
    'HYK': 'Hykker',
    'HYA': 'Hyatta',
    'IKL': 'I KALL',
    '3I': 'i-Cherry',
    'IJ': 'i-Joy',
    'IM': 'i-mate',
    'IO': 'i-mobile',
    'INN': 'I-INN',
    'IPL': 'I-Plus',
    'OF': 'iOutdoor',
    'IB': 'iBall',
    'IY': 'iBerry',
    '7I': 'iBrit',
    'IBO': 'ibowin',
    'I2': 'IconBIT',
    'ING': 'Icone Gold',
    'IC': 'iDroid',
    'IDI': 'iDino',
    '6Z': 'iData',
    'IDC': 'IDC',
    'IG': 'iGet',
    'IHL': 'iHome Life',
    'IH': 'iHunt',
    'IA': 'Ikea',
    'IYO': 'iYou',
    '8I': 'IKU Mobile',
    '2K': 'IKI Mobile',
    'IK': 'iKoMo',
    '58': 'iKon',
    '588': 'iKonia',
    'I7': 'iLA',
    '2I': 'iLife',
    '1I': 'iMars',
    'IMI': 'iMI',
    'U4': 'iMan',
    'ILE': 'iLepo',
    'IL': 'IMO Mobile',
    'IMA': 'Imaq',
    'IM1': 'Imose',
    'I3': 'Impression',
    'FC': 'INCAR',
    '2H': 'Inch',
    '6I': 'Inco',
    'INK': 'Inka',
    'IW': 'iNew',
    'IF': 'Infinix',
    'INF': 'Infiniton',
    'IPR': 'InfinityPro',
    'I0': 'InFocus',
    'IN1': 'InFone',
    'II': 'Inkti',
    'MIR': 'Infomir',
    '81': 'InfoKit',
    'I5': 'InnJoo',
    '26': 'Innos',
    'IN': 'Innostream',
    'I4': 'Inoi',
    'INO': 'iNo Mobile',
    'IQ': 'INQ',
    'QN': 'iQ&T',
    'IS': 'Insignia',
    'YI': 'INSYS',
    'IT': 'Intek',
    'INT': 'Intel',
    'IX': 'Intex',
    'IV': 'Inverto',
    '32': 'Invens',
    '4I': 'Invin',
    'IFT': 'iFIT',
    'INA': 'iNavi',
    'I1': 'iOcean',
    'IMU': 'iMuz',
    'IP': 'iPro',
    'X9': 'iPEGTOP',
    '8Q': 'IQM',
    'Q8': 'IRA',
    'I6': 'Irbis',
    '5I': 'Iris',
    'IRE': 'iReplace',
    'IR': 'iRola',
    'IU': 'iRulu',
    'IRO': 'iRobot',
    '9I': 'iSWAG',
    '9J': 'iSafe Mobile',
    'IST': 'iStar',
    '86': 'IT',
    'IZ': 'iTel',
    '0I': 'iTruck',
    'I8': 'iVA',
    'IE': 'iView',
    '0J': 'iVooMi',
    'UI': 'ivvi',
    'QW': 'iWaylink',
    'I9': 'iZotron',
    'IXT': 'iXTech',
    'IOT': 'IOTWE',
    'JA': 'JAY-Tech',
    'JAM': 'Jambo',
    'JCK': 'Jckkcfug',
    'KJ': 'Jiake',
    'JD': 'Jide',
    'JEE': 'Jeep',
    'J6': 'Jeka',
    'JF': 'JFone',
    'JI': 'Jiayu',
    'JG': 'Jinga',
    'JIN': 'Jin Tu',
    'JX': 'Jio',
    'VJ': 'Jivi',
    'JK': 'JKL',
    'JR1': 'JREN',
    'JO': 'Jolla',
    'JP': 'Joy',
    'JOY': 'JoySurf',
    'UJ': 'Juniper Systems',
    'J5': 'Just5',
    'JUS': 'JUSYEA',
    '7J': 'Jumper',
    'JPA': 'JPay',
    'JV': 'JVC',
    'JXD': 'JXD',
    'JS': 'Jesy',
    'KT': 'K-Touch',
    'KLT': 'K-Lite',
    'K4': 'Kaan',
    'K7': 'Kaiomy',
    'KL': 'Kalley',
    'K6': 'Kanji',
    'KA': 'Karbonn',
    'K5': 'KATV1',
    'ROI': 'KAP',
    'KAP': 'Kapsys',
    'K0': 'Kata',
    'KZ': 'Kazam',
    '9K': 'Kazuna',
    'KD': 'KDDI',
    'KHA': 'Khadas',
    'KS': 'Kempler & Strauss',
    'K3': 'Keneksi',
    'KHI': 'KENSHI',
    'KNW': 'KENWOOD',
    'KX': 'Kenxinda',
    'KEN': 'Kenbo',
    'KND': 'Kendo',
    'KZG': 'KZG',
    'K1': 'Kiano',
    'KID': 'kidiby',
    '5W': 'Kingbox',
    'S4': 'Kingelon',
    'KI': 'Kingsun',
    'KIS': 'Kinstone',
    'KF': 'KINGZONE',
    'KIN': 'Kingstar',
    '46': 'Kiowa',
    'KV': 'Kivi',
    '64': 'Kvant',
    'KVA': 'KVADRA',
    '0K': 'Klipad',
    'KNM': 'KN Mobile',
    'KC': 'Kocaso',
    'KK': 'Kodak',
    'KG': 'Kogan',
    'KGT': 'KGTEL',
    'KM': 'Komu',
    'KMC': 'KMC',
    'KO': 'Konka',
    'KW': 'Konrow',
    'KB': 'Koobee',
    '7K': 'Koolnee',
    'K9': 'Kooper',
    'KP': 'KOPO',
    'KR': 'Koridy',
    'XK': 'Koslam',
    'K2': 'KRONO',
    'KRX': 'Korax',
    'KE': 'Krüger&Matz',
    '5K': 'KREZ',
    'WK': 'KRIP',
    'KRA': 'Kraft',
    'KH': 'KT-Tech',
    'KTC': 'KTC',
    'Z6': 'KUBO',
    'KUG': 'KuGou',
    'K8': 'Kuliao',
    '8K': 'Kult',
    'KU': 'Kumai',
    '6K': 'Kurio',
    'KYD': 'Kydos',
    'KY': 'Kyocera',
    'KQ': 'Kyowon',
    '1K': 'Kzen',
    'LQ': 'LAIQ',
    'LAG': 'LAGENIO',
    'L6': 'Land Rover',
    'L2': 'Landvo',
    'LA': 'Lanix',
    'LA1': 'Lanin',
    'LK': 'Lark',
    'Z3': 'Laurus',
    'LEC': 'Lectrus',
    'LAS': 'Laser',
    'LV': 'Lava',
    'LVI': 'Lville',
    'LC': 'LCT',
    'L5': 'Leagoo',
    'U3': 'Leben',
    'LEB': 'LeBest',
    'LD': 'Ledstar',
    'LEE': 'Leelbox',
    'L1': 'LeEco',
    '4B': 'Leff',
    'LEG': 'Legend',
    'L4': 'Lemhoov',
    'W9': 'LEMFO',
    'LEM': 'Lemco',
    'LN': 'Lenco',
    'LE': 'Lenovo',
    'LT': 'Leotec',
    'LP': 'Le Pan',
    'ZJ': 'Leke',
    'L7': 'Lephone',
    'LZ': 'Lesia',
    'L3': 'Lexand',
    'LX': 'Lexibook',
    'LG': 'LG',
    '39': 'Liberton',
    '5L': 'Linsar',
    'LIN': 'Linsay',
    'LF': 'Lifemaxx',
    'LI': 'Lingwin',
    'LIB': 'Lingbo',
    'LIM': 'Lime',
    'LJ': 'L-Max',
    'LW': 'Linnex',
    'JJ': 'Listo',
    'LNM': 'LNMBBS',
    'LO': 'Loewe',
    'LNG': 'LongTV',
    'YL': 'Loview',
    'LOV': 'Lovme',
    'LGN': 'LOGAN',
    '1L': 'Logic',
    'LH': 'Logic Instrument',
    'LM': 'Logicom',
    'LOG': 'Logik',
    'LGT': 'Logitech',
    'GY': 'LOKMAT',
    '0L': 'Lumigon',
    'LU': 'Lumus',
    'LUM': 'Lumitel',
    'L9': 'Luna',
    'LNN': 'LUNNEN',
    'LUO': 'LUO',
    'LR': 'Luxor',
    'LY': 'LYF',
    'LL': 'Leader Phone',
    'LTL': 'LYOTECH LABS',
    'QL': 'LT Mobile',
    'LW1': 'LW',
    'MQ': 'M.T.T.',
    'MN': 'M4tel',
    'XM': 'Macoox',
    '92': 'MAC AUDIO',
    'MJ': 'Majestic',
    'FQ': 'Mafe',
    'MAG': 'MAG',
    'MA2': 'MAGCH',
    '6Y': 'Magicsee',
    'MA4': 'Magenta',
    '23': 'Magnus',
    'NH': 'Manhattan',
    'MAN': 'Mango',
    '5M': 'Mann',
    'MA': 'Manta Multimedia',
    'Z0': 'Mantra',
    'J4': 'Mara',
    'MAR': 'Marshal',
    '8Y': 'Massgo',
    'MA1': 'Mascom',
    '2M': 'Masstel',
    '3X': 'Mastertech',
    'MAS': 'Master-G',
    '50': 'Matrix',
    'MAT': 'Matco Tools',
    '7M': 'Maxcom',
    '7M1': 'Maxfone',
    'ZM': 'Maximus',
    '6X': 'Maxtron',
    '0D': 'MAXVI',
    'MAX': 'Maxwell',
    'XZ': 'MAXX',
    'MW': 'Maxwest',
    'M0': 'Maze',
    'YM': 'Maze Speed',
    '87': 'Malata',
    'MAU': 'Maunfeld',
    'MCL': 'McLaut',
    '28': 'MBOX',
    'FK': 'MBI',
    'MBK': 'MBK',
    '3D': 'MDC Store',
    '1Y': 'OTT',
    '09': 'meanIT',
    'M3': 'Mecer',
    'M3M': 'M3 Mobile',
    '0M': 'Mecool',
    'MEC': 'MECHEN',
    'MEM': 'MeMobile',
    'MC': 'Mediacom',
    'MD': 'Medion',
    'M2': 'MEEG',
    'MEG': 'MEGA VISION',
    'MCA': 'Megacable',
    'MP': 'MegaFon',
    'MGX': 'MEGAMAX',
    'X0': 'mPhone',
    '3M': 'Meitu',
    'M1': 'Meizu',
    '0E': 'Melrose',
    'MU': 'Memup',
    'ME': 'Metz',
    'MEO': 'MEO',
    'MX': 'MEU',
    'MES': 'MESWAO',
    'MII': 'MIIA',
    'MI': 'MicroMax',
    'MIP': 'mipo',
    'MS': 'Microsoft',
    '6Q': 'Microtech',
    'MIG': 'Mightier',
    '1X': 'Minix',
    'OM': 'Mintt',
    'MIN': 'Mint',
    'MO': 'Mio',
    'MOD': 'Moondrop',
    'MOR': 'MORTAL',
    'X7': 'Mione',
    'M7': 'Miray',
    'MIT': 'Mitchell & Brown',
    '8M': 'Mito',
    'MT': 'Mitsubishi',
    '0Y': 'Mitsui',
    'M5': 'MIXC',
    '2D': 'MIVO',
    '1Z': 'MiXzo',
    'MIW': 'MIWANG',
    'ML': 'MLLED',
    'LS': 'MLS',
    'MLA': 'Microlab',
    '4M': 'Mobicel',
    'M6': 'Mobiistar',
    'MOK': 'Mobile Kingdom',
    'MH': 'Mobiola',
    'MB': 'Mobistel',
    'ID': 'MobiIoT',
    '6W': 'MobiWire',
    '9M': 'Mobo',
    'MOB': 'Mobell',
    'MVO': 'Mobvoi',
    'M4': 'Modecom',
    'MEP': 'Mode Mobile',
    'MF': 'Mofut',
    'MR': 'Motorola',
    'MTS': 'Motorola Solutions',
    'MIV': 'Motiv',
    'MV': 'Movic',
    'MOV': 'Movitel',
    'MO1': 'MOVISUN',
    'MOS': 'Mosimosi',
    'MOX': 'Moxee',
    'MM': 'Mpman',
    'MZ': 'MSI',
    '3R': 'MStar',
    'M9': 'MTC',
    'N4': 'MTN',
    '72': 'M-Tech',
    '9H': 'M-Horse',
    'MKP': 'M-KOPA',
    'MLB': 'multibox',
    '1R': 'Multilaser',
    'MPS': 'MultiPOS',
    'MLT': 'MULTYNET',
    '1M': 'MYFON',
    'MY1': 'myPhone (PL)',
    'MY': 'MyPhone (PH)',
    '51': 'Myros',
    'M8': 'Myria',
    '6M': 'Mystery',
    '3T': 'MyTab',
    'MG': 'MyWigo',
    'J3': 'Mymaga',
    'MYM': 'MyMobile',
    '07': 'MyGica',
    'MYG': 'MygPad',
    'MWA': 'MwalimuPlus',
    'NEO': 'neoCore',
    'NER': 'Neoregent',
    '08': 'Nabi',
    'N7': 'National',
    'NC': 'Navcity',
    '6N': 'Navitech',
    '7V': 'Navitel',
    'N3': 'Navon',
    '7R': 'NavRoad',
    'NAB': 'NABO',
    'NAS': 'NASCO',
    'NP': 'Naomi Phone',
    'NAN': 'Nanho',
    'NE': 'NEC',
    'NDP': 'Nedaphone',
    '8N': 'Necnot',
    'NF': 'Neffos',
    '9X': 'Neo',
    'NEK': 'NEKO',
    '1N': 'Neomi',
    '7Q': 'Neon IQ',
    '8F': 'Neolix',
    'NES': 'Nesons',
    'NET': 'NetBox',
    'NWT': 'NETWIT',
    'NA': 'Netgear',
    'NEM': 'Netmak',
    'NU': 'NeuImage',
    'NEU': 'NeuTab',
    'NEV': 'NEVIR',
    'NW': 'Newgen',
    'N9': 'Newland',
    '0N': 'Newman',
    'NS': 'NewsMy',
    'ND': 'Newsday',
    'HB': 'New Balance',
    'BRI': 'New Bridge',
    'NEW': 'Newal',
    'XB': 'NEXBOX',
    'NX': 'Nexian',
    '7X': 'Nexa',
    '7XR': 'Nexar',
    'N8': 'NEXON',
    'N2': 'Nextbit',
    'NT': 'NextBook',
    'NTT': 'NTT West',
    '4N': 'NextTab',
    'NEX': 'NEXT',
    'NST': 'Next & NextStar',
    'NJO': 'nJoy',
    'NG': 'NGM',
    'NZ': 'NG Optics',
    'NZP': 'NGpon',
    'NN': 'Nikon',
    'NIL': 'NILAIT',
    'NI': 'Nintendo',
    'NIN': 'NINETEC',
    'NI1': 'NINETOLOGY',
    'N5': 'NOA',
    'N1': 'Noain',
    'N6': 'Nobby',
    'NOC': 'Novacom',
    'NOS': 'NoviSea',
    'NO2': 'NOVIS',
    'NOV': 'Novey',
    'NO1': 'NOVO',
    '57': 'Nubia',
    'JN': 'NOBUX',
    'NB': 'Noblex',
    'OG': 'NOGA',
    'NK': 'Nokia',
    'NM': 'Nomi',
    '2N': 'Nomu',
    '6H': 'Noontec',
    'NR': 'Nordmende',
    'NRD': 'Nordfrost',
    'NOR': 'NORMANDE',
    '7N': 'NorthTech',
    'NOT': 'Nothing',
    '5N': 'Nos',
    'NO': 'Nous',
    'NQ': 'Novex',
    'NOD': 'noDROPOUT',
    'NJ': 'NuAns',
    'NL': 'NUU Mobile',
    'N0': 'Nuvo',
    'NUV': 'NuVision',
    'NV': 'Nvidia',
    'NY': 'NYX Mobile',
    'NON': 'N-one',
    'O3': 'O+',
    'OT': 'O2',
    'O7': 'Oale',
    'OC': 'OASYS',
    'OB': 'Obi',
    'OBR': 'Ober',
    'OQ': 'Meta',
    'O1': 'Odys',
    'ODP': 'Odotpad',
    'O9': 'ok.',
    'OKA': 'Okapi',
    'OA': 'Okapia',
    'OKI': 'Oking',
    'OLA': 'Olax',
    'OLK': 'Olkya',
    'OLY': 'Olympia',
    'OCE': 'OCEANIC',
    'OLT': 'OLTO',
    'OJ': 'Ookee',
    'OD': 'Onda',
    'ON': 'OnePlus',
    'ONC': 'OneClick',
    'ONL': 'OneLern',
    'OAN': 'Oangcc',
    'OX': 'Onix',
    'OIN': 'Onida',
    '3O': 'ONYX BOOX',
    'O4': 'ONN',
    '9Q': 'Onkyo',
    'ONV': 'ONVO',
    'OOR': 'Ooredoo',
    '2O': 'OpelMobile',
    'OH': 'Openbox',
    '7Y': 'Obabox',
    'OP': 'OPPO',
    'OO': 'Opsson',
    'OPT': 'Optoma',
    'OPH': 'Ophone',
    'OR': 'Orange',
    'ORP': 'Orange Pi',
    'ORA': 'Orava',
    'O5': 'Orbic',
    'Y6': 'Orbita',
    'ORB': 'Orbsmart',
    'OS': 'Ordissimo',
    '8O': 'Orion',
    'OTT': 'OTTO',
    'OK': 'Ouki',
    '0O': 'OINOM',
    'OIL': 'Oilsky',
    'QK': 'OKWU',
    'QQ': 'OMIX',
    '56': 'OKSI',
    'OE': 'Oukitel',
    'OU': 'OUYA',
    'JB': 'OUJIA',
    'OV': 'Overmax',
    '30': 'Ovvi',
    'O2': 'Owwo',
    'OSC': 'OSCAL',
    'OXT': 'OX TAB',
    'OY': 'Oysters',
    'QF': 'OYSIN',
    'O6': 'Oyyu',
    'OZ': 'OzoneHD',
    'OLL': 'Ollee',
    '7P': 'Mode 1',
    'PRA': 'Pacific Research Alliance',
    'PAG': 'PAGRAER',
    'PAD': '7Ke tree',
    'YP': 'Paladin',
    'PM': 'Palm',
    'PN': 'Panacom',
    'PA': 'Panasonic',
    'PNV': 'Panavox',
    'PT': 'Pantech',
    'PAN': 'Pano',
    'PND': 'Panodic',
    'PA1': 'Panoramic',
    'PLT': 'Platoon',
    'PLD': 'PLDT',
    '94': 'Packard Bell',
    'H9': 'Parrot Mobile',
    'PAR': 'Partner Mobile',
    'PAP': 'PAPYRE',
    'PB': 'PCBOX',
    'PCS': 'PC Smart',
    'PC': 'PCD',
    'PD': 'PCD Argentina',
    'PE': 'PEAQ',
    '8J': 'Pelitt',
    'PEN': 'Penta',
    'PG': 'Pentagram',
    'PQ': 'Pendoo',
    '93': 'Perfeo',
    '1P': 'Phicomm',
    '4P': 'Philco',
    'PH': 'Philips',
    '5P': 'Phonemax',
    'PO': 'phoneOne',
    'PI': 'Pioneer',
    'PIC': 'Pioneer Computers',
    'PJ': 'PiPO',
    '8P': 'Pixelphone',
    '9O': 'Pixela',
    'PX': 'Pixus',
    'PIX': 'PIXPRO',
    'QP': 'Pico',
    'PIR': 'PIRANHA',
    'PIN': 'PINE64',
    '9P': 'Planet Computers',
    'PLA': 'Play Now',
    'PY': 'Ployer',
    'P4': 'Plum',
    'PLU': 'PlusStyle',
    '22': 'Pluzz',
    'P8': 'PocketBook',
    '0P': 'POCO',
    'FH': 'Point Mobile',
    'PV': 'Point of View',
    'PVB': 'PVBox',
    'PL': 'Polaroid',
    'Q6': 'Polar',
    '97': 'PolarLine',
    'PP': 'PolyPad',
    'P5': 'Polytron',
    'P2': 'Pomp',
    'P0': 'Poppox',
    '0X': 'POPTEL',
    'PS': 'Positivo',
    '3P': 'Positivo BGH',
    '3F': 'Porsche',
    'PRT': 'Portfolio',
    'DRE': 'Powerway',
    'PPD': 'PPDS',
    'P3': 'PPTV',
    'FP': 'Premio',
    'PR2': 'PREMIER',
    'PR1': 'Premier Star',
    'PR': 'Prestigio',
    'P9': 'Primepad',
    'PRM': 'PRIME',
    '6P': 'Primux',
    '2P': 'Prixton',
    'PRI': 'Pritom',
    'PRP': 'PRISM+',
    'PF': 'PROFiLO',
    'P6': 'Proline',
    '5O': 'Prology',
    'P1': 'ProScan',
    'PRO': 'PROSONIC',
    'P7': 'Protruly',
    'R0': 'ProVision',
    '7O': 'Polestar',
    'PU': 'PULID',
    'UP': 'Purism',
    'PUN': 'Punos',
    'QFX': 'QFX',
    'Q7': 'Q-Box',
    'QH': 'Q-Touch',
    'QB': 'Q.Bell',
    'QI': 'Qilive',
    'QIN': 'QIN',
    'QIW': 'Qiuwoky',
    'QM': 'QMobile',
    'QT': 'Qtek',
    'Q9': 'QTECH',
    '84': 'Quanta Computer',
    'QA': 'Quantum',
    'QUA': 'Quatro',
    'QU': 'Quechua',
    'QUE': 'Quest',
    'QUI': 'Quipus',
    'QO': 'Qumo',
    'UQ': 'Qubo',
    'QUP': 'Qupi',
    'YQ': 'QLink',
    'QY': 'Qnet Mobile',
    'WJ': 'Qware',
    'QWT': 'QWATT',
    'R2': 'R-TV',
    'R3D': 'R3Di',
    'RA': 'Ramos',
    '0R': 'Raspberry',
    'R9': 'Ravoz',
    'RZ': 'Razer',
    'RAZ': 'RAZZ',
    '95': 'Rakuten',
    'RAY': 'Raylandz',
    'RC': 'RCA Tablets',
    'RCT': 'RCT',
    '2R': 'Reach',
    'RLX': 'Realix',
    'REL': 'RelNAT',
    'RE4': 'Relndoo',
    'RB': 'Readboy',
    'RE': 'Realme',
    'RE1': 'Redbean',
    'R8': 'RED',
    'RDX': 'RED-X',
    'REW': 'Redway',
    '6F': 'Redfox',
    'RE2': 'RedLine',
    'RD': 'Reeder',
    'Z9': 'REGAL',
    'RH': 'Remdun',
    'RP': 'Revo',
    'REV': 'Revomovil',
    '8R': 'Retroid Pocket',
    'REN': 'Renova',
    'RE3': 'RENSO',
    'REP': 'rephone',
    'RHI': 'Rhino',
    'RIC': 'Ricoh',
    'RI': 'Rikomagic',
    'RM': 'RIM',
    'RN': 'Rinno',
    'RNB': 'Ringing Bells',
    'RX': 'Ritmix',
    'R7': 'Ritzviva',
    'RV': 'Riviera',
    '6R': 'Rivo',
    'RIZ': 'Rizzen',
    'RR': 'Roadrover',
    'QR': 'ROADMAX',
    'ROH': 'ROCH',
    'ROC': 'Roam Cat',
    'ROT': 'Rocket',
    'R1': 'Rokit',
    'RK': 'Roku',
    'R3': 'Rombica',
    'RUA': 'Romsat',
    'R5': 'Ross&Moor',
    'RO': 'Rover',
    'R6': 'Rover Computers',
    'RQ': 'RoyQueen',
    'RJ': 'Royole',
    'RT': 'RT Project',
    'RTK': 'RTK',
    'RG': 'RugGear',
    'RUG': 'Ruggex',
    'RUT': 'RuggeTech',
    'RU': 'Runbo',
    'RUN': 'RunGee',
    'RUP': 'Rupa',
    'RL': 'Ruio',
    'RY': 'Ryte',
    'X5': 'Saba',
    '8L': 'S-TELL',
    '8L1': 'S-Color',
    '4O': 'S2Tel',
    '89': 'Seatel',
    'SEW': 'Sewoo',
    'SE1': 'SEEWO',
    'SEN': 'SENNA',
    'SER': 'SERVO',
    'Y7': 'Saiet',
    'SLF': 'SAILF',
    'X1': 'Safaricom',
    'SG': 'Sagem',
    'SAG': 'Sagemcom',
    '4L': 'Salora',
    'SA': 'Samsung',
    'SAT': 'Samtech',
    'SAM': 'Samtron',
    'SAB': 'Sambox',
    'SNA': 'SNAMI',
    'S0': 'Sanei',
    '12': 'Sansui',
    'SAK': 'Sankey',
    'SQ': 'Santin',
    'SY': 'Sanyo',
    'SAN': 'SANY',
    'S9': 'Savio',
    'Y4': 'TCL SCBC',
    'SCH': 'SCHAUB LORENZ',
    'CZ': 'Schneider',
    'SHO': 'SCHONTECH',
    'SCO': 'Scosmos',
    'SC1': 'Scoole',
    'ZG': 'Schok',
    'G8': 'SEG',
    'SEX': 'SEHMAX',
    'SD': 'Sega',
    '0U': 'Selecline',
    '9G': 'Selenga',
    'SV': 'Selevision',
    'SL': 'Selfix',
    '0S': 'SEMP TCL',
    'S1': 'Sencor',
    'SNM': 'Sencrom',
    'SN': 'Sendo',
    '01': 'Senkatel',
    'S6': 'Senseit',
    'EW': 'Senwa',
    '24': 'Seeken',
    'SEB': 'SEBBE',
    '61': 'Seuic',
    'SX': 'SFR',
    'SGI': 'SGIN',
    'SH': 'Sharp',
    'JU': 'Shanling',
    '7S': 'Shift Phones',
    '78': 'Shivaki',
    'RS': 'Shtrikh-M',
    '3S': 'Shuttle',
    '13': 'Sico',
    'SI': 'Siemens',
    '1S': 'Sigma',
    '70': 'Silelis',
    'SJ': 'Silent Circle',
    'SIL': 'Silva Schneider',
    '10': 'Simbans',
    '98': 'Simply',
    'SIM': 'simfer',
    '52': 'Singtech',
    'SIN': 'SINGER',
    '31': 'Siragon',
    'SIS': 'Siswoo',
    '83': 'Sirin Labs',
    '5Z': 'SK Broadband',
    'GK': 'SKG',
    'SW': 'Sky',
    'SK': 'Skyworth',
    'SKY': 'Skyline',
    'SK1': 'SkyStream',
    'SKT': 'Skytech',
    'SKK': 'SKK Mobile',
    '14': 'Smadl',
    '19': 'Smailo',
    'SR': 'Smart Electronic',
    'SMA': 'Smart Kassel',
    'STE': 'Smart Tech',
    '49': 'Smart',
    '47': 'SmartBook',
    '3B': 'Smartab',
    '80': 'SMARTEC',
    'SM1': 'Smartex',
    'SC': 'Smartfren',
    'S7': 'Smartisan',
    'SMU': 'SMUX',
    'SMT': 'SMT Telecom',
    'JR': 'Sylvania',
    'SYH': 'SYH',
    '3Y': 'Smarty',
    'HH': 'Smooth Mobile',
    '1Q': 'Smotreshka',
    'SF': 'Softbank',
    '9L': 'SOLE',
    'JL': 'SOLO',
    'SOS': 'SOSH',
    'SOD': 'Soda',
    'SOL': 'Solas',
    '16': 'Solone',
    'OI': 'Sonim',
    'SVE': 'Sveon',
    'SO': 'Sony',
    'SE': 'Sony Ericsson',
    'X2': 'Soundmax',
    'SUL': 'SoulLink',
    '8S': 'Soyes',
    '77': 'SONOS',
    '68': 'Soho Style',
    'SOB': 'SobieTech',
    'SOW': 'SOWLY',
    'PK': 'Spark NZ',
    'SPX': 'Sparx',
    'FS': 'SPC',
    '6S': 'Spectrum',
    '43': 'Spectralink',
    'SP': 'Spice',
    'SPD': 'Spider',
    'SPU': 'SPURT',
    'QS': 'SQOOL',
    'OL': 'Starlight',
    'STA': 'Star-Light',
    '18': 'Starmobile',
    '2S': 'Starway',
    '45': 'Starwind',
    'SB': 'STF Mobile',
    'S8': 'STK',
    'GQ': 'STG Telecom',
    'S2': 'Stonex',
    'ST': 'Storex',
    'STR': 'StreamSystem',
    '71': 'StrawBerry',
    '96': 'STRONG',
    '69': 'Stylo',
    'STI': 'Stilevs',
    '9S': 'Sugar',
    'SUA': 'SUAAT',
    'SUR': 'Surge',
    'SUF': 'Surfans',
    '06': 'Subor',
    'SUT': 'SULPICE TV',
    'SZ': 'Sumvision',
    'SNG': 'SUNGATE',
    '0H': 'Sunstech',
    'S3': 'SunVan',
    '5S': 'Sunvell',
    '5Y': 'Sunny',
    'W8': 'SUNWIND',
    'SBX': 'SuperBOX',
    'SBM': 'Supermax',
    'SBR': 'Sber',
    'SGE': 'Super General',
    'SU': 'SuperSonic',
    '79': 'SuperTab',
    'STV': 'SuperTV',
    'S5': 'Supra',
    'SUP': 'Supraim',
    'ZS': 'Suzuki',
    '2J': 'Sunmi',
    'SUN': 'Sunmax',
    '0W': 'Swipe',
    'SWI': 'Switel',
    'SS': 'SWISSMOBILITY',
    '1W': 'Swisstone',
    'SWO': 'SWOFY',
    'SSK': 'SSKY',
    'SSM': 'Ssmart',
    'SYC': 'Syco',
    'SM': 'Symphony',
    '4S': 'Syrox',
    'SYS': 'System76',
    'TPS': 'SZ TPS',
    'TM': 'T-Mobile',
    'T96': 'T96',
    'TAD': 'TADAAM',
    'TK': 'Takara',
    '73': 'Tambo',
    '9N': 'Tanix',
    'U5': 'Taiga System',
    'TAL': 'Talius',
    '7G': 'TAG Tech',
    'TLB': 'TALBERG',
    'TAU': 'TAUBE',
    'T5': 'TB Touch',
    'TC': 'TCL',
    'T0': 'TD Systems',
    'YY': 'TD Tech',
    'H4': 'Technicolor',
    'TEA': 'TeachTouch',
    'Z5': 'Technika',
    'TE1': 'Techmade',
    'TX': 'TechniSat',
    'TT': 'TechnoTrend',
    'TTS': 'TECHNOSAT',
    'TM1': 'Temigereev',
    'TP': 'TechPad',
    '9E': 'Techwood',
    '7F': 'Technopc',
    'TCH': 'Techstorm',
    'T7': 'Teclast',
    'TB': 'Tecno Mobile',
    'TEC': 'TecToy',
    '91': 'TEENO',
    'TLK': 'Telkom',
    '2L': 'Tele2',
    'TL': 'Telefunken',
    'TG': 'Telego',
    'T2': 'Telenor',
    'TE': 'Telit',
    '65': 'Telia',
    'TLY': 'Telly',
    'TEL': 'Telma',
    'PW': 'Telpo',
    'TLS': 'TeloSystems',
    'TER': 'Teracube',
    'WR': 'Terra',
    'TD': 'Tesco',
    'TA': 'Tesla',
    '9T': 'Tetratab',
    'TET': 'TETC',
    'TZ': 'teXet',
    '29': 'Teknosa',
    'JZ': 'TJC',
    'TJD': 'TJD',
    'JC': 'TENPLUS',
    'T4': 'ThL',
    'TN': 'Thomson',
    'O0': 'Thuraya',
    'TI': 'TIANYU',
    'JY': 'Tigers',
    '8T': 'Time2',
    'TQ': 'Timovi',
    'TIM': 'TIMvision',
    '2T': 'Tinai',
    'TF': 'Tinmo',
    'TH': 'TiPhone',
    'YV': 'TiVo',
    'TIV': 'Tivax',
    'TIB': 'Tibuta',
    'Y3': 'TOKYO',
    'TOX': 'TOX',
    'T1': 'Tolino',
    '0T': 'Tone',
    'TY': 'Tooky',
    'TYD': 'TYD',
    'TOO': 'TOOGO',
    'TPT': 'Top-Tech',
    'T9': 'Top House',
    'DK': 'Topelotek',
    '42': 'Topway',
    'TO': 'Toplux',
    'TOD': 'TOPDON',
    'TOP': 'TopDevice',
    'TO2': 'TOPSHOWS',
    '7T': 'Torex',
    'TOR': 'Torque',
    'TRN': 'TORNADO',
    '6O': 'TOSCIDO',
    'TO1': 'Topsion',
    'TS': 'Toshiba',
    'T8': 'Touchmate',
    'TOU': 'Touch Plus',
    '5R': 'Transpeed',
    'T6': 'TrekStor',
    'TRP': 'Trecfone',
    'T3': 'Trevi',
    'TRI': 'TriaPlay',
    'TJ': 'Trifone',
    'Q5': 'Trident',
    'TRB': 'Trimble',
    '4T': 'Tronsmart',
    '11': 'True',
    'JT': 'True Slim',
    'J1': 'Trio',
    'TRC': 'Tricolor',
    'THT': 'Tsinghua Tongfang',
    '5C': 'TTEC',
    'TTF': 'TTfone',
    'TTK': 'TTK-TV',
    'TU': 'Tunisie Telecom',
    '1T': 'Turbo',
    'TR': 'Turbo-X',
    '5X': 'TurboPad',
    '5T': 'TurboKids',
    'UR': 'Turkcell',
    '4U': 'TuCEL',
    'TUV': 'Tuvio',
    'TUC': 'TUCSON',
    '2U': 'Türk Telekom',
    'TUR': 'Türksat',
    'TV': 'TVC',
    'TVP': 'TV+',
    'TW': 'TWM',
    'Z1': 'TWZ Corporation',
    'TWN': 'TwinMOS',
    '15': 'Tymes',
    'UC': 'U.S. Cellular',
    'UD1': 'UD',
    'UGI': 'UGINE',
    'UG': 'Ugoos',
    'U1': 'Uhans',
    'UH': 'Uhappy',
    'UL': 'Ulefone',
    'UA': 'Umax',
    'UM': 'UMIDIGI',
    'UM2': 'Umiio',
    'UNT': 'Unitech',
    'UZ': 'Unihertz',
    '3Z': 'UZ Mobile',
    'UX': 'Unimax',
    'UNQ': 'Uniqcell',
    'US': 'Uniscope',
    'UNI': 'Unistrong',
    'U2': 'UNIWA',
    'UND': 'Uniden',
    'BAS': 'Unikalne Smartphones',
    'UNE': 'UNITED',
    'UGR': 'United Group',
    'UO': 'Unnecto',
    'UNN': 'Unnion Technologies',
    'UNP': 'UnoPhone',
    'UU': 'Unonu',
    'UN': 'Unowhy',
    'UY': 'UNNO',
    'UOO': 'UOOGOU',
    'UNB': 'Unblock Tech',
    'UK': 'UTOK',
    '3U': 'IUNI',
    'UT': 'UTStarcom',
    '6U': 'UTime',
    '9U': 'Urovo',
    'UW': 'U-Magic',
    '5V': 'VAIO',
    'WV': 'VAVA',
    'VA': 'Vastking',
    'VAS': 'VASOUN',
    'VP': 'Vargo',
    'VC': 'Vankyo',
    'VAL': 'VALEM',
    'VA2': 'VALE',
    'VAT': 'VALTECH',
    'VAN': 'VANGUARD',
    'VAW': 'VANWIN',
    'VB': 'VC',
    'VEI': 'Veidoo',
    'VN': 'Venso',
    'VNP': 'VNPT Technology',
    'VEN': 'Venstar',
    'UV': 'Venturer',
    'VQ': 'Vega',
    'WC': 'VEON',
    '4V': 'Verico',
    'V4': 'Verizon',
    'VR': 'Vernee',
    'VX': 'Vertex',
    'VE': 'Vertu',
    'VET': 'VETAS',
    'VL': 'Verykool',
    'QV': 'Verssed',
    'VER': 'Versus',
    'V8': 'Vesta',
    'VEK': 'Vekta',
    'VT': 'Vestel',
    '48': 'Vexia',
    'V6': 'VGO TEL',
    'QJ': 'VDVD',
    'VIC': 'Victurio',
    'VD': 'Videocon',
    'VW': 'Videoweb',
    'VS': 'ViewSonic',
    'VIE': 'Viendo',
    'VIK': 'VIKUSHA',
    'V7': 'Vinga',
    'V7T': 'V7',
    'V3': 'Vinsoc',
    'XD': 'Vinabox',
    'FV': 'Vios',
    '0V': 'Vipro',
    'ZV': 'Virzo',
    'VIP': 'Viper',
    'VI': 'Vitelcom',
    'VIB': 'ViBox',
    '8V': 'Viumee',
    'V5': 'Vivax',
    'VIV': 'VIVIMAGE',
    'VI2': 'VIVIBright',
    'VV': 'Vivo',
    '6V': 'VIWA',
    'VII': 'VIIPOO',
    'VID': 'VIDA',
    'VZ': 'Vizio',
    'VIZ': 'Vizmo',
    'VIT': 'Vityaz',
    'VTM': 'Vitumi',
    '9V': 'Vision Touch',
    'VIS': 'Vision Technology',
    'VST': 'Visitech',
    'VIL': 'Visual Land',
    'VI1': 'VILLAON',
    'VIM': 'VIMOQ',
    'VK': 'VK Mobile',
    'JM': 'v-mobile',
    'VHO': 'V-HOPE',
    'VHM': 'V-HOME',
    'VGE': 'V-Gen',
    'V0': 'VKworld',
    'VM': 'Vodacom',
    'VOC': 'VOCAL',
    'VF': 'Vodafone',
    '7W': 'VOGA',
    'V2': 'Vonino',
    '1V': 'Vontar',
    'VG': 'Vorago',
    '2V': 'Vorke',
    '8U': 'Vorcom',
    'JW': 'Vortex',
    'VRX': 'VORTEX (RO)',
    'VOR': 'Vormor',
    'V1': 'Voto',
    'Z7': 'VOX Electronics',
    'VOI': 'VOIX',
    'VO': 'Voxtel',
    'VY': 'Voyo',
    'VOL': 'Völfen',
    'VO1': 'Volt',
    'VOP': 'Volla',
    'V02': 'VOLIA',
    'VH': 'Vsmart',
    'V9': 'Vsun',
    'VU': 'Vulcan',
    '3V': 'VVETIME',
    'ZC': 'VUCATIMES',
    'VO2': 'VOLKANO',
    'VUE': 'Vue Micro',
    'WAK': 'Walker',
    'WA': 'Walton',
    'WAF': 'WAF',
    'WAO': 'W&O',
    'WLT': 'Waltham',
    'WAL': 'Waltter',
    'WAI': 'Wainyok',
    'WAT': 'waipu.tv',
    'WHO': 'Whoop',
    'WBL': 'We. by Loewe.',
    'WCP': 'WeChip',
    'WM': 'Weimei',
    'WM1': 'Weiimi',
    'WE': 'WellcoM',
    'W6': 'WELLINGTON',
    'WD': 'Western Digital',
    'WST': 'Weston',
    'WT': 'Westpoint',
    'WAN': 'Zhongyu Display',
    'WA1': 'WANSA',
    'WY': 'Wexler',
    '3W': 'WE',
    'WEC': 'Wecool',
    'WEE': 'Weelikeit',
    'WP': 'Wieppo',
    'W2': 'Wigor',
    'WI': 'Wiko',
    'WF': 'Wileyfox',
    'WLR': 'WildRed',
    'WS': 'Winds',
    'WN': 'Wink',
    '9W': 'Winmax',
    'W5': 'Winnovo',
    'WU': 'Wintouch',
    'WIS': 'Winstar',
    'W0': 'Wiseasy',
    '2W': 'Wizz',
    'W4': 'WIWA',
    'WIZ': 'WizarPos',
    'WL': 'Wolder',
    'WG': 'Wolfgang',
    'WQ': 'Wolki',
    'WON': 'WONDER',
    'WO': 'Wonu',
    'W1': 'Woo',
    'WX': 'Woxter',
    'WOZ': 'WOZIFAN',
    'XQ': 'X-AGE',
    'XEL': 'XElectron',
    'X3': 'X-BO',
    'XBI': 'XB',
    'XMO': 'X-Mobile',
    'XT': 'X-TIGI',
    'XV': 'X-View',
    'X4': 'X.Vision',
    'X88': 'X88',
    'X96': 'X96',
    '96Q': 'X96Q',
    'A95': 'A95X',
    'XG': 'Xgody',
    'XGE': 'XGEM',
    'QX': 'XGIMI',
    'XL': 'Xiaolajiao',
    'XI': 'Xiaomi',
    'XW': 'Xiaodu',
    'XN': 'Xion',
    'XO': 'Xolo',
    'XR': 'Xoro',
    'XPP': 'XPPen',
    'XRL': 'XREAL',
    'XS': 'Xshitou',
    'XSM': 'Xsmart',
    '4X': 'Xtouch',
    'X8': 'Xtratech',
    'XCR': 'Xcruiser',
    'XCO': 'XCOM',
    'XCL': 'Xcell',
    'XWA': 'Xwave',
    'YD': 'Yandex',
    'YA': 'Yarvik',
    'Y2': 'Yes',
    'YES': 'Yestel',
    'YE': 'Yezz',
    'YG': 'YEPEN',
    'YEL': 'YELLYOUTH',
    'YK': 'Yoka TV',
    'YO': 'Yota',
    'YOU': 'Youin',
    'YO1': 'Youwei',
    'YOO': 'Yooz',
    'YT': 'Ytone',
    'Y9': 'YOTOPT',
    'Y1': 'Yu',
    'YF': 'YU Fly',
    'Y0': 'YUHO',
    'YN': 'Yuno',
    'YUN': 'YUNDOO',
    'YUS': 'YunSong',
    'YUM': 'YUMKEM',
    'YIK': 'YIKEMI',
    'YU': 'Yuandao',
    'YS': 'Yusun',
    'YJ': 'YASIN',
    'YX': 'Yxtel',
    '0Z': 'Zatec',
    '2Z': 'Zaith',
    'ZAM': 'Zamolxe',
    'ZAL': 'ZALA',
    'ZZB': 'ZZB',
    'ZEA': 'Zealot',
    'PZ': 'Zebra',
    'ZE1': 'Zeblaze',
    'ZE': 'Zeemi',
    'WZ': 'Zeeker',
    'ZN': 'Zen',
    'ZK': 'Zenek',
    'ZL': 'Zentality',
    'ZF': 'Zfiner',
    'ZI': 'Zidoo',
    'FZ': 'ZIFRO',
    'ZIF': 'ZIFFLER',
    'ZIO': 'ZIOVO',
    'ZX': 'Ziox',
    'ZIK': 'ZIK',
    'ZKI': 'Z-Kai',
    'ZIG': 'Zigo',
    'ZIM': 'Zimmer',
    'ZIN': 'Zinox',
    'ZO': 'Zonda',
    'ZW': 'Zonko',
    'ZP': 'Zopo',
    'ZOO': 'ZoomSmart',
    'ZO1': 'Zoom',
    'ZT': 'ZTE',
    'ZU': 'Zuum',
    'ZY': 'Zync',
    'ZR': 'Zyrex',
    'ZQ': 'ZYQ',
    'Z4': 'ZH&K',
    'OW': 'öwn',
    'WBF': 'Webfleet',
    'WSS': 'WS',
    # legacy brands, might be removed in future versions
    'WB': 'Web TV',
    'XX': 'Unknown',
}
# flip Abbrev / Brand for fast membership testing
BRAND_TO_ABBREV = {brand.lower(): abbrev for abbrev, brand in DEVICE_BRANDS.items()}


class BaseDeviceParser(Parser):
    DEVICE_TYPE = DeviceType.Unknown
    DEVICE_BRANDS = DEVICE_BRANDS
    BRAND_TO_ABBREV = BRAND_TO_ABBREV

    __slots__ = ()

    # -----------------------------------------------------------------------------
    # UA parsing methods
    # -----------------------------------------------------------------------------
    def extract_model(self) -> None:
        """
        Brand has list of model regexes to parse
        """
        user_agent = self.user_agent
        for model in self.ua_data.pop('models', []):
            if model_matched := model['regex'].search(user_agent):
                self.ua_data |= {k: v.strip() for k, v in model.items() if k != 'regex'}
                self.ua_data['model'] = perform_model_substitutions(
                    model['model'], model_matched, ' '
                )
                return

        if name := self.ua_data.get('model', ''):
            if "\\g<" in name:
                self.ua_data['model'] = perform_model_substitutions(name, self.matched_regex, ' ')

    def dtype(self) -> DeviceType | str:
        return self.DEVICE_TYPE

    def device_type_from_fixture(self) -> DeviceType:
        """
        The regex fixture may contain the "device" key
        which should be inserted as "type" in the ua_data.
        """
        return self.ua_data.get('device', DeviceType.Unknown)

    def set_details(self) -> None:
        """
        Set device data from UA or Client Hints.
        """
        if self.ua_data:
            self.extract_model()

            self.ua_data |= {
                'type': self.dtype(),
                'version': self.set_version(self.ua_data.get('version', '')),
            }

            return super().set_details()


def perform_model_substitutions(
    substring: str, regex_match: regex.Match, underscore_substitute: str
) -> str:
    """
    Perform several normalizations after default regex substitution
    """
    value = perform_substitutions(substring, regex_match, underscore_substitute)
    if not value or value == 'Build':
        return ''

    # normalize D510_TD / ETON-T730D_TD
    # Tbook 16 Power(M5F8) Build
    for suffix in (' TD', ' Build'):
        value = value.removesuffix(suffix)

    if value.endswith('))'):
        return value[:-1]

    return value


__all__ = (
    'BaseDeviceParser',
    'DEVICE_BRANDS',
    'MOBILE_DEVICE_TYPES',
)
