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

// This program updates the language locale arb files with any missing resource
// entries that are included in the English arb files. This is useful when
// adding new resources for localization. You can just add the appropriate
// entries to the English arb file and then run this script. It will then check
// all of the other language locale arb files and update them with the English
// source for any missing resources. These will be picked up by the localization
// team and then translated.
//
// ## Usage
//
// Run this program from the root of the git repository.
//
// ```
// dart dev/tools/localization/bin/gen_missing_localizations.dart
// ```

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

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

import '../localizations_utils.dart';
import '../localizations_validator.dart';

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

  final String localizationPath = path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n');
  updateMissingResources(localizationPath, 'material');
  updateMissingResources(localizationPath, 'cupertino');
}

Map<String, dynamic> loadBundle(File file) {
  if (!FileSystemEntity.isFileSync(file.path))
    exitWithError('Unable to find input file: ${file.path}');
  return json.decode(file.readAsStringSync()) as Map<String, dynamic>;
}

void writeBundle(File file, Map<String, dynamic> bundle) {
  final StringBuffer contents = StringBuffer();
  contents.writeln('{');
  for (final String key in bundle.keys) {
    contents.writeln('  "$key": ${json.encode(bundle[key])}${key == bundle.keys.last ? '' : ','}');
  }
  contents.writeln('}');
  file.writeAsStringSync(contents.toString());
}

Set<String> resourceKeys(Map<String, dynamic> bundle) {
  return Set<String>.from(
    // Skip any attribute keys
    bundle.keys.where((String key) => !key.startsWith('@'))
  );
}

bool intentionallyOmitted(String key, Map<String, dynamic> bundle) {
  final String attributeKey = '@$key';
  final dynamic attribute = bundle[attributeKey];
  return attribute is Map && attribute.containsKey('notUsed');
}

/// Whether `key` corresponds to one of the plural variations of a key with
/// the same prefix and suffix "Other".
bool isPluralVariation(String key, Map<String, dynamic> bundle) {
  final Match? pluralMatch = kPluralRegexp.firstMatch(key);
  if (pluralMatch == null)
    return false;
  final String prefix = pluralMatch[1]!;
  return bundle.containsKey('${prefix}Other');
}

void updateMissingResources(String localizationPath, String groupPrefix) {
  final Directory localizationDir = Directory(localizationPath);
  final RegExp filenamePattern = RegExp('${groupPrefix}_(\\w+)\\.arb');

  final Map<String, dynamic> englishBundle = loadBundle(File(path.join(localizationPath, '${groupPrefix}_en.arb')));
  final Set<String> requiredKeys = resourceKeys(englishBundle);

  for (final FileSystemEntity entity in localizationDir.listSync().toList()..sort(sortFilesByPath)) {
    final String entityPath = entity.path;
    if (FileSystemEntity.isFileSync(entityPath) && filenamePattern.hasMatch(entityPath)) {
      final String localeString = filenamePattern.firstMatch(entityPath)![1]!;
      final LocaleInfo locale = LocaleInfo.fromString(localeString);

      // Only look at top-level language locales
      if (locale.length == 1) {
        final File arbFile = File(entityPath);
        final Map<String, dynamic> localeBundle = loadBundle(arbFile);
        final Set<String> localeResources = resourceKeys(localeBundle);
        final Set<String> missingResources = requiredKeys.difference(localeResources).where(
          (String key) => !isPluralVariation(key, localeBundle) && !intentionallyOmitted(key, localeBundle)
        ).toSet();
        if (missingResources.isNotEmpty) {
          localeBundle.addEntries(missingResources.map((String k) =>
            MapEntry<String, String>(k, englishBundle[k].toString())));
          writeBundle(arbFile, localeBundle);
          print('Updated $entityPath with missing entries for $missingResources');
        }
      }
    }
  }
}
