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

import 'package:meta/meta.dart';

import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../convert.dart';
import '../flutter_manifest.dart';

import 'gen_l10n_templates.dart';
import 'gen_l10n_types.dart';
import 'localizations_utils.dart';
import 'message_parser.dart';

/// Run the localizations generation script with the configuration [options].
LocalizationsGenerator generateLocalizations({
  required Directory projectDir,
  Directory? dependenciesDir,
  required LocalizationOptions options,
  required Logger logger,
  required FileSystem fileSystem,
}) {
  // If generating a synthetic package, generate a warning if
  // flutter: generate is not set.
  final FlutterManifest? flutterManifest = FlutterManifest.createFromPath(
    projectDir.childFile('pubspec.yaml').path,
    fileSystem: projectDir.fileSystem,
    logger: logger,
  );
  if (options.useSyntheticPackage && (flutterManifest == null || !flutterManifest.generateSyntheticPackage)) {
    throwToolExit(
      'Attempted to generate localizations code without having '
      'the flutter: generate flag turned on.'
      '\n'
      'Check pubspec.yaml and ensure that flutter: generate: true has '
      'been added and rebuild the project. Otherwise, the localizations '
      'source code will not be importable.'
    );
  }

  precacheLanguageAndRegionTags();

  final String inputPathString = options.arbDirectory?.path ?? fileSystem.path.join('lib', 'l10n');
  final String templateArbFileName = options.templateArbFile?.toFilePath() ?? 'app_en.arb';
  final String outputFileString = options.outputLocalizationsFile?.toFilePath() ?? 'app_localizations.dart';
  LocalizationsGenerator generator;
  try {
    generator = LocalizationsGenerator(
      fileSystem: fileSystem,
      inputsAndOutputsListPath: dependenciesDir?.path,
      projectPathString: projectDir.path,
      inputPathString: inputPathString,
      templateArbFileName: templateArbFileName,
      outputFileString: outputFileString,
      outputPathString: options.outputDirectory?.path,
      classNameString: options.outputClass ?? 'AppLocalizations',
      preferredSupportedLocales: options.preferredSupportedLocales,
      headerString: options.header,
      headerFile: options.headerFile?.toFilePath(),
      useDeferredLoading: options.deferredLoading ?? false,
      useSyntheticPackage: options.useSyntheticPackage,
      areResourceAttributesRequired: options.areResourceAttributesRequired,
      untranslatedMessagesFile: options.untranslatedMessagesFile?.toFilePath(),
      usesNullableGetter: options.usesNullableGetter,
      useEscaping: options.useEscaping,
      logger: logger,
      suppressWarnings: options.suppressWarnings,
    )
      ..loadResources()
      ..writeOutputFiles(isFromYaml: true);
  } on L10nException catch (e) {
    throwToolExit(e.message);
  }
  return generator;
}

/// The path for the synthetic package.
String _defaultSyntheticPackagePath(FileSystem fileSystem) => fileSystem.path.join('.dart_tool', 'flutter_gen');

/// The default path used when the `_useSyntheticPackage` setting is set to true
/// in [LocalizationsGenerator].
///
/// See [LocalizationsGenerator.initialize] for where and how it is used by the
/// localizations tool.
String _syntheticL10nPackagePath(FileSystem fileSystem) => fileSystem.path.join(_defaultSyntheticPackagePath(fileSystem), 'gen_l10n');

// Generate method parameters and also infer the correct types from the usage of the placeholders
// For example, if placeholders are used for plurals and no type was specified, then the type will
// automatically set to 'num'. Similarly, if such placeholders are used for selects, then the type
// will be set to 'String'. For such placeholders that are used for both, we should throw an error.
List<String> generateMethodParameters(Message message) {
  return message.placeholders.values.map((Placeholder placeholder) {
    return '${placeholder.type} ${placeholder.name}';
  }).toList();
}

// Similar to above, but is used for passing arguments into helper functions.
List<String> generateMethodArguments(Message message) {
  return message.placeholders.values.map((Placeholder placeholder) => placeholder.name).toList();
}

String generateDateFormattingLogic(Message message) {
  if (message.placeholders.isEmpty || !message.placeholdersRequireFormatting) {
    return '@(none)';
  }

  final Iterable<String> formatStatements = message.placeholders.values
    .where((Placeholder placeholder) => placeholder.requiresDateFormatting)
    .map((Placeholder placeholder) {
      final String? placeholderFormat = placeholder.format;
      if (placeholderFormat == null) {
        throw L10nException(
          'The placeholder, ${placeholder.name}, has its "type" resource attribute set to '
          'the "${placeholder.type}" type. To properly resolve for the right '
          '${placeholder.type} format, the "format" attribute needs to be set '
          'to determine which DateFormat to use. \n'
          "Check the intl library's DateFormat class constructors for allowed "
          'date formats.'
        );
      }
      final bool? isCustomDateFormat = placeholder.isCustomDateFormat;
      if (!placeholder.hasValidDateFormat
          && (isCustomDateFormat == null || !isCustomDateFormat)) {
        throw L10nException(
          'Date format "$placeholderFormat" for placeholder '
          '${placeholder.name} does not have a corresponding DateFormat '
          "constructor\n. Check the intl library's DateFormat class "
          'constructors for allowed date formats, or set "isCustomDateFormat" attribute '
          'to "true".'
        );
      }
      if (placeholder.hasValidDateFormat) {
        return dateFormatTemplate
          .replaceAll('@(placeholder)', placeholder.name)
          .replaceAll('@(format)', placeholderFormat);
      }
      return dateFormatCustomTemplate
        .replaceAll('@(placeholder)', placeholder.name)
        .replaceAll('@(format)', "'${generateString(placeholderFormat)}'");
    });

  return formatStatements.isEmpty ? '@(none)' : formatStatements.join();
}

