// 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,
      logger: logger,
    )
      ..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.
// TODO(thkim1011): Let's store the output of this function in the Message class, so that we don't
// recompute this. See https://github.com/flutter/flutter/issues/112709
List<String> generateMethodParameters(Message message) {
  return message.placeholders.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.map((Placeholder placeholder) => placeholder.name).toList();
}

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

  final Iterable<String> formatStatements = message.placeholders
    .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
    .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 ?? '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,
    required Logger logger,
  }) {
    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,
      logger: logger,
    );
  }

  /// 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,
  });

  final FileSystem _fs;
  Iterable<Message> _allMessages = <Message>[];
  late final AppResourceBundleCollection _allBundles = AppResourceBundleCollection(inputDirectory);

  late final AppResourceBundle _templateBundle = AppResourceBundle(templateArbFile);
  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;

  /// 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.
  @visibleForTesting
  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;

  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;
    }

    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 getter and method name cannot contain non-alphanumeric symbols
    if (name.contains(RegExp(r'[^a-zA-Z_\d]'))) {
      return false;
    }
    // Dart method name must start with lower case character
    if (name[0].contains(RegExp(r'[A-Z]'))) {
      return false;
    }
    // Dart class 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() {
    _allMessages = _templateBundle.resourceIds.map((String id) => Message(
       _templateBundle.resources, id, areResourceAttributesRequired,
    ));
    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.'
        );
      }
    }

    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,
    AppResourceBundle bundle,
    AppResourceBundle templateBundle,
    Iterable<Message> messages,
  ) {
    final LocaleInfo locale = bundle.locale;

    final Iterable<String> methods = messages.map((Message message) {
      if (bundle.translationFor(message) == null) {
        _addUnimplementedMessage(locale, message.resourceId);
      }

      return _generateMethod(
        message,
        bundle.file.basename,
        bundle.translationFor(message) ?? templateBundle.translationFor(message)!,
      );
    });

    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,
    Iterable<Message> messages,
  ) {
    final LocaleInfo locale = bundle.locale;
    final String baseClassName = '$className${LocaleInfo.fromString(locale.languageCode).camelCase()}';

    messages
      .where((Message message) => bundle.translationFor(message) == null)
      .forEach((Message message) {
        _addUnimplementedMessage(locale, message.resourceId);
      });

    final Iterable<String> methods = messages
      .where((Message message) => bundle.translationFor(message) != null)
      .map((Message message) => _generateMethod(message, bundle.file.basename, bundle.translationFor(message)!));

    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,
          _allBundles.bundleFor(locale)!,
          _allBundles.bundleFor(_templateArbLocale)!,
          _allMessages,
        );

        // 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)!,
            _allMessages,
          );
        });

        _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, String filename, String translationForMessage) {
    // Determine if we must import intl for date or number formatting.
    if (message.placeholdersRequireFormatting) {
      requiresIntlImport = true;
    }

    final Node node = Parser(message.resourceId, filename, translationForMessage).parse();
    // 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> helperMethods = <String>[];

    // Get a unique helper method name.
    int methodNameCount = 0;
    String getHelperMethodName() {
      return '_${message.resourceId}${methodNameCount++}';
    }

    // Do a DFS post order traversal, generating dependent
    // placeholder, plural, select helper methods, and combine these into
    // one message. Returns the method/placeholder to use in parent string.
    HelperMethod generateHelperMethods(Node node, { bool isRoot = false }) {
      final Set<Placeholder> dependentPlaceholders = <Placeholder>{};
      switch (node.type) {
        case ST.message:
          final List<HelperMethod> helpers = node.children.map<HelperMethod>((Node node) {
            if (node.type == ST.string) {
              return HelperMethod(<Placeholder>{}, string: node.value);
            }
            final HelperMethod helper = generateHelperMethods(node);
            dependentPlaceholders.addAll(helper.dependentPlaceholders);
            return helper;
          }).toList();
          final String messageString = generateReturnExpr(helpers);

          // If the message is just a normal string, then only return the string.
          if (dependentPlaceholders.isEmpty) {
            return HelperMethod(dependentPlaceholders, string: messageString);
          }

          // For messages, if we are generating the actual overridden method, then we should also deal with
          // date and number formatting here.
          final String helperMethodName = getHelperMethodName();
          final HelperMethod messageHelper = HelperMethod(dependentPlaceholders, helper: helperMethodName);
          if (isRoot) {
            helperMethods.add(methodTemplate
              .replaceAll('@(name)', message.resourceId)
              .replaceAll('@(parameters)', generateMethodParameters(message).join(', '))
              .replaceAll('@(dateFormatting)', generateDateFormattingLogic(message))
              .replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message))
              .replaceAll('@(message)', messageString)
              .replaceAll('@(none)\n', '')
            );
          } else {
            helperMethods.add(messageHelperTemplate
              .replaceAll('@(name)', helperMethodName)
              .replaceAll('@(parameters)', messageHelper.methodParameters)
              .replaceAll('@(message)', messageString)
            );
          }
          return messageHelper;

        case ST.placeholderExpr:
          assert(node.children[1].type == ST.identifier);
          final Node identifier = node.children[1];
          // Check that placeholders exist.
          // TODO(thkim1011): Make message.placeholders a map so that we don't need to do linear time search.
          // See https://github.com/flutter/flutter/issues/112709
          final Placeholder placeholder = message.placeholders.firstWhere(
            (Placeholder placeholder) => placeholder.name == identifier.value,
            orElse: () {
              throw L10nException('''
Make sure that the specified placeholder is defined in your arb file.
$translationForMessage
${Parser.indentForError(identifier.positionInMessage)}''');
            }
          );
          dependentPlaceholders.add(placeholder);
          return HelperMethod(dependentPlaceholders, placeholder: placeholder);

        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];

          // Check that identifier exists and is of type int or num.
          final Placeholder placeholder = message.placeholders.firstWhere(
            (Placeholder placeholder) => placeholder.name == identifier.value,
            orElse: () {
              throw L10nException('''
Make sure that the specified plural placeholder is defined in your arb file.
$translationForMessage
${List<String>.filled(identifier.positionInMessage, ' ').join()}^''');
            }
          );
          dependentPlaceholders.add(placeholder);
          // TODO(thkim1011): Uncomment the following lines after Message refactor.
          // See https://github.com/flutter/flutter/issues/112709.
