// 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 program generates getMaterialTranslation(), getCupertinoTranslation(),
// and getWidgetsTranslation() functions that look up the translations provided by
// the arb files. The returned value is a generated instance of a
// GlobalMaterialLocalizations, GlobalCupertinoLocalizations, or
// GlobalWidgetsLocalizations object that corresponds to a single locale.
//
// The *.arb files are in packages/flutter_localizations/lib/src/l10n.
//
// The arb (JSON) format files must contain a single map indexed by locale.
// Each map value is itself a map with resource identifier keys and localized
// resource string values.
//
// The arb filenames are expected to have the form "material_(\w+)\.arb" or
// "cupertino_(\w+)\.arb" where the group following "_" identifies the language
// code and the country code, e.g. "material_en.arb" or "material_en_GB.arb".
// In most cases both codes are just two characters.
//
// This app is typically run by hand when a module's .arb files have been
// updated.
//
// ## 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_localizations.dart
// ```
//
// If you have removed localizations from the canonical localizations, then
// add the '--remove-undefined' flag to also remove them from the other files.
//
// ```
// dart dev/tools/localization/bin/gen_localizations.dart --remove-undefined
// ```
//
// If the data looks good, use the `-w` or `--overwrite` option to overwrite the
// generated_material_localizations.dart, generated_cupertino_localizations.dart,
// and generated_widgets_localizations.dart files in packages/flutter_localizations/lib/src/l10n/:
//
// ```
// dart dev/tools/localization/bin/gen_localizations.dart --overwrite
// ```

import 'dart:io';

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

import '../gen_cupertino_localizations.dart';
import '../gen_material_localizations.dart';
import '../gen_widgets_localizations.dart';
import '../localizations_utils.dart';
import '../localizations_validator.dart';
import 'encode_kn_arb_files.dart';