String generateNumberFormattingLogic(Message message) {
  if (message.placeholders.isEmpty || !message.placeholdersRequireFormatting) {
    return '@(none)';
  }

  final Iterable<String> formatStatements = message.placeholders.values
    .where((Placeholder placeholder) => placeholder.requiresNumFormatting)
    .map((Placeholder placeholder) {
      final String? placeholderFormat = placeholder.format;
      if (!placeholder.hasValidNumberFormat || placeholderFormat == null) {
        throw L10nException(
          'Number format $placeholderFormat for the ${placeholder.name} '
          'placeholder does not have a corresponding NumberFormat constructor.\n'
          "Check the intl library's NumberFormat class constructors for allowed "
          'number formats.'
        );
      }
      final Iterable<String> parameters =
        placeholder.optionalParameters.map<String>((OptionalParameter parameter) {
          if (parameter.value is num) {
            return '${parameter.name}: ${parameter.value}';
          } else {
            return "${parameter.name}: '${generateString(parameter.value.toString())}'";
          }
        },
      );

      if (placeholder.hasNumberFormatWithParameters) {
        return numberFormatNamedTemplate
            .replaceAll('@(placeholder)', placeholder.name)
            .replaceAll('@(format)', placeholderFormat)
            .replaceAll('@(parameters)', parameters.join(',\n      '));
      } else {
        return numberFormatPositionalTemplate
            .replaceAll('@(placeholder)', placeholder.name)
            .replaceAll('@(format)', placeholderFormat);
      }
    });

  return formatStatements.isEmpty ? '@(none)' : formatStatements.join();
}

/// List of possible cases for plurals defined the ICU messageFormat syntax.
Map<String, String> pluralCases = <String, String>{
  '0': 'zero',
  '1': 'one',
  '2': 'two',
  'zero': 'zero',
  'one': 'one',
  'two': 'two',
  'few': 'few',
  'many': 'many',
  'other': 'other',
};

String generateBaseClassMethod(Message message, LocaleInfo? templateArbLocale) {
  final String comment = message
    .description
    ?.split('\n')
    .map((String line) => '  /// $line')
    .join('\n') ?? '  /// No description provided for @${message.resourceId}.';
  final String templateLocaleTranslationComment = '''
  /// In $templateArbLocale, this message translates to:
  /// **'${generateString(message.value)}'**''';

  if (message.placeholders.isNotEmpty) {
    return baseClassMethodTemplate
      .replaceAll('@(comment)', comment)
      .replaceAll('@(templateLocaleTranslationComment)', templateLocaleTranslationComment)
      .replaceAll('@(name)', message.resourceId)
      .replaceAll('@(parameters)', generateMethodParameters(message).join(', '));
  }
  return baseClassGetterTemplate
    .replaceAll('@(comment)', comment)
    .replaceAll('@(templateLocaleTranslationComment)', templateLocaleTranslationComment)
    .replaceAll('@(name)', message.resourceId);
}

// Add spaces to pad the start of each line. Skips the first line
// assuming that the padding is already present.
String _addSpaces(String message, {int spaces = 0}) {
  bool isFirstLine = true;
  return message
    .split('\n')
    .map((String value) {
      if (isFirstLine) {
        isFirstLine = false;
        return value;
      }
      return value.padLeft(spaces);
    })
    .join('\n');
}

String _generateLookupByAllCodes(
  AppResourceBundleCollection allBundles,
  String Function(LocaleInfo) generateSwitchClauseTemplate,
) {
  final Iterable<LocaleInfo> localesWithAllCodes = allBundles.locales.where((LocaleInfo locale) {
    return locale.scriptCode != null && locale.countryCode != null;
  });

  if (localesWithAllCodes.isEmpty) {
    return '';
  }

  final Iterable<String> switchClauses = localesWithAllCodes.map<String>((LocaleInfo locale) {
    return generateSwitchClauseTemplate(locale)
      .replaceAll('@(case)', locale.toString());
  });

  return allCodesLookupTemplate.replaceAll(
    '@(allCodesSwitchClauses)',
    switchClauses.join('\n        '),
  );
}

String _generateLookupByScriptCode(
  AppResourceBundleCollection allBundles,
  String Function(LocaleInfo) generateSwitchClauseTemplate,
) {
  final Iterable<String> switchClauses = allBundles.languages.map((String language) {
    final Iterable<LocaleInfo> locales = allBundles.localesForLanguage(language);
    final Iterable<LocaleInfo> localesWithScriptCodes = locales.where((LocaleInfo locale) {
      return locale.scriptCode != null && locale.countryCode == null;
    });

    if (localesWithScriptCodes.isEmpty) {
      return null;
    }

    return _addSpaces(nestedSwitchTemplate
      .replaceAll('@(languageCode)', language)
      .replaceAll('@(code)', 'scriptCode')
      .replaceAll('@(switchClauses)',
        _addSpaces(
          localesWithScriptCodes.map((LocaleInfo locale) {
            return generateSwitchClauseTemplate(locale)
              .replaceAll('@(case)', locale.scriptCode!);
          }).join('\n'),
          spaces: 8,
        ),
      ),
      spaces: 4,
    );
  }).whereType<String>();

  if (switchClauses.isEmpty) {
    return '';
  }

  return languageCodeSwitchTemplate
    .replaceAll('@(comment)', '// Lookup logic when language+script codes are specified.')
    .replaceAll('@(switchClauses)', switchClauses.join('\n      '),
  );
}

String _generateLookupByCountryCode(
  AppResourceBundleCollection allBundles,
  String Function(LocaleInfo) generateSwitchClauseTemplate,
) {
  final Iterable<String> switchClauses = allBundles.languages.map((String language) {
    final Iterable<LocaleInfo> locales = allBundles.localesForLanguage(language);
    final Iterable<LocaleInfo> localesWithCountryCodes = locales.where((LocaleInfo locale) {
      return locale.countryCode != null && locale.scriptCode == null;
    });

    if (localesWithCountryCodes.isEmpty) {
      return null;
    }

    return _addSpaces(
      nestedSwitchTemplate
        .replaceAll('@(languageCode)', language)
        .replaceAll('@(code)', 'countryCode')
        .replaceAll('@(switchClauses)', _addSpaces(
          localesWithCountryCodes.map((LocaleInfo locale) {
            return generateSwitchClauseTemplate(locale).replaceAll('@(case)', locale.countryCode!);
          }).join('\n'),
          spaces: 4,
        )),
      spaces: 4,
    );
  }).whereType<String>();

  if (switchClauses.isEmpty) {
    return '';
  }

  return languageCodeSwitchTemplate
    .replaceAll('@(comment)', '// Lookup logic when language+country codes are specified.')
    .replaceAll('@(switchClauses)', switchClauses.join('\n    '));
}

String _generateLookupByLanguageCode(
  AppResourceBundleCollection allBundles,
  String Function(LocaleInfo) generateSwitchClauseTemplate,
) {
  final Iterable<String> switchClauses = allBundles.languages.map((String language) {
    final Iterable<LocaleInfo> locales = allBundles.localesForLanguage(language);
    final Iterable<LocaleInfo> localesWithLanguageCode = locales.where((LocaleInfo locale) {
      return locale.countryCode == null && locale.scriptCode == null;
    });

    if (localesWithLanguageCode.isEmpty) {
      return null;
    }

    return localesWithLanguageCode.map((LocaleInfo locale) {
      return generateSwitchClauseTemplate(locale)
        .replaceAll('@(case)', locale.languageCode);
    }).join('\n      ');
  }).whereType<String>();

  if (switchClauses.isEmpty) {
    return '';
  }

  return languageCodeSwitchTemplate
    .replaceAll('@(comment)', '// Lookup logic when only language code is specified.')
    .replaceAll('@(switchClauses)', switchClauses.join('\n    '));
}