//           if (placeholder.type != 'num' && placeholder.type != 'int') {
//             throw L10nException('''
// The specified placeholder must be of type int or num.
// $translationForMessage
// ${List<String>.filled(identifier.positionInMessage, ' ').join()}^''');
//           }

          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 HelperMethod pluralPartHelper = generateHelperMethods(pluralMessage);
              pluralLogicArgs[pluralCases[pluralCase]!] = '      ${pluralCases[pluralCase]}: ${pluralPartHelper.helperOrPlaceholder},';
              dependentPlaceholders.addAll(pluralPartHelper.dependentPlaceholders);
            } else {
              logger.printWarning('''
The plural part specified below is overrided by a later plural part.
$translationForMessage
${Parser.indentForError(pluralPart.positionInMessage)}
''');
            }
          }
          final String helperMethodName = getHelperMethodName();
          final HelperMethod pluralHelper = HelperMethod(dependentPlaceholders, helper: helperMethodName);
          helperMethods.add(pluralHelperTemplate
            .replaceAll('@(name)', helperMethodName)
            .replaceAll('@(parameters)', pluralHelper.methodParameters)
            .replaceAll('@(count)', identifier.value!)
            .replaceAll('@(pluralLogicArgs)', pluralLogicArgs.values.join('\n'))
          );
          return pluralHelper;

        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];
          // Check that identifier exists
          final Placeholder placeholder = message.placeholders.firstWhere(
            (Placeholder placeholder) => placeholder.name == identifier.value,
            orElse: () {
              throw L10nException('''
Make sure that the specified select placeholder is defined in your arb file.
$translationForMessage
${Parser.indentForError(identifier.positionInMessage)}''');
            }
          );
          dependentPlaceholders.add(placeholder);
          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 HelperMethod selectPartHelper = generateHelperMethods(selectMessage);
            selectLogicArgs.add("        '$selectCase': ${selectPartHelper.helperOrPlaceholder},");
            dependentPlaceholders.addAll(selectPartHelper.dependentPlaceholders);
          }
          final String helperMethodName = getHelperMethodName();
          final HelperMethod selectHelper = HelperMethod(dependentPlaceholders, helper: helperMethodName);

          helperMethods.add(selectHelperTemplate
            .replaceAll('@(name)', helperMethodName)
            .replaceAll('@(parameters)', selectHelper.methodParameters)
            .replaceAll('@(choice)', identifier.value!)
            .replaceAll('@(selectCases)', selectLogicArgs.join('\n'))
          );
          return HelperMethod(dependentPlaceholders, helper: helperMethodName);
        // ignore: no_default_cases
        default:
          throw Exception('Cannot call "generateHelperMethod" on node type ${node.type}');
      }
    }
    generateHelperMethods(node, isRoot: true);
    return helperMethods.last.replaceAll('@(helperMethods)', helperMethods.sublist(0, helperMethods.length - 1).join('\n\n'));
  }

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

    // 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);
  }
}