/// This is the core of this script; it generates the code used for translations.
String generateArbBasedLocalizationSubclasses({
  required Map<LocaleInfo, Map<String, String>> localeToResources,
  required Map<LocaleInfo, Map<String, dynamic>> localeToResourceAttributes,
  required String generatedClassPrefix,
  required String baseClass,
  required HeaderGenerator generateHeader,
  required ConstructorGenerator generateConstructor,
  ConstructorGenerator? generateConstructorForCountrySubClass,
  required String factoryName,
  required String factoryDeclaration,
  required bool callsFactoryWithConst,
  required String factoryArguments,
  required String supportedLanguagesConstant,
  required String supportedLanguagesDocMacro,
}) {
  assert(generatedClassPrefix.isNotEmpty);
  assert(baseClass.isNotEmpty);
  assert(factoryName.isNotEmpty);
  assert(factoryDeclaration.isNotEmpty);
  assert(factoryArguments.isNotEmpty);
  assert(supportedLanguagesConstant.isNotEmpty);
  assert(supportedLanguagesDocMacro.isNotEmpty);
  generateConstructorForCountrySubClass ??= generateConstructor;
  final output = StringBuffer();
  output.writeln(
    generateHeader('dart dev/tools/localization/bin/gen_localizations.dart --overwrite'),
  );

  final supportedLocales = StringBuffer();

  final languageToLocales = <String, List<LocaleInfo>>{};
  final languageToScriptCodes = <String, Set<String>>{};
  // Used to calculate if there are any corresponding countries for a given language and script.
  final languageAndScriptToCountryCodes = <LocaleInfo, Set<String>>{};
  final allResourceIdentifiers = <String>{};
  for (final LocaleInfo locale in localeToResources.keys.toList()..sort()) {
    if (locale.scriptCode != null) {
      languageToScriptCodes[locale.languageCode] ??= <String>{};
      languageToScriptCodes[locale.languageCode]!.add(locale.scriptCode!);
    }
    if (locale.countryCode != null && locale.scriptCode != null) {
      final key = LocaleInfo.fromString('${locale.languageCode}_${locale.scriptCode}');
      languageAndScriptToCountryCodes[key] ??= <String>{};
      languageAndScriptToCountryCodes[key]!.add(locale.countryCode!);
    }
    languageToLocales[locale.languageCode] ??= <LocaleInfo>[];
    languageToLocales[locale.languageCode]!.add(locale);
    allResourceIdentifiers.addAll(localeToResources[locale]!.keys.toList()..sort());
  }

  // We generate one class per supported language (e.g.
  // `MaterialLocalizationEn`). These implement everything that is needed by the
  // superclass (e.g. GlobalMaterialLocalizations).

  // We also generate one subclass for each locale with a script code (e.g.
  // `MaterialLocalizationZhHant`). Their superclasses are the aforementioned
  // language classes for the same locale but without a script code (e.g.
  // `MaterialLocalizationZh`).

  // We also generate one subclass for each locale with a country code (e.g.
  // `MaterialLocalizationEnGb`). Their superclasses are the aforementioned
  // language classes for the same locale but without a country code (e.g.
  // `MaterialLocalizationEn`).

  // If scriptCodes for a language are defined, we expect a scriptCode to be
  // defined for locales that contain a countryCode. The superclass becomes
  // the script subclass (e.g. `MaterialLocalizationZhHant`) and the generated
  // subclass will also contain the script code (e.g. `MaterialLocalizationZhHantTW`).

  // When scriptCodes are not defined for languages that use scriptCodes to distinguish
  // between significantly differing scripts, we assume the scriptCodes in the
  // [LocaleInfo.fromString] factory and add it to the [LocaleInfo]. We then generate
  // the script classes based on the first locale that we assume to use the script.

  final List<String> allKeys = allResourceIdentifiers.toList()..sort();
  final List<String> languageCodes = languageToLocales.keys.toList()..sort();
  final canonicalLocale = LocaleInfo.fromString('en');
  for (final languageName in languageCodes) {
    final languageLocale = LocaleInfo.fromString(languageName);
    output.writeln(generateClassDeclaration(languageLocale, generatedClassPrefix, baseClass));
    output.writeln(generateConstructor(languageLocale));

    final Map<String, String> languageResources = localeToResources[languageLocale]!;
    for (final key in allKeys) {
      final attributes = localeToResourceAttributes[canonicalLocale]![key] as Map<String, dynamic>?;
      output.writeln(generateGetter(key, languageResources[key], attributes, languageLocale));
    }
    output.writeln('}');
    var countryCodeCount = 0;
    var scriptCodeCount = 0;
    if (languageToScriptCodes.containsKey(languageName)) {
      scriptCodeCount = languageToScriptCodes[languageName]!.length;
      // Language has scriptCodes, so we need to properly fallback countries to corresponding
      // script default values before language default values.
      for (final String scriptCode in languageToScriptCodes[languageName]!) {
        final scriptBaseLocale = LocaleInfo.fromString('${languageName}_$scriptCode');
        output.writeln(
          generateClassDeclaration(
            scriptBaseLocale,
            generatedClassPrefix,
            '$generatedClassPrefix${languageLocale.camelCase()}',
          ),
        );
        output.writeln(generateConstructorForCountrySubClass(scriptBaseLocale));
        final Map<String, String> scriptResources = localeToResources[scriptBaseLocale]!;
        for (final String key in scriptResources.keys.toList()..sort()) {
          if (languageResources[key] == scriptResources[key]) {
            continue;
          }
          final attributes =
              localeToResourceAttributes[canonicalLocale]![key] as Map<String, dynamic>?;
          output.writeln(generateGetter(key, scriptResources[key], attributes, languageLocale));
        }
        output.writeln('}');

        final List<LocaleInfo> localeCodes = languageToLocales[languageName]!..sort();
        for (final locale in localeCodes) {
          if (locale.originalString == languageName) {
            continue;
          }
          if (locale.originalString == '${languageName}_$scriptCode') {
            continue;
          }
          if (locale.scriptCode != scriptCode) {
            continue;
          }
          countryCodeCount += 1;
          output.writeln(
            generateClassDeclaration(
              locale,
              generatedClassPrefix,
              '$generatedClassPrefix${scriptBaseLocale.camelCase()}',
            ),
          );
          output.writeln(generateConstructorForCountrySubClass(locale));
          final Map<String, String> localeResources = localeToResources[locale]!;
          for (final String key in localeResources.keys) {
            // When script fallback contains the key, we compare to it instead of language fallback.
            if (scriptResources.containsKey(key)
                ? scriptResources[key] == localeResources[key]
                : languageResources[key] == localeResources[key]) {
              continue;
            }
            final attributes =
                localeToResourceAttributes[canonicalLocale]![key] as Map<String, dynamic>?;
            output.writeln(generateGetter(key, localeResources[key], attributes, languageLocale));
          }
          output.writeln('}');
        }
      }
    } else {
      // No scriptCode. Here, we do not compare against script default (because it
      // doesn't exist).
      final List<LocaleInfo> localeCodes = languageToLocales[languageName]!..sort();
      for (final locale in localeCodes) {
        if (locale.originalString == languageName) {
          continue;
        }
        countryCodeCount += 1;
        final Map<String, String> localeResources = localeToResources[locale]!;
        output.writeln(
          generateClassDeclaration(
            locale,
            generatedClassPrefix,
            '$generatedClassPrefix${languageLocale.camelCase()}',
          ),
        );
        output.writeln(generateConstructorForCountrySubClass(locale));
        for (final String key in localeResources.keys) {
          if (languageResources[key] == localeResources[key]) {
            continue;
          }
          final attributes =
              localeToResourceAttributes[canonicalLocale]![key] as Map<String, dynamic>?;
          output.writeln(generateGetter(key, localeResources[key], attributes, languageLocale));
        }
        output.writeln('}');
      }
    }

    final scriptCodeMessage = scriptCodeCount == 0
        ? ''
        : ' and $scriptCodeCount script${scriptCodeCount == 1 ? '' : 's'}';
    if (countryCodeCount == 0) {
      if (scriptCodeCount == 0) {
        supportedLocales.writeln('///  * `$languageName` - ${describeLocale(languageName)}');
      } else {
        supportedLocales.writeln(
          '///  * `$languageName` - ${describeLocale(languageName)} (plus $scriptCodeCount script${scriptCodeCount == 1 ? '' : 's'})',
        );
      }
    } else if (countryCodeCount == 1) {
      supportedLocales.writeln(
        '///  * `$languageName` - ${describeLocale(languageName)} (plus one country variation$scriptCodeMessage)',
      );
    } else {
      supportedLocales.writeln(
        '///  * `$languageName` - ${describeLocale(languageName)} (plus $countryCodeCount country variations$scriptCodeMessage)',
      );
    }
  }

  // Generate the factory function. Given a Locale it returns the corresponding
  // base class implementation.
  output.writeln('''

/// The set of supported languages, as language code strings.
///
/// The [$baseClass.delegate] can generate localizations for
/// any [Locale] with a language code from this set, regardless of the region.
/// Some regions have specific support (e.g. `de` covers all forms of German,
/// but there is support for `de-CH` specifically to override some of the
/// translations for Switzerland).
///
/// See also:
///
///  * [$factoryName], whose documentation describes these values.
final Set<String> $supportedLanguagesConstant = HashSet<String>.from(const <String>[
${languageCodes.map<String>((String value) => "  '$value', // ${describeLocale(value)}").toList().join('\n')}
]);

/// Creates a [$baseClass] instance for the given `locale`.
///
/// All of the function's arguments except `locale` will be passed to the [
/// $baseClass] constructor. (The `localeName` argument of that
/// constructor is specified by the actual subclass constructor by this
/// function.)
///
/// The following locales are supported by this package:
///
/// {@template $supportedLanguagesDocMacro}
$supportedLocales/// {@endtemplate}
///
/// Generally speaking, this method is only intended to be used by
/// [$baseClass.delegate].
$factoryDeclaration
  switch (locale.languageCode) {''');
  for (final String language in languageToLocales.keys) {
    // Only one instance of the language.
    if (languageToLocales[language]!.length == 1) {
      output.writeln(
        '''
    case '$language':
      return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${languageToLocales[language]![0].camelCase()}($factoryArguments);''',
      );
    } else if (!languageToScriptCodes.containsKey(language)) {
      // Does not distinguish between scripts. Switch on countryCode directly.
      output.writeln('''
    case '$language': {
      switch (locale.countryCode) {''');
      for (final LocaleInfo locale in languageToLocales[language]!) {
        if (locale.originalString == language) {
          continue;
        }
        assert(locale.length > 1);
        final String countryCode = locale.countryCode!;
        output.writeln(
          '''
        case '$countryCode':
          return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''',
        );
      }
      output.writeln('''
      }
      return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
    }''');
    } else {
      // Language has scriptCode, add additional switch logic.
      var hasCountryCode = false;
      output.writeln('''
    case '$language': {
      switch (locale.scriptCode) {''');
      for (final String scriptCode in languageToScriptCodes[language]!) {
        final scriptLocale = LocaleInfo.fromString('${language}_$scriptCode');
        output.writeln('''
        case '$scriptCode': {''');
        if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
          output.writeln('''
          switch (locale.countryCode) {''');
          for (final LocaleInfo locale in languageToLocales[language]!) {
            if (locale.countryCode == null) {
              continue;
            } else {
              hasCountryCode = true;
            }
            if (locale.originalString == language) {
              continue;
            }
            if (locale.scriptCode != scriptCode && locale.scriptCode != null) {
              continue;
            }
            final String countryCode = locale.countryCode!;
            output.writeln(
              '''
            case '$countryCode':
              return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''',
            );
          }
        }
        // Return a fallback locale that matches scriptCode, but not countryCode.
        //
        // Explicitly defined scriptCode fallback:
        if (languageToLocales[language]!.contains(scriptLocale)) {
          if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
            output.writeln('''
          }''');
          }
          output.writeln('''
          return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
        }''');
        } else {
          // Not Explicitly defined, fallback to first locale with the same language and
          // script:
          for (final LocaleInfo locale in languageToLocales[language]!) {
            if (locale.scriptCode != scriptCode) {
              continue;
            }
            if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
              output.writeln('''
          }''');
            }
            output.writeln('''
          return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
        }''');
            break;
          }
        }
      }
      output.writeln('''
      }''');
      if (hasCountryCode) {
        output.writeln('''
      switch (locale.countryCode) {''');
        for (final LocaleInfo locale in languageToLocales[language]!) {
          if (locale.originalString == language) {
            continue;
          }
          assert(locale.length > 1);
          if (locale.countryCode == null) {
            continue;
          }
          final String countryCode = locale.countryCode!;
          output.writeln(
            '''
        case '$countryCode':
          return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''',
          );
        }
        output.writeln('''
      }''');
      }
      output.writeln('''
      return ${callsFactoryWithConst ? 'const ' : ''}$generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
    }''');
    }
  }
  output.writeln('''
  }
  assert(false, '$factoryName() called for unsupported locale "\$locale"');
  return null;
}''');

  return output.toString();
}

