// Copyright 2014 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.

// @dart = 2.8

/// This program extracts localized date symbols and patterns from the intl
/// package for the subset of locales supported by the flutter_localizations
/// package.
///
/// The extracted data is written into:
///   packages/flutter_localizations/lib/src/l10n/generated_date_localizations.dart
///
/// ## Usage
///
/// Run this program from the root of the git repository.
///
/// The following outputs the generated Dart code to the console as a dry run:
///
/// ```
/// dart dev/tools/localization/bin/gen_date_localizations.dart
/// ```
///
/// If the data looks good, use the `--overwrite` option to overwrite the
/// lib/src/l10n/date_localizations.dart file:
///
/// ```
/// dart dev/tools/localization/bin/gen_date_localizations.dart --overwrite
/// ```

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

import 'package:path/path.dart' as path;

import '../localizations_utils.dart';

const String _kCommandName = 'gen_date_localizations.dart';

// Used to let _jsonToMap know what locale it's date symbols converting for.
// Date symbols for the Kannada locale ('kn') are handled specially because
// some of the strings contain characters that can crash Emacs on Linux.
// See packages/flutter_localizations/lib/src/l10n/README for more information.
String currentLocale;

Future<void> main(List<String> rawArgs) async {
  checkCwdIsRepoRoot(_kCommandName);

  final bool writeToFile = parseArgs(rawArgs).writeToFile;

  final File dotPackagesFile = File(path.join('packages', 'flutter_localizations', '.packages'));
  final bool dotPackagesExists = dotPackagesFile.existsSync();

  if (!dotPackagesExists) {
    exitWithError(
      'File not found: ${dotPackagesFile.path}. $_kCommandName must be run '
      'after a successful "flutter update-packages".'
    );
  }

  final String pathToIntl = dotPackagesFile
    .readAsStringSync()
    .split('\n')
    .firstWhere(
      (String line) => line.startsWith('intl:'),
      orElse: () {
        exitWithError('intl dependency not found in ${dotPackagesFile.path}');
        return null; // unreachable
      },
    )
    .split(':')
    .last;

  final Directory dateSymbolsDirectory = Directory(path.join(pathToIntl, 'src', 'data', 'dates', 'symbols'));
  final Map<String, File> symbolFiles = _listIntlData(dateSymbolsDirectory);
  final Directory datePatternsDirectory = Directory(path.join(pathToIntl, 'src', 'data', 'dates', 'patterns'));
  final Map<String, File> patternFiles = _listIntlData(datePatternsDirectory);
  final StringBuffer buffer = StringBuffer();
  final Set<String> supportedLocales = _supportedLocales();

  buffer.writeln(
'''
// Copyright 2014 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 has been automatically generated. Please do not edit it manually.
// To regenerate run (omit --overwrite to print to console instead of the file):
// dart --enable-asserts dev/tools/localization/bin/gen_date_localizations.dart --overwrite

'''
);
  buffer.writeln('''
/// The subset of date symbols supported by the intl package which are also
/// supported by flutter_localizations.''');
  buffer.writeln('const Map<String, dynamic> dateSymbols = <String, dynamic> {');
  symbolFiles.forEach((String locale, File data) {
    currentLocale = locale;
    if (supportedLocales.contains(locale))
      buffer.writeln(_jsonToMapEntry(locale, json.decode(data.readAsStringSync())));
  });
  currentLocale = null;
  buffer.writeln('};');

  // Code that uses datePatterns expects it to contain values of type
  // Map<String, String> not Map<String, dynamic>.
  buffer.writeln('''
/// The subset of date patterns supported by the intl package which are also
/// supported by flutter_localizations.''');
  buffer.writeln('const Map<String, Map<String, String>> datePatterns = <String, Map<String, String>> {');
  patternFiles.forEach((String locale, File data) {
    if (supportedLocales.contains(locale)) {
      final Map<String, dynamic> patterns = json.decode(data.readAsStringSync()) as Map<String, dynamic>;
      buffer.writeln("'$locale': <String, String>{");
      patterns.forEach((String key, dynamic value) {
        assert(value is String);
        buffer.writeln(_jsonToMapEntry(key, value));
      });
      buffer.writeln('},');
    }
  });
  buffer.writeln('};');

  if (writeToFile) {
    final File dateLocalizationsFile = File(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n', 'generated_date_localizations.dart'));
    dateLocalizationsFile.writeAsStringSync(buffer.toString());
    Process.runSync(path.join('bin', 'cache', 'dart-sdk', 'bin', 'dartfmt'), <String>[
      '-w',
      dateLocalizationsFile.path,
    ]);
  } else {
    print(buffer);
  }
}

String _jsonToMapEntry(String key, dynamic value) {
  return "'$key': ${_jsonToMap(value)},";
}

String _jsonToMap(dynamic json) {
  if (json == null || json is num || json is bool)
    return '$json';

  if (json is String)
    return generateEncodedString(currentLocale, json);

  if (json is Iterable) {
    final StringBuffer buffer = StringBuffer('<dynamic>[');
    for (final dynamic value in json) {
      buffer.writeln('${_jsonToMap(value)},');
    }
    buffer.write(']');
    return buffer.toString();
  }

  if (json is Map<String, dynamic>) {
    final StringBuffer buffer = StringBuffer('<String, dynamic>{');
    json.forEach((String key, dynamic value) {
      buffer.writeln(_jsonToMapEntry(key, value));
    });
    buffer.write('}');
    return buffer.toString();
  }

  throw 'Unsupported JSON type ${json.runtimeType} of value $json.';
}

Set<String> _supportedLocales() {
  // Assumes that en_US is a supported locale by default. Without this, usage
  // of the intl package APIs before Flutter populates its set of supported i18n
  // date patterns and symbols may cause problems.
  //
  // For more context, see https://github.com/flutter/flutter/issues/67644.
  final Set<String> supportedLocales = <String>{
    'en_US',
  };
  final RegExp filenameRE = RegExp(r'(?:material|cupertino)_(\w+)\.arb$');
  final Directory supportedLocalesDirectory = Directory(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n'));
  for (final FileSystemEntity entity in supportedLocalesDirectory.listSync()) {
    final String filePath = entity.path;
    if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath)) {
      supportedLocales.add(filenameRE.firstMatch(filePath)[1]);
    }
  }

  return supportedLocales;
}

Map<String, File> _listIntlData(Directory directory) {
  final Map<String, File> localeFiles = <String, File>{};
  final Iterable<File> files = directory
    .listSync()
    .whereType<File>()
    .where((File file) => file.path.endsWith('.json'));
  for (final File file in files) {
    final String locale = path.basenameWithoutExtension(file.path);
    localeFiles[locale] = file;
  }

  final List<String> locales = localeFiles.keys.toList(growable: false);
  locales.sort();
  return Map<String, File>.fromIterable(locales, value: (dynamic locale) => localeFiles[locale]);
}