String _generateLookupBody(
  AppResourceBundleCollection allBundles,
  String className,
  bool useDeferredLoading,
  String fileName,
) {
  String generateSwitchClauseTemplate(LocaleInfo locale) {
    return (useDeferredLoading ?
      switchClauseDeferredLoadingTemplate : switchClauseTemplate)
      .replaceAll('@(localeClass)', '$className${locale.camelCase()}')
      .replaceAll('@(appClass)', className)
      .replaceAll('@(library)', '${fileName}_${locale.languageCode}');
  }
  return lookupBodyTemplate
    .replaceAll('@(lookupAllCodesSpecified)', _generateLookupByAllCodes(
      allBundles,
      generateSwitchClauseTemplate,
    ))
    .replaceAll('@(lookupScriptCodeSpecified)', _generateLookupByScriptCode(
      allBundles,
      generateSwitchClauseTemplate,
    ))
    .replaceAll('@(lookupCountryCodeSpecified)', _generateLookupByCountryCode(
      allBundles,
      generateSwitchClauseTemplate,
    ))
    .replaceAll('@(lookupLanguageCodeSpecified)', _generateLookupByLanguageCode(
      allBundles,
      generateSwitchClauseTemplate,
    ));
}

String _generateDelegateClass({
  required AppResourceBundleCollection allBundles,
  required String className,
  required Set<String> supportedLanguageCodes,
  required bool useDeferredLoading,
  required String fileName,
}) {

  final String lookupBody = _generateLookupBody(
    allBundles,
    className,
    useDeferredLoading,
    fileName,
  );
  final String loadBody = (
    useDeferredLoading ? loadBodyDeferredLoadingTemplate : loadBodyTemplate
  )
    .replaceAll('@(class)', className)
    .replaceAll('@(lookupName)', 'lookup$className');
  final String lookupFunction = (useDeferredLoading ?
  lookupFunctionDeferredLoadingTemplate : lookupFunctionTemplate)
    .replaceAll('@(class)', className)
    .replaceAll('@(lookupName)', 'lookup$className')
    .replaceAll('@(lookupBody)', lookupBody);
  return delegateClassTemplate
    .replaceAll('@(class)', className)
    .replaceAll('@(loadBody)', loadBody)
    .replaceAll('@(supportedLanguageCodes)', supportedLanguageCodes.join(', '))
    .replaceAll('@(lookupFunction)', lookupFunction);
}

class LocalizationsGenerator {
  /// Initializes [inputDirectory], [outputDirectory], [templateArbFile],
  /// [outputFile] and [className].
  ///
  /// Throws an [L10nException] when a provided configuration is not allowed
  /// by [LocalizationsGenerator].
  ///
  /// Throws a [FileSystemException] when a file operation necessary for setting
  /// up the [LocalizationsGenerator] cannot be completed.
  factory LocalizationsGenerator({
    required FileSystem fileSystem,
    required String inputPathString,
    String? outputPathString,
    required String templateArbFileName,
    required String outputFileString,
    required String classNameString,
    List<String>? preferredSupportedLocales,
    String? headerString,
    String? headerFile,
    bool useDeferredLoading = false,
    String? inputsAndOutputsListPath,
    bool useSyntheticPackage = true,
    String? projectPathString,
    bool areResourceAttributesRequired = false,
    String? untranslatedMessagesFile,
    bool usesNullableGetter = true,
    bool useEscaping = false,
    required Logger logger,
    bool suppressWarnings = false,
  }) {
    final Directory? projectDirectory = projectDirFromPath(fileSystem, projectPathString);
    final Directory inputDirectory = inputDirectoryFromPath(fileSystem, inputPathString, projectDirectory);
    final Directory outputDirectory = outputDirectoryFromPath(fileSystem, outputPathString ?? inputPathString, useSyntheticPackage, projectDirectory);
    return LocalizationsGenerator._(
      fileSystem,
      useSyntheticPackage: useSyntheticPackage,
      usesNullableGetter: usesNullableGetter,
      className: classNameFromString(classNameString),
      projectDirectory: projectDirectory,
      inputDirectory: inputDirectory,
      outputDirectory: outputDirectory,
      templateArbFile: templateArbFileFromFileName(templateArbFileName, inputDirectory),
      baseOutputFile: outputDirectory.childFile(outputFileString),
      preferredSupportedLocales: preferredSupportedLocalesFromLocales(preferredSupportedLocales),
      header: headerFromFile(headerString, headerFile, inputDirectory),
      useDeferredLoading: useDeferredLoading,
      untranslatedMessagesFile: _untranslatedMessagesFileFromPath(fileSystem, untranslatedMessagesFile),
      inputsAndOutputsListFile: _inputsAndOutputsListFileFromPath(fileSystem, inputsAndOutputsListPath),
      areResourceAttributesRequired: areResourceAttributesRequired,
      useEscaping: useEscaping,
      logger: logger,
      suppressWarnings: suppressWarnings,
    );
  }

  /// Creates an instance of the localizations generator class.
  ///
  /// It takes in a [FileSystem] representation that the class will act upon.
  LocalizationsGenerator._(this._fs, {
    required this.inputDirectory,
    required this.outputDirectory,
    required this.templateArbFile,
    required this.baseOutputFile,
    required this.className,
    this.preferredSupportedLocales = const <LocaleInfo>[],
    this.header = '',
    this.useDeferredLoading = false,
    required this.inputsAndOutputsListFile,
    this.useSyntheticPackage = true,
    this.projectDirectory,
    this.areResourceAttributesRequired = false,
    this.untranslatedMessagesFile,
    this.usesNullableGetter = true,
    required this.logger,
    this.useEscaping = false,
    this.suppressWarnings = false,
  });

  final FileSystem _fs;
  List<Message> _allMessages = <Message>[];
  late final AppResourceBundleCollection _allBundles = AppResourceBundleCollection(inputDirectory);
  late final AppResourceBundle _templateBundle = AppResourceBundle(templateArbFile);
  late final Map<LocaleInfo, String> _inputFileNames = Map<LocaleInfo, String>.fromEntries(
    _allBundles.bundles.map((AppResourceBundle bundle) => MapEntry<LocaleInfo, String>(bundle.locale, bundle.file.basename))
  );
  late final LocaleInfo _templateArbLocale = _templateBundle.locale;