/// Returns the appropriate type for getters with the given attributes.
///
/// Typically "String", but some (e.g. "timeOfDayFormat") return enums.
///
/// Used by [generateGetter] below.
String generateType(Map<String, dynamic>? attributes) {
  final bool optional = attributes?.containsKey('optional') ?? false;
  final String type = switch (attributes?['x-flutter-type']) {
    'icuShortTimePattern' => 'TimeOfDayFormat',
    'scriptCategory' => 'ScriptCategory',
    _ => 'String',
  };
  return type + (optional ? '?' : '');
}

/// Returns the appropriate name for getters with the given attributes.
///
/// Typically this is the key unmodified, but some have parameters, and
/// the GlobalMaterialLocalizations class does the substitution, and for
/// those we have to therefore provide an alternate name.
///
/// Used by [generateGetter] below.
String generateKey(String key, Map<String, dynamic>? attributes) {
  if (attributes != null) {
    if (attributes.containsKey('parameters')) {
      return '${key}Raw';
    }
    switch (attributes['x-flutter-type'] as String?) {
      case 'icuShortTimePattern':
        return '${key}Raw';
    }
  }
  if (key == 'datePickerDateOrder') {
    return 'datePickerDateOrderString';
  }
  if (key == 'datePickerDateTimeOrder') {
    return 'datePickerDateTimeOrderString';
  }
  return key;
}

