import * as fs from 'fs' ; import { join } from 'path' ; import * as zlib from 'zlib' ; import { getSupplemental } from '../../../cldr' ; import { objectToString , Code , HEADER , NOLINT_MAXLINE } from './util' ; import { parseLanguageTag , LanguageTag } from '@phensley/cldr-core' ; import { inspect } from 'util' ; const enum Tag { LANGUAGE = 0 , SCRIPT = 1 , REGION = 2 } /**
 * Split string into lines and split each line into a colon-delimited
 * key / value pair, and convert each group into an object.
 */ const parseSubtagBlock = ( raw ) : { [ x ] : string ; } => { return raw . trim ( ) . split ( '\n' ) . map ( ( s ) => { const i = s . indexOf ( ':' ) ; return [ s . substring ( 0 , i ) , s . substring ( i + 1 ) ] ; } ) . reduce ( ( o , [ k , v ] ) => { o [ k . trim ( ) ] = v . trim ( ) ; return o ; } , { } ) ; } ; const getIanaSubtags = ( ) => { const path = join ( __dirname , '..' , '..' , '..' , '..' , 'data' , 'raw-iana-subtags.txt.gz' ) ; const raw = fs . readFileSync ( path ) ; const data = zlib . gunzipSync ( raw ) . toString ( 'utf-8' ) ; return data . split ( '%%' ) . map ( parseSubtagBlock ) . filter ( ( r ) => r . Type ) ; } ; const pruneRegion = ( m ) : void => Object . keys ( m ) . forEach ( ( k ) => { const v = m [ k ] ; if ( v . endsWith ( '-ZZ' ) ) { m [ k ] = v . substring ( 0 , - 3 ) ; } } ) ; interface FakeLanguageTag { core : ( string | number ) [ ] ; _extensions ? : string [ ] ; _privateUse ? : string ; } /**
 * Omit keys whose value is empty.
 */ const filterSubtags = ( likely ) => { return Object . keys ( likely ) . reduce ( ( p , key ) => { const val = likely [ key ] ; if ( val ) { p [ key ] = val ; } return p ; } , { } as any ) ; } ; export type FastTag = ( string | number ) [ ] ; export const fastTag = ( real ) : FastTag => { const fake = real as any as FakeLanguageTag ; const language = fake . core [ Tag . LANGUAGE ] ; const script = fake . core [ Tag . SCRIPT ] ; const region = fake . core [ Tag . REGION ] ; return [ language || Tag . LANGUAGE , script || Tag . SCRIPT , region || Tag . REGION ] ; } ; const putMap = ( map , key ) => { let val = map [ key ] ; if ( val === undefined ) { val = { } ; map [ key ] = val ; } return val ; } ; const buildSubtags = ( likely ) => { likely = filterSubtags ( likely ) ; const index = { } ; const scripts = [ ] ; Object . keys ( likely ) . sort ( ) . forEach ( ( k ) => { const key = fastTag ( parseLanguageTag ( k ) ) ; const val = fastTag ( parseLanguageTag ( likely [ k ] ) ) ; const map = putMap ( putMap ( index , key [ Tag . LANGUAGE ] ) , key [ Tag . SCRIPT ] ) ; const script = val [ Tag . SCRIPT ] ; let scriptid = scripts . indexOf ( script as string ) ; if ( scriptid === - 1 ) { scriptid = scripts . length ; scripts . push ( script as string ) ; } val [ Tag . SCRIPT ] = scriptid ; const _val = val . map ( ( t , i ) => ( i === Tag . LANGUAGE && t === key [ Tag . LANGUAGE ] ) || ( i === Tag . REGION && t === key [ Tag . REGION ] ) ? '' : t ) . join ( '-' ) ; map [ key [ Tag . REGION ] ] = _val ; } ) ; index . _ = scripts ; return index ; } ; const encodekey = ( s ) => { if ( /\d+/ . test ( s ) ) { const n = parseInt ( s , 10 ) ; if ( isFinite ( n ) && ( s . length === 1 || s [ 0 ] !== '0' ) ) { return s ; } return `'${ s }'` ; } return s ; } ; const encode = ( o ) : string => { if ( Array . isArray ( o ) ) { return '[' + o . map ( encode ) . join ( ',' ) + ']' ; } else if ( typeof o === 'object' ) { return ( '{' + Object . keys ( o ) . map ( ( k ) => encodekey ( k ) + ':' + encode ( o [ k ] ) ) . join ( ',' ) + '}' ) ; } else if ( typeof o === 'string' && o . length ) { return `'${ o }'` ; } else if ( typeof o === 'number' ) { return `${ o }` ; } else if ( ! o ) { return `` ; } else { throw new Error ( `invalid type ${ typeof o }: ${ inspect ( o ) }` ) ; } return '' ; } ; export const getSubtags = ( _data ) : Code [ ] => { const result = [ ] ; const supplemental = getSupplemental ( ) ; const ianaSubtags = getIanaSubtags ( ) ; const grandfathered = objectToString ( ianaSubtags . filter ( ( r ) => r . Type === 'grandfathered' ) . reduce ( ( o , r ) => { const tag = r . Tag ; o [ tag ] = r [ 'Preferred-Value' ] ; return o ; } , { } ) ) ; pruneRegion ( supplemental . LikelySubtags ) ; const likely = buildSubtags ( supplemental . LikelySubtags ) ; let code = HEADER + NOLINT_MAXLINE ; code += `export const grandfatheredRaw = '${ grandfathered }';\n` ; result . push ( Code . languagetag ( [ 'autogen.subtags.ts' ] , code ) ) ; code = HEADER + NOLINT_MAXLINE ; code += `export const likelySubtags: any = ${ encode ( likely ) };\n` ; result . push ( Code . locale ( [ 'autogen.subtags.ts' ] , code ) ) ; return result ; } ;