  @visibleForTesting
  final bool useSyntheticPackage;

  // Used to decide if the generated code is nullable or not
  // (whether AppLocalizations? or AppLocalizations is returned from
  // `static {name}Localizations{?} of (BuildContext context))`
  @visibleForTesting
  final bool usesNullableGetter;

  /// The directory that contains the project's arb files, as well as the
  /// header file, if specified.
  ///
  /// It is assumed that all input files (e.g. [templateArbFile], arb files
  /// for translated messages, header file templates) will reside here.
  final Directory inputDirectory;

  /// The Flutter project's root directory.
  final Directory? projectDirectory;

  /// The directory to generate the project's localizations files in.
  ///
  /// It is assumed that all output files (e.g. The localizations
  /// [outputFile], `messages_<locale>.dart` and `messages_all.dart`)
  /// will reside here.
  final Directory outputDirectory;

  /// The input arb file which defines all of the messages that will be
  /// exported by the generated class that's written to [outputFile].
  final File templateArbFile;

  /// The file to write the generated abstract localizations and
  /// localizations delegate classes to. Separate localizations
  /// files will also be generated for each language using this
  /// filename as a prefix and the locale as the suffix.
  final File baseOutputFile;

  /// The class name to be used for the localizations class in [outputFile].
  ///
  /// For example, if 'AppLocalizations' is passed in, a class named
  /// AppLocalizations will be used for localized message lookups.
  final String className;

  /// The list of preferred supported locales.
  ///
  /// By default, the list of supported locales in the localizations class
  /// will be sorted in alphabetical order. However, this option
  /// allows for a set of preferred locales to appear at the top of the
  /// list.
  ///
  /// The order of locales in this list will also be the order of locale
  /// priority. For example, if a device supports 'en' and 'es' and
  /// ['es', 'en'] is passed in, the 'es' locale will take priority over 'en'.
  final List<LocaleInfo> preferredSupportedLocales;

  // Whether we need to import intl or not. This flag is updated after parsing
  // all of the messages.
  bool requiresIntlImport = false;

  // Whether we want to use escaping for ICU messages.
  bool useEscaping = false;

  /// Whether any errors were caught. This is set after encountering any errors
  /// from calling [_generateMethod].
  bool hadErrors = false;

  /// The list of all arb path strings in [inputDirectory].
  List<String> get arbPathStrings {
    return _allBundles.bundles.map((AppResourceBundle bundle) => bundle.file.path).toList();
  }

  List<String> get outputFileList {
    return _outputFileList;
  }

  /// The supported language codes as found in the arb files located in
  /// [inputDirectory].
  final Set<String> supportedLanguageCodes = <String>{};

  /// The supported locales as found in the arb files located in
  /// [inputDirectory].
  final Set<LocaleInfo> supportedLocales = <LocaleInfo>{};

  /// The header to be prepended to the generated Dart localization file.
  final String header;

  final Map<LocaleInfo, List<String>> _unimplementedMessages = <LocaleInfo, List<String>>{};

  /// Whether to generate the Dart localization file with locales imported as
  /// deferred, allowing for lazy loading of each locale in Flutter web.
  ///
  /// This can reduce a web app’s initial startup time by decreasing the size of
  /// the JavaScript bundle. When [_useDeferredLoading] is set to true, the
  /// messages for a particular locale are only downloaded and loaded by the
  /// Flutter app as they are needed. For projects with a lot of different
  /// locales and many localization strings, it can be an performance
  /// improvement to have deferred loading. For projects with a small number of
  /// locales, the difference is negligible, and might slow down the start up
  /// compared to bundling the localizations with the rest of the application.
  ///
  /// Note that this flag does not affect other platforms such as mobile or
  /// desktop.
  final bool useDeferredLoading;

  /// Contains a map of each output language file to its corresponding content in
  /// string format.
  final Map<File, String> _languageFileMap = <File, String>{};

  /// A generated file that will contain the list of messages for each locale
  /// that do not have a translation yet.
  final File? untranslatedMessagesFile;

  /// The file that contains the list of inputs and outputs for generating
  /// localizations.
  @visibleForTesting
  final File? inputsAndOutputsListFile;
  final List<String> _inputFileList = <String>[];
  final List<String> _outputFileList = <String>[];

  /// Whether or not resource attributes are required for each corresponding
  /// resource id.
  ///
  /// Resource attributes provide metadata about the message.
  @visibleForTesting
  final bool areResourceAttributesRequired;

  /// Logger to be used during the execution of the script.
  Logger logger;

  /// Whether or not to suppress warnings or not.
  final bool suppressWarnings;

  static bool _isNotReadable(FileStat fileStat) {
    final String rawStatString = fileStat.modeString();
    // Removes potential prepended permission bits, such as '(suid)' and '(guid)'.
    final String statString = rawStatString.substring(rawStatString.length - 9);
    return !(statString[0] == 'r' || statString[3] == 'r' || statString[6] == 'r');
  }

  static bool _isNotWritable(FileStat fileStat) {
    final String rawStatString = fileStat.modeString();
    // Removes potential prepended permission bits, such as '(suid)' and '(guid)'.
    final String statString = rawStatString.substring(rawStatString.length - 9);
    return !(statString[1] == 'w' || statString[4] == 'w' || statString[7] == 'w');
  }

  @visibleForTesting
  static Directory? projectDirFromPath(FileSystem fileSystem, String? projectPathString) {
    if (projectPathString == null) {
      return null;
    }

    final Directory directory = fileSystem.directory(projectPathString);
    if (!directory.existsSync()) {
      throw L10nException(
        'Directory does not exist: $directory.\n'
        "Please select a directory that contains the project's localizations "
        'resource files.'
      );
    }
    return directory;
  }

  /// Sets the reference [Directory] for [inputDirectory].
  @visibleForTesting
  static Directory inputDirectoryFromPath(FileSystem fileSystem, String inputPathString, Directory? projectDirectory) {
    final Directory inputDirectory = fileSystem.directory(
      projectDirectory != null
        ? _getAbsoluteProjectPath(inputPathString, projectDirectory)
        : inputPathString
    );

    if (!inputDirectory.existsSync()) {
      throw L10nException(
        "The 'arb-dir' directory, '$inputDirectory', does not exist.\n"
        'Make sure that the correct path was provided.'
      );
    }

    final FileStat fileStat = inputDirectory.statSync();
    if (_isNotReadable(fileStat) || _isNotWritable(fileStat)) {
      throw L10nException(
        "The 'arb-dir' directory, '$inputDirectory', doesn't allow reading and writing.\n"
        'Please ensure that the user has read and write permissions.'
      );
    }
    return inputDirectory;
  }

