import { sortSet , Code , HEADER , NOLINT_MAXLINE } from './util' ; type StringMap = { [ x ] : string ; } ; export type MapSet = { [ x ] : Set < string > ; } ; const BASE = 0x03b1 ; /**
 * Create or update a set stored in a map under the given key.
 */ const mapSet = ( map , key , val ) => { let values = map [ key ] ; if ( values === undefined ) { values = new Set < string > ( ) ; map [ key ] = values ; } values . add ( val ) ; } ; /**
 * Populate the various structures that make up the partition table.
 *
 * // TODO: may move this into the compiler and load the data
 * directly into the table at runtime.
 */ export const buildPartitions = ( data ) => { const { territoryContainment , matchVariables } = data ; let partitionIdSequence = 0 ; const getPartitionId = ( ids , vars ) => { const key = sortSet ( vars ) . join ( ', ' ) ; let id = ids [ key ] ; if ( id === undefined ) { id = String . fromCharCode ( BASE + partitionIdSequence ++ ) ; ids [ key ] = id ; } return id ; } ; const partitionIdInverse = { } ; const variableToPartitionIds = { } ; const regionToPartition = { } ; const macroRegionToPartitions = { } ; const partitionIds = { } ; const regionToVariables = { } ; const partitionToRegions = { } ; const allCountries = territoryContainment [ '001' ] ; Object . keys ( matchVariables ) . sort ( ) . forEach ( ( variable ) => { const countries = matchVariables [ variable ] . sort ( ) ; const inverse = new Set < string > ( allCountries ) ; countries . forEach ( ( country ) => { mapSet ( regionToVariables , country , variable ) ; inverse . delete ( country ) ; } ) ; const inverseVar = '$!' + variable . substring ( 1 ) ; sortSet ( inverse ) . forEach ( ( country ) => { mapSet ( regionToVariables , country , inverseVar ) ; } ) ; } ) ; Object . keys ( regionToVariables ) . sort ( ) . forEach ( ( country ) => { const vars = regionToVariables [ country ] ; const partitionId = getPartitionId ( partitionIds , vars ) ; mapSet ( partitionToRegions , partitionId , country ) ; mapSet ( regionToPartition , country , partitionId ) ; vars . forEach ( ( v ) => { mapSet ( variableToPartitionIds , v , partitionId ) ; } ) ; } ) ; Object . keys ( territoryContainment ) . sort ( ) . forEach ( ( macro ) => { territoryContainment [ macro ] . forEach ( ( country ) => { const vars = regionToVariables [ country ] ; const partitionId = getPartitionId ( partitionIds , vars ) ; mapSet ( macroRegionToPartitions , macro , partitionId ) ; } ) ; } ) ; Object . keys ( partitionIds ) . forEach ( ( k ) => ( partitionIdInverse [ k ] = partitionIds [ k ] ) ) ; let table = '# Generated by @phensley/cldr-compiler\n\n' ; Object . keys ( partitionIdInverse ) . sort ( ) . forEach ( ( vars ) => { const id = partitionIdInverse [ vars ] ; table += `${ id } -> ${ vars }\n` ; } ) ; table += '\n' ; Object . keys ( macroRegionToPartitions ) . sort ( ) . forEach ( ( macro ) => { const partition = sortSet ( macroRegionToPartitions [ macro ] ) . join ( ', ' ) ; table += `${ macro }  [${ partition }]\n` ; } ) ; table += '\n' ; Object . keys ( regionToPartition ) . sort ( ) . forEach ( ( region ) => { const partition = sortSet ( regionToPartition [ region ] ) . join ( ', ' ) ; table += `${ region }  [${ partition }]\n` ; } ) ; return { variables : variableToPartitionIds , macroRegions : macroRegionToPartitions , regions : regionToPartition , table , } ; } ; const encode = ( ms ) : string => Object . keys ( ms ) . map ( ( k ) => `${ k }:${ sortSet ( ms [ k ] ) . join ( '' ) }` ) . join ( '|' ) ; export const getPartition = ( data ) : Code [ ] => { const { macroRegions , regions , table } = buildPartitions ( data ) ; let code = HEADER ; let str = '' ; str = encode ( regions ) ; code += NOLINT_MAXLINE ; code += `export const regions = '${ str }';\n\n` ; str = encode ( macroRegions ) ; code += NOLINT_MAXLINE ; code += `export const macroRegions = '${ str }';\n` ; return [ Code . localematcher ( [ 'autogen.partition.ts' ] , code ) , Code . top ( [ 'notes' , 'language-partition-table.txt' ] , table ) , ] ; } ;