// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is used to generate the switch statements in the Locale class.
// See: ../lib/ui/window.dart

// When running this script, use the output of this script to update the
// comments that say when the script was last run (that comment appears twice in
// window.dart), and then replace all the map entries with the output from
// this script (the first set for _canonicalizeLanguageCode and the second set
// for _canonicalizeRegionCode).

import 'dart:async';
import 'dart:convert';
import 'dart:io';

const String registry = 'https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry';

Map<String, List<String>> parseSection(String section) {
  final Map<String, List<String>> result = <String, List<String>>{};
  List<String> lastHeading;
  for (String line in section.split('\n')) {
    if (line == '')
      continue;
    if (line.startsWith('  ')) {
      lastHeading[lastHeading.length - 1] = '${lastHeading.last}${line.substring(1)}';
      continue;
    }
    final int colon = line.indexOf(':');
    if (colon <= 0)
      throw 'not sure how to deal with "$line"';
    final String name = line.substring(0, colon);
    final String value = line.substring(colon + 2);
    lastHeading = result.putIfAbsent(name, () => <String>[]);
    result[name].add(value);
  }
  return result;
}

Future<Null> main() async {
  final HttpClient client = new HttpClient();
  final String body = (await (await (await client.getUrl(Uri.parse(registry))).close()).transform(utf8.decoder).toList()).join('');
  final List<Map<String, List<String>>> sections = body.split('%%').map<Map<String, List<String>>>(parseSection).toList();
  final Map<String, List<String>> outputs = <String, List<String>>{'language': <String>[], 'region': <String>[]};
  String fileDate;
  for (Map<String, List<String>> section in sections) {
    if (fileDate == null) {
      // first block should contain a File-Date metadata line.
      fileDate = section['File-Date'].single;
      continue;
    }
    assert(section.containsKey('Type'), section.toString());
    final String type = section['Type'].single;
    if ((type == 'language' || type == 'region') && (section.containsKey('Preferred-Value'))) {
      assert(section.containsKey('Subtag'), section.toString());
      final String subtag = section['Subtag'].single;
      final List<String> descriptions = section['Description'];
      assert(descriptions.isNotEmpty);
      assert(section.containsKey('Deprecated'));
      final String comment = section.containsKey('Comment') ? section['Comment'].single : 'deprecated ${section['Deprecated'].single}';
      final String preferredValue = section['Preferred-Value'].single;
      outputs[type].add('\'$subtag\': \'$preferredValue\', // ${descriptions.join(", ")}; $comment');
    }
  }
  print('// Mappings generated for language subtag registry as of $fileDate.');
  print('// For languageCode:');
  print(outputs['language'].join('\n'));
  print('// For regionCode:');
  print(outputs['region'].join('\n'));
}