  /// Sets the reference [Directory] for [outputDirectory].
  @visibleForTesting
  static Directory outputDirectoryFromPath(FileSystem fileSystem, String outputPathString, bool useSyntheticPackage, Directory? projectDirectory) {
    Directory outputDirectory;
    if (useSyntheticPackage) {
      outputDirectory = fileSystem.directory(
        projectDirectory != null
          ? _getAbsoluteProjectPath(_syntheticL10nPackagePath(fileSystem), projectDirectory)
          : _syntheticL10nPackagePath(fileSystem)
      );
    } else {
      outputDirectory = fileSystem.directory(
        projectDirectory != null
          ? _getAbsoluteProjectPath(outputPathString, projectDirectory)
          : outputPathString
      );
    }
    return outputDirectory;
  }

  /// Sets the reference [File] for [templateArbFile].
  @visibleForTesting
  static File templateArbFileFromFileName(String templateArbFileName, Directory inputDirectory) {
    final File templateArbFile = inputDirectory.childFile(templateArbFileName);
    final FileStat templateArbFileStat = templateArbFile.statSync();
    if (templateArbFileStat.type == FileSystemEntityType.notFound) {
      throw L10nException(
        "The 'template-arb-file', $templateArbFile, does not exist."
      );
    }
    final String templateArbFileStatModeString = templateArbFileStat.modeString();
    if (templateArbFileStatModeString[0] == '-' && templateArbFileStatModeString[3] == '-') {
      throw L10nException(
        "The 'template-arb-file', $templateArbFile, is not readable.\n"
        'Please ensure that the user has read permissions.'
      );
    }
    return templateArbFile;
  }

  static bool _isValidClassName(String className) {
    // Public Dart class name cannot begin with an underscore
    if (className[0] == '_') {
      return false;
    }
    // Dart class name cannot contain non-alphanumeric symbols
    if (className.contains(RegExp(r'[^a-zA-Z_\d]'))) {
      return false;
    }
    // Dart class name must start with upper case character
    if (className[0].contains(RegExp(r'[a-z]'))) {
      return false;
    }
    // Dart class name cannot start with a number
    if (className[0].contains(RegExp(r'\d'))) {
      return false;
    }
    return true;
  }

  /// Sets the [className] for the localizations and localizations delegate
  /// classes.
  @visibleForTesting
  static String classNameFromString(String classNameString) {
    if (classNameString.isEmpty) {
      throw L10nException('classNameString argument cannot be empty');
    }
    if (!_isValidClassName(classNameString)) {
      throw L10nException(
        "The 'output-class', $classNameString, is not a valid public Dart class name.\n"
      );
    }
    return classNameString;
  }

  /// Sets [preferredSupportedLocales] so that this particular list of locales
  /// will take priority over the other locales.
  @visibleForTesting
  static List<LocaleInfo> preferredSupportedLocalesFromLocales(List<String>? inputLocales) {
    if (inputLocales == null || inputLocales.isEmpty) {
      return const <LocaleInfo>[];
    }
    return inputLocales.map((String localeString) {
      return LocaleInfo.fromString(localeString);
    }).toList();
  }

  static String headerFromFile(String? headerString, String? headerFile, Directory inputDirectory) {
    if (headerString != null && headerFile != null) {
      throw L10nException(
        'Cannot accept both header and header file arguments. \n'
        'Please make sure to define only one or the other. '
      );
    }

    if (headerString != null) {
      return headerString;
    } else if (headerFile != null) {
      try {
        return inputDirectory.childFile(headerFile).readAsStringSync();
      } on FileSystemException catch (error) {
        throw L10nException (
          'Failed to read header file: "$headerFile". \n'
          'FileSystemException: ${error.message}'
        );
      }
    }
    return '';
  }

  static String _getAbsoluteProjectPath(String relativePath, Directory projectDirectory) =>
      projectDirectory.fileSystem.path.join(projectDirectory.path, relativePath);