const Map<String, String> _icuTimeOfDayToEnum = <String, String>{
  'HH:mm': 'TimeOfDayFormat.HH_colon_mm',
  'HH.mm': 'TimeOfDayFormat.HH_dot_mm',
  "HH 'h' mm": 'TimeOfDayFormat.frenchCanadian',
  'HH:mm น.': 'TimeOfDayFormat.HH_colon_mm',
  'H:mm': 'TimeOfDayFormat.H_colon_mm',
  'h:mm a': 'TimeOfDayFormat.h_colon_mm_space_a',
  'a h:mm': 'TimeOfDayFormat.a_space_h_colon_mm',
  'ah:mm': 'TimeOfDayFormat.a_space_h_colon_mm',
};

const Map<String, String> _scriptCategoryToEnum = <String, String>{
  'English-like': 'ScriptCategory.englishLike',
  'dense': 'ScriptCategory.dense',
  'tall': 'ScriptCategory.tall',
};

/// Returns the literal that describes the value returned by getters
/// with the given attributes.
///
/// This handles cases like the value being a literal `null`, an enum, and so
/// on. The default is to treat the value as a string and escape it and quote
/// it.
///
/// Used by [generateGetter] below.
String? generateValue(String? value, Map<String, dynamic>? attributes, LocaleInfo locale) {
  if (value == null) {
    return null;
  }
  // cupertino_en.arb doesn't use x-flutter-type.
  if (attributes != null) {
    switch (attributes['x-flutter-type'] as String?) {
      case 'icuShortTimePattern':
        if (!_icuTimeOfDayToEnum.containsKey(value)) {
          throw Exception(
            '"$value" is not one of the ICU short time patterns supported '
            'by the material library. Here is the list of supported '
            'patterns:\n  ${_icuTimeOfDayToEnum.keys.join('\n  ')}',
          );
        }
        return _icuTimeOfDayToEnum[value];
      case 'scriptCategory':
        if (!_scriptCategoryToEnum.containsKey(value)) {
          throw Exception(
            '"$value" is not one of the scriptCategory values supported '
            'by the material library. Here is the list of supported '
            'values:\n  ${_scriptCategoryToEnum.keys.join('\n  ')}',
          );
        }
        return _scriptCategoryToEnum[value];
    }
  }
  return generateEncodedString(locale.languageCode, value);
}