  static File? _untranslatedMessagesFileFromPath(FileSystem fileSystem, String? untranslatedMessagesFileString) {
    if (untranslatedMessagesFileString == null || untranslatedMessagesFileString.isEmpty) {
      return null;
    }
    untranslatedMessagesFileString = untranslatedMessagesFileString.replaceAll(r'\', fileSystem.path.separator);
    return fileSystem.file(untranslatedMessagesFileString);
  }

  static File? _inputsAndOutputsListFileFromPath(FileSystem fileSystem, String? inputsAndOutputsListPath) {
    if (inputsAndOutputsListPath == null) {
      return null;
    }

    return fileSystem.file(
      fileSystem.path.join(inputsAndOutputsListPath, 'gen_l10n_inputs_and_outputs.json'),
    );
  }

  static bool _isValidGetterAndMethodName(String name) {
    if (name.isEmpty) {
      return false;
    }
    // Public Dart method name must not start with an underscore
    if (name[0] == '_') {
      return false;
    }
    // Dart identifiers can only use letters, numbers, underscores, and `$`
    if (name.contains(RegExp(r'[^a-zA-Z_$\d]'))) {
      return false;
    }
    // Dart getter and method name should start with lower case character
    if (name[0].contains(RegExp(r'[A-Z]'))) {
      return false;
    }
    // Dart getter and method name cannot start with a number
    if (name[0].contains(RegExp(r'\d'))) {
      return false;
    }
    return true;
  }

  // Load _allMessages from templateArbFile and _allBundles from all of the ARB
  // files in inputDirectory. Also initialized: supportedLocales.
  void loadResources() {
    for (final String resourceId in _templateBundle.resourceIds) {
      if (!_isValidGetterAndMethodName(resourceId)) {
        throw L10nException(
          'Invalid ARB resource name "$resourceId" in $templateArbFile.\n'
          'Resources names must be valid Dart method names: they have to be '
          'camel case, cannot start with a number or underscore, and cannot '
          'contain non-alphanumeric characters.'
        );
      }
    }
    // The call to .toList() is absolutely necessary. Otherwise, it is an iterator and will call Message's constructor again.
    _allMessages = _templateBundle.resourceIds.map((String id) => Message(
       _templateBundle, _allBundles, id, areResourceAttributesRequired, useEscaping: useEscaping, logger: logger,
    )).toList();
    if (inputsAndOutputsListFile != null) {
      _inputFileList.addAll(_allBundles.bundles.map((AppResourceBundle bundle) {
        return bundle.file.absolute.path;
      }));
    }

    final List<LocaleInfo> allLocales = List<LocaleInfo>.from(_allBundles.locales);
    for (final LocaleInfo preferredLocale in preferredSupportedLocales) {
      final int index = allLocales.indexOf(preferredLocale);
      if (index == -1) {
        throw L10nException(
          "The preferred supported locale, '$preferredLocale', cannot be "
          'added. Please make sure that there is a corresponding ARB file '
          'with translations for the locale, or remove the locale from the '
          'preferred supported locale list.'
        );
      }
      allLocales.removeAt(index);
      allLocales.insertAll(0, preferredSupportedLocales);
    }
    supportedLocales.addAll(allLocales);
  }

  void _addUnimplementedMessage(LocaleInfo locale, String message) {
    if (_unimplementedMessages.containsKey(locale)) {
      _unimplementedMessages[locale]!.add(message);
    } else {
      _unimplementedMessages.putIfAbsent(locale, () => <String>[message]);
    }
  }

  String _generateBaseClassFile(
    String className,
    String fileName,
    String header,
    final LocaleInfo locale,
  ) {
    final Iterable<String> methods = _allMessages.map((Message message) {
      if (message.messages[locale] == null) {
        _addUnimplementedMessage(locale, message.resourceId);
        return _generateMethod(
          message,
          _templateArbLocale,
        );
      }
      return _generateMethod(
        message,
        locale,
      );
    });

    return classFileTemplate
      .replaceAll('@(header)', header.isEmpty ? '' : '$header\n\n')
      .replaceAll('@(language)', describeLocale(locale.toString()))
      .replaceAll('@(baseClass)', className)
      .replaceAll('@(fileName)', fileName)
      .replaceAll('@(class)', '$className${locale.camelCase()}')
      .replaceAll('@(localeName)', locale.toString())
      .replaceAll('@(methods)', methods.join('\n\n'))
      .replaceAll('@(requiresIntlImport)', requiresIntlImport ? "import 'package:intl/intl.dart' as intl;\n\n" : '');
  }

  String _generateSubclass(
    String className,
    AppResourceBundle bundle,
  ) {
    final LocaleInfo locale = bundle.locale;
    final String baseClassName = '$className${LocaleInfo.fromString(locale.languageCode).camelCase()}';

    _allMessages
      .where((Message message) => message.messages[locale] == null)
      .forEach((Message message) {
        _addUnimplementedMessage(locale, message.resourceId);
      });

    final Iterable<String> methods = _allMessages
      .where((Message message) => message.messages[locale] != null)
      .map((Message message) => _generateMethod(message, locale));

    return subclassTemplate
      .replaceAll('@(language)', describeLocale(locale.toString()))
      .replaceAll('@(baseLanguageClassName)', baseClassName)
      .replaceAll('@(class)', '$className${locale.camelCase()}')
      .replaceAll('@(localeName)', locale.toString())
      .replaceAll('@(methods)', methods.join('\n\n'));
  }

  // Generate the AppLocalizations class, its LocalizationsDelegate subclass,
  // and all AppLocalizations subclasses for every locale. This method by
  // itself does not generate the output files.
  String _generateCode() {
    bool isBaseClassLocale(LocaleInfo locale, String language) {
      return locale.languageCode == language
          && locale.countryCode == null
          && locale.scriptCode == null;
    }

    List<LocaleInfo> getLocalesForLanguage(String language) {
      return _allBundles.bundles
        // Return locales for the language specified, except for the base locale itself
        .where((AppResourceBundle bundle) {
          final LocaleInfo locale = bundle.locale;
          return !isBaseClassLocale(locale, language) && locale.languageCode == language;
        })
        .map((AppResourceBundle bundle) => bundle.locale).toList();
    }

    final String directory = _fs.path.basename(outputDirectory.path);
    final String outputFileName = _fs.path.basename(baseOutputFile.path);
    if (!outputFileName.endsWith('.dart')) {
      throw L10nException(
        "The 'output-localization-file', $outputFileName, is invalid.\n"
        'The file name must have a .dart extension.'
      );
    }

    final Iterable<String> supportedLocalesCode = supportedLocales.map((LocaleInfo locale) {
      final String languageCode = locale.languageCode;
      final String? countryCode = locale.countryCode;
      final String? scriptCode = locale.scriptCode;

      if (countryCode == null && scriptCode == null) {
        return "Locale('$languageCode')";
      } else if (countryCode != null && scriptCode == null) {
        return "Locale('$languageCode', '$countryCode')";
      } else if (countryCode != null && scriptCode != null) {
        return "Locale.fromSubtags(languageCode: '$languageCode', countryCode: '$countryCode', scriptCode: '$scriptCode')";
      } else {
        return "Locale.fromSubtags(languageCode: '$languageCode', scriptCode: '$scriptCode')";
      }
    });

    final Set<String> supportedLanguageCodes = Set<String>.from(
      _allBundles.locales.map<String>((LocaleInfo locale) => "'${locale.languageCode}'")
    );

    final List<LocaleInfo> allLocales = _allBundles.locales.toList()..sort();
    final int extensionIndex = outputFileName.indexOf('.');
    if (extensionIndex <= 0) {
      throw L10nException(
        "The 'output-localization-file', $outputFileName, is invalid.\n"
        'The base name cannot be empty.'
      );
    }
    final String fileName = outputFileName.substring(0, extensionIndex);
    final String fileExtension = outputFileName.substring(extensionIndex + 1);
    for (final LocaleInfo locale in allLocales) {
      if (isBaseClassLocale(locale, locale.languageCode)) {
        final File languageMessageFile = outputDirectory.childFile('${fileName}_$locale.$fileExtension');

        // Generate the template for the base class file. Further string
        // interpolation will be done to determine if there are
        // subclasses that extend the base class.
        final String languageBaseClassFile = _generateBaseClassFile(
          className,
          outputFileName,
          header,
          locale,
        );

        // Every locale for the language except the base class.
        final List<LocaleInfo> localesForLanguage = getLocalesForLanguage(locale.languageCode);

        // Generate every subclass that is needed for the particular language
        final Iterable<String> subclasses = localesForLanguage.map<String>((LocaleInfo locale) {
          return _generateSubclass(
            className,
            _allBundles.bundleFor(locale)!,
          );
        });

        _languageFileMap.putIfAbsent(languageMessageFile, () {
          return languageBaseClassFile.replaceAll('@(subclasses)', subclasses.join());
        });
      }
    }

    final List<String> sortedClassImports = supportedLocales
      .where((LocaleInfo locale) => isBaseClassLocale(locale, locale.languageCode))
      .map((LocaleInfo locale) {
        final String library = '${fileName}_$locale';
        if (useDeferredLoading) {
          return "import '$library.$fileExtension' deferred as $library;";
        } else {
          return "import '$library.$fileExtension';";
        }
      })
      .toList()
      ..sort();

    final String delegateClass = _generateDelegateClass(
      allBundles: _allBundles,
      className: className,
      supportedLanguageCodes: supportedLanguageCodes,
      useDeferredLoading: useDeferredLoading,
      fileName: fileName,
    );

    return fileTemplate
      .replaceAll('@(header)', header.isEmpty ? '' : '$header\n')
      .replaceAll('@(class)', className)
      .replaceAll('@(methods)', _allMessages.map((Message message) => generateBaseClassMethod(message, _templateArbLocale)).join('\n'))
      .replaceAll('@(importFile)', '$directory/$outputFileName')
      .replaceAll('@(supportedLocales)', supportedLocalesCode.join(',\n    '))
      .replaceAll('@(supportedLanguageCodes)', supportedLanguageCodes.join(', '))
      .replaceAll('@(messageClassImports)', sortedClassImports.join('\n'))
      .replaceAll('@(delegateClass)', delegateClass)
      .replaceAll('@(requiresFoundationImport)', useDeferredLoading ? '' : "import 'package:flutter/foundation.dart';")
      .replaceAll('@(requiresIntlImport)', requiresIntlImport ? "import 'package:intl/intl.dart' as intl;" : '')
      .replaceAll('@(canBeNullable)', usesNullableGetter ? '?' : '')
      .replaceAll('@(needsNullCheck)', usesNullableGetter ? '' : '!')
      // Removes all trailing whitespace from the generated file.
      .split('\n').map((String line) => line.trimRight()).join('\n')
      // Cleans out unnecessary newlines.
      .replaceAll('\n\n\n', '\n\n');
  }

  String _generateMethod(Message message, LocaleInfo locale) {
    try {
      // Determine if we must import intl for date or number formatting.
      if (message.placeholdersRequireFormatting) {
        requiresIntlImport = true;
      }

      final String translationForMessage = message.messages[locale]!;
      final Node node = message.parsedMessages[locale]!;
      // If parse tree is only a string, then return a getter method.
      if (node.children.every((Node child) => child.type == ST.string)) {
        // Use the parsed translation to handle escaping with the same behavior.
        return getterTemplate
          .replaceAll('@(name)', message.resourceId)
          .replaceAll('@(message)', "'${generateString(node.children.map((Node child) => child.value!).join())}'");
      }

      final List<String> tempVariables = <String>[];
      // Get a unique temporary variable name.
      int variableCount = 0;
      String getTempVariableName() {
        return '_temp${variableCount++}';
      }

      // Do a DFS post order traversal through placeholderExpr, pluralExpr, and selectExpr nodes.
      // When traversing through a placeholderExpr node, return "$placeholderName".
      // When traversing through a pluralExpr node, return "$tempVarN" and add variable declaration in "tempVariables".
      // When traversing through a selectExpr node, return "$tempVarN" and add variable declaration in "tempVariables".
      // When traversing through a message node, return concatenation of all of "generateVariables(child)" for each child.
      String generateVariables(Node node, { bool isRoot = false }) {
        switch (node.type) {
          case ST.message:
            final List<String> expressions = node.children.map<String>((Node node) {
              if (node.type == ST.string) {
                return node.value!;
              }
              return generateVariables(node);
            }).toList();
            return generateReturnExpr(expressions);

          case ST.placeholderExpr:
            assert(node.children[1].type == ST.identifier);
            final String identifier = node.children[1].value!;
            final Placeholder placeholder = message.placeholders[identifier]!;
            if (placeholder.requiresFormatting) {
              return '\$${node.children[1].value}String';
            }
            return '\$${node.children[1].value}';

          case ST.pluralExpr:
            requiresIntlImport = true;
            final Map<String, String> pluralLogicArgs = <String, String>{};
            // Recall that pluralExpr are of the form
            // pluralExpr := "{" ID "," "plural" "," pluralParts "}"
            assert(node.children[1].type == ST.identifier);
            assert(node.children[5].type == ST.pluralParts);

            final Node identifier = node.children[1];
            final Node pluralParts = node.children[5];

            for (final Node pluralPart in pluralParts.children.reversed) {
              String pluralCase;
              Node pluralMessage;
              if (pluralPart.children[0].value == '=') {
                assert(pluralPart.children[1].type == ST.number);
                assert(pluralPart.children[3].type == ST.message);
                pluralCase = pluralPart.children[1].value!;
                pluralMessage = pluralPart.children[3];
              } else {
                assert(pluralPart.children[0].type == ST.identifier || pluralPart.children[0].type == ST.other);
                assert(pluralPart.children[2].type == ST.message);
                pluralCase = pluralPart.children[0].value!;
                pluralMessage = pluralPart.children[2];
              }
              if (!pluralLogicArgs.containsKey(pluralCases[pluralCase])) {
                final String pluralPartExpression = generateVariables(pluralMessage);
                final String? transformedPluralCase = pluralCases[pluralCase];
                // A valid plural case is one of "=0", "=1", "=2", "zero", "one", "two", "few", "many", or "other".
                if (transformedPluralCase == null) {
                  throw L10nParserException(
                    '''
The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "many", or "other.
    $pluralCase is not a valid plural case.''',
                    _inputFileNames[locale]!,
                    message.resourceId,
                    translationForMessage,
                    pluralPart.positionInMessage,
                  );
                }
                pluralLogicArgs[transformedPluralCase] = '      ${pluralCases[pluralCase]}: $pluralPartExpression,';
              } else if (!suppressWarnings) {
                logger.printWarning('''
[${_inputFileNames[locale]}:${message.resourceId}] ICU Syntax Warning: The plural part specified below is overridden by a later plural part.
    $translationForMessage
    ${Parser.indentForError(pluralPart.positionInMessage)}''');
              }
            }
            final String tempVarName = getTempVariableName();
            tempVariables.add(pluralVariableTemplate
              .replaceAll('@(varName)', tempVarName)
              .replaceAll('@(count)', identifier.value!)
              .replaceAll('@(pluralLogicArgs)', pluralLogicArgs.values.join('\n'))
            );
            return '\$$tempVarName';

          case ST.selectExpr:
            requiresIntlImport = true;
            // Recall that pluralExpr are of the form
            // pluralExpr := "{" ID "," "plural" "," pluralParts "}"
            assert(node.children[1].type == ST.identifier);
            assert(node.children[5].type == ST.selectParts);

            final Node identifier = node.children[1];
            final List<String> selectLogicArgs = <String>[];
            final Node selectParts = node.children[5];
            for (final Node selectPart in selectParts.children) {
              assert(selectPart.children[0].type == ST.identifier || selectPart.children[0].type == ST.other);
              assert(selectPart.children[2].type == ST.message);
              final String selectCase = selectPart.children[0].value!;
              final Node selectMessage = selectPart.children[2];
              final String selectPartExpression = generateVariables(selectMessage);
              selectLogicArgs.add("        '$selectCase': $selectPartExpression,");
            }
            final String tempVarName = getTempVariableName();
            tempVariables.add(selectVariableTemplate
              .replaceAll('@(varName)', tempVarName)
              .replaceAll('@(choice)', identifier.value!)
              .replaceAll('@(selectCases)', selectLogicArgs.join('\n'))
            );
            return '\$$tempVarName';
          // ignore: no_default_cases
          default:
            throw Exception('Cannot call "generateHelperMethod" on node type ${node.type}');
        }
      }
      final String messageString = generateVariables(node, isRoot: true);
      final String tempVarLines = tempVariables.isEmpty ? '' : '${tempVariables.join('\n')}\n';
      return methodTemplate
                .replaceAll('@(name)', message.resourceId)
                .replaceAll('@(parameters)', generateMethodParameters(message).join(', '))
                .replaceAll('@(dateFormatting)', generateDateFormattingLogic(message))
                .replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message))
                .replaceAll('@(tempVars)', tempVarLines)
                .replaceAll('@(message)', messageString)
                .replaceAll('@(none)\n', '');
    } on L10nParserException catch (error) {
      logger.printError(error.toString());
      hadErrors = true;
      return '';
    }
  }

  List<String> writeOutputFiles({ bool isFromYaml = false }) {
    // First, generate the string contents of all necessary files.
    final String generatedLocalizationsFile = _generateCode();

    // If there were any syntax errors, don't write to files.
    if (hadErrors) {
      throw L10nException('Found syntax errors.');
    }

    // A pubspec.yaml file is required when using a synthetic package. If it does not
    // exist, create a blank one.
    if (useSyntheticPackage) {
      final Directory syntheticPackageDirectory = projectDirectory != null
          ? projectDirectory!.childDirectory(_defaultSyntheticPackagePath(_fs))
          : _fs.directory(_defaultSyntheticPackagePath(_fs));
      syntheticPackageDirectory.createSync(recursive: true);
      final File flutterGenPubspec = syntheticPackageDirectory.childFile('pubspec.yaml');
      if (!flutterGenPubspec.existsSync()) {
        flutterGenPubspec.writeAsStringSync(emptyPubspecTemplate);
      }
    }

    // Since all validity checks have passed up to this point,
    // write the contents into the directory.
    outputDirectory.createSync(recursive: true);

    // Ensure that the created directory has read/write permissions.
    final FileStat fileStat = outputDirectory.statSync();
    if (_isNotReadable(fileStat) || _isNotWritable(fileStat)) {
      throw L10nException(
        "The 'output-dir' directory, $outputDirectory, doesn't allow reading and writing.\n"
        'Please ensure that the user has read and write permissions.'
      );
    }

    // Generate the required files for localizations.
    _languageFileMap.forEach((File file, String contents) {
      file.writeAsStringSync(contents);
      _outputFileList.add(file.absolute.path);
    });

    baseOutputFile.writeAsStringSync(generatedLocalizationsFile);
    final File? messagesFile = untranslatedMessagesFile;
    if (messagesFile != null) {
      _generateUntranslatedMessagesFile(logger, messagesFile);
    } else if (_unimplementedMessages.isNotEmpty) {
      _unimplementedMessages.forEach((LocaleInfo locale, List<String> messages) {
        logger.printStatus('"$locale": ${messages.length} untranslated message(s).');
      });
      if (isFromYaml) {
        logger.printStatus(
          'To see a detailed report, use the untranslated-messages-file \n'
          'option in the l10n.yaml file:\n'
          'untranslated-messages-file: desiredFileName.txt\n'
          '<other option>: <other selection> \n\n'
        );
      } else {
        logger.printStatus(
          'To see a detailed report, use the --untranslated-messages-file \n'
          'option in the flutter gen-l10n tool:\n'
          'flutter gen-l10n --untranslated-messages-file=desiredFileName.txt\n'
          '<other options> \n\n'
        );
      }

      logger.printStatus(
        'This will generate a JSON format file containing all messages that \n'
        'need to be translated.'
      );
    }
    final File? inputsAndOutputsListFileLocal = inputsAndOutputsListFile;
    _outputFileList.add(baseOutputFile.absolute.path);
    if (inputsAndOutputsListFileLocal != null) {
      // Generate a JSON file containing the inputs and outputs of the gen_l10n script.
      if (!inputsAndOutputsListFileLocal.existsSync()) {
        inputsAndOutputsListFileLocal.createSync(recursive: true);
      }

      inputsAndOutputsListFileLocal.writeAsStringSync(
        json.encode(<String, Object> {
          'inputs': _inputFileList,
          'outputs': _outputFileList,
        }),
      );
    }

    return _outputFileList;
  }

  void _generateUntranslatedMessagesFile(Logger logger, File untranslatedMessagesFile) {
    if (_unimplementedMessages.isEmpty) {
      untranslatedMessagesFile.writeAsStringSync('{}');
      _outputFileList.add(untranslatedMessagesFile.absolute.path);
      return;
    }

    String resultingFile = '{\n';
    int count = 0;
    final int numberOfLocales = _unimplementedMessages.length;
    _unimplementedMessages.forEach((LocaleInfo locale, List<String> messages) {
      resultingFile += '  "$locale": [\n';

      for (int i = 0; i < messages.length; i += 1) {
        resultingFile += '    "${messages[i]}"';
        if (i != messages.length - 1) {
          resultingFile += ',';
        }
        resultingFile += '\n';
      }

      resultingFile += '  ]';
      count += 1;
      if (count < numberOfLocales) {
        resultingFile += ',\n';
      }
      resultingFile += '\n';
    });

    resultingFile += '}\n';
    untranslatedMessagesFile.writeAsStringSync(resultingFile);
    _outputFileList.add(untranslatedMessagesFile.absolute.path);
  }
}