/// Combines [generateType], [generateKey], and [generateValue] to return
/// the source of getters for the GlobalMaterialLocalizations subclass.
/// The locale is the locale for which the getter is being generated.
String generateGetter(
  String key,
  String? value,
  Map<String, dynamic>? attributes,
  LocaleInfo locale,
) {
  final String type = generateType(attributes);
  key = generateKey(key, attributes);
  final String? generatedValue = generateValue(value, attributes, locale);
  return '''

  @override
  $type get $key => $generatedValue;''';
}

void main(List<String> rawArgs) {
  checkCwdIsRepoRoot('gen_localizations');
  final GeneratorOptions options = parseArgs(rawArgs);

  // filenames are assumed to end in "prefix_lc.arb" or "prefix_lc_cc.arb", where prefix
  // is the 2nd command line argument, lc is a language code and cc is the country
  // code. In most cases both codes are just two characters.

  final directory = Directory(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n'));
  final widgetsFilenameRE = RegExp(r'widgets_(\w+)\.arb$');
  final materialFilenameRE = RegExp(r'material_(\w+)\.arb$');
  final cupertinoFilenameRE = RegExp(r'cupertino_(\w+)\.arb$');

  try {
    validateEnglishLocalizations(File(path.join(directory.path, 'widgets_en.arb')));
    validateEnglishLocalizations(File(path.join(directory.path, 'material_en.arb')));
    validateEnglishLocalizations(File(path.join(directory.path, 'cupertino_en.arb')));
  } on ValidationError catch (exception) {
    exitWithError('$exception');
  }

  // Only rewrite material_kn.arb and cupertino_en.arb if overwriting the
  // Material and Cupertino localizations files.
  if (options.writeToFile) {
    // Encodes the material_kn.arb file and the cupertino_en.arb files before
    // generating localizations. This prevents a subset of Emacs users from
    // crashing when opening up the Flutter source code.
    // See https://github.com/flutter/flutter/issues/36704 for more context.
    encodeKnArbFiles(directory);
  }

  precacheLanguageAndRegionTags();

  // Maps of locales to resource key/value pairs for Widgets ARBs.
  final widgetsLocaleToResources = <LocaleInfo, Map<String, String>>{};
  // Maps of locales to resource key/attributes pairs for Widgets ARBs.
  // https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
  final widgetsLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};

  // Maps of locales to resource key/value pairs for Material ARBs.
  final materialLocaleToResources = <LocaleInfo, Map<String, String>>{};
  // Maps of locales to resource key/attributes pairs for Material ARBs.
  // https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
  final materialLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};

  // Maps of locales to resource key/value pairs for Cupertino ARBs.
  final cupertinoLocaleToResources = <LocaleInfo, Map<String, String>>{};
  // Maps of locales to resource key/attributes pairs for Cupertino ARBs.
  // https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
  final cupertinoLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};

  loadMatchingArbsIntoBundleMaps(
    directory: directory,
    filenamePattern: widgetsFilenameRE,
    localeToResources: widgetsLocaleToResources,
    localeToResourceAttributes: widgetsLocaleToResourceAttributes,
  );
  loadMatchingArbsIntoBundleMaps(
    directory: directory,
    filenamePattern: materialFilenameRE,
    localeToResources: materialLocaleToResources,
    localeToResourceAttributes: materialLocaleToResourceAttributes,
  );
  loadMatchingArbsIntoBundleMaps(
    directory: directory,
    filenamePattern: cupertinoFilenameRE,
    localeToResources: cupertinoLocaleToResources,
    localeToResourceAttributes: cupertinoLocaleToResourceAttributes,
  );

  try {
    validateLocalizations(
      widgetsLocaleToResources,
      widgetsLocaleToResourceAttributes,
      removeUndefined: options.removeUndefined,
    );
    validateLocalizations(
      materialLocaleToResources,
      materialLocaleToResourceAttributes,
      removeUndefined: options.removeUndefined,
    );
    validateLocalizations(
      cupertinoLocaleToResources,
      cupertinoLocaleToResourceAttributes,
      removeUndefined: options.removeUndefined,
    );
  } on ValidationError catch (exception) {
    exitWithError('$exception');
  }
  if (options.removeUndefined) {
    removeUndefinedLocalizations(widgetsLocaleToResources);
    removeUndefinedLocalizations(materialLocaleToResources);
    removeUndefinedLocalizations(cupertinoLocaleToResources);
  }

  final String? widgetsLocalizations = options.writeToFile || !options.cupertinoOnly
      ? generateArbBasedLocalizationSubclasses(
          localeToResources: widgetsLocaleToResources,
          localeToResourceAttributes: widgetsLocaleToResourceAttributes,
          generatedClassPrefix: 'WidgetsLocalization',
          baseClass: 'GlobalWidgetsLocalizations',
          generateHeader: generateWidgetsHeader,
          generateConstructor: generateWidgetsConstructor,
          generateConstructorForCountrySubClass: generateWidgetsConstructorForCountrySubclass,
          factoryName: widgetsFactoryName,
          factoryDeclaration: widgetsFactoryDeclaration,
          callsFactoryWithConst: true,
          factoryArguments: widgetsFactoryArguments,
          supportedLanguagesConstant: widgetsSupportedLanguagesConstant,
          supportedLanguagesDocMacro: widgetsSupportedLanguagesDocMacro,
        )
      : null;
  final String? materialLocalizations = options.writeToFile || !options.cupertinoOnly
      ? generateArbBasedLocalizationSubclasses(
          localeToResources: materialLocaleToResources,
          localeToResourceAttributes: materialLocaleToResourceAttributes,
          generatedClassPrefix: 'MaterialLocalization',
          baseClass: 'GlobalMaterialLocalizations',
          generateHeader: generateMaterialHeader,
          generateConstructor: generateMaterialConstructor,
          factoryName: materialFactoryName,
          factoryDeclaration: materialFactoryDeclaration,
          callsFactoryWithConst: false,
          factoryArguments: materialFactoryArguments,
          supportedLanguagesConstant: materialSupportedLanguagesConstant,
          supportedLanguagesDocMacro: materialSupportedLanguagesDocMacro,
        )
      : null;
  final String? cupertinoLocalizations = options.writeToFile || !options.materialOnly
      ? generateArbBasedLocalizationSubclasses(
          localeToResources: cupertinoLocaleToResources,
          localeToResourceAttributes: cupertinoLocaleToResourceAttributes,
          generatedClassPrefix: 'CupertinoLocalization',
          baseClass: 'GlobalCupertinoLocalizations',
          generateHeader: generateCupertinoHeader,
          generateConstructor: generateCupertinoConstructor,
          factoryName: cupertinoFactoryName,
          factoryDeclaration: cupertinoFactoryDeclaration,
          callsFactoryWithConst: false,
          factoryArguments: cupertinoFactoryArguments,
          supportedLanguagesConstant: cupertinoSupportedLanguagesConstant,
          supportedLanguagesDocMacro: cupertinoSupportedLanguagesDocMacro,
        )
      : null;

  if (options.writeToFile) {
    final widgetsLocalizationsFile = File(
      path.join(directory.path, 'generated_widgets_localizations.dart'),
    );
    widgetsLocalizationsFile.writeAsStringSync(widgetsLocalizations!, flush: true);
    final materialLocalizationsFile = File(
      path.join(directory.path, 'generated_material_localizations.dart'),
    );
    materialLocalizationsFile.writeAsStringSync(materialLocalizations!, flush: true);
    final cupertinoLocalizationsFile = File(
      path.join(directory.path, 'generated_cupertino_localizations.dart'),
    );
    cupertinoLocalizationsFile.writeAsStringSync(cupertinoLocalizations!, flush: true);
  } else {
    if (options.cupertinoOnly) {
      stdout.write(cupertinoLocalizations);
    } else if (options.materialOnly) {
      stdout.write(materialLocalizations);
    } else if (options.widgetsOnly) {
      stdout.write(widgetsLocalizations);
    } else {
      stdout.write(widgetsLocalizations);
      stdout.write(materialLocalizations);
      stdout.write(cupertinoLocalizations);
    }
  }
}
