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

import 'dart:convert' show json;
import 'dart:io';

import 'localizations_utils.dart';

// The first suffix in kPluralSuffixes must be "Other". "Other" is special
// because it's the only one that is required.
const List<String> kPluralSuffixes = <String>['Other', 'Zero', 'One', 'Two', 'Few', 'Many'];
final RegExp kPluralRegexp = RegExp(r'(\w*)(' + kPluralSuffixes.skip(1).join(r'|') + r')$');

class ValidationError implements Exception {
  ValidationError(this.message);
  final String message;
  @override
  String toString() => message;
}

/// Sanity checking of the @foo metadata in the English translations, *_en.arb.
///
/// - For each foo, resource, there must be a corresponding @foo.
/// - For each @foo resource, there must be a corresponding foo, except
///   for plurals, for which there must be a fooOther.
/// - Each @foo resource must have a Map value with a String valued
///   description entry.
///
/// Throws an exception upon failure.
void validateEnglishLocalizations(File file) {
  final errorMessages = StringBuffer();

  if (!file.existsSync()) {
    errorMessages.writeln('English localizations do not exist: $file');
    throw ValidationError(errorMessages.toString());
  }

  final bundle = json.decode(file.readAsStringSync()) as Map<String, dynamic>;

  for (final String resourceId in bundle.keys) {
    if (resourceId.startsWith('@')) {
      continue;
    }

    if (bundle['@$resourceId'] != null) {
      continue;
    }

    bool checkPluralResource(String suffix) {
      final int suffixIndex = resourceId.indexOf(suffix);
      return suffixIndex != -1 && bundle['@${resourceId.substring(0, suffixIndex)}'] != null;
    }

    if (kPluralSuffixes.any(checkPluralResource)) {
      continue;
    }

    errorMessages.writeln('A value was not specified for @$resourceId');
  }

  for (final String atResourceId in bundle.keys) {
    if (!atResourceId.startsWith('@')) {
      continue;
    }

    final dynamic atResourceValue = bundle[atResourceId];
    final Map<String, dynamic>? atResource = atResourceValue is Map<String, dynamic>
        ? atResourceValue
        : null;
    if (atResource == null) {
      errorMessages.writeln('A map value was not specified for $atResourceId');
      continue;
    }

    final bool optional = atResource.containsKey('optional');
    final description = atResource['description'] as String?;
    if (description == null && !optional) {
      errorMessages.writeln('No description specified for $atResourceId');
    }

    final plural = atResource['plural'] as String?;
    final String resourceId = atResourceId.substring(1);
    if (plural != null) {
      final resourceIdOther = '${resourceId}Other';
      if (!bundle.containsKey(resourceIdOther)) {
        errorMessages.writeln('Default plural resource $resourceIdOther undefined');
      }
    } else {
      if (!optional && !bundle.containsKey(resourceId)) {
        errorMessages.writeln('No matching $resourceId defined for $atResourceId');
      }
    }
  }

  if (errorMessages.isNotEmpty) {
    throw ValidationError(errorMessages.toString());
  }
}

/// This removes undefined localizations (localizations that aren't present in
/// the canonical locale anymore) by:
///
/// 1. Looking up the canonical (English, in this case) localizations.
/// 2. For each locale, getting the resources.
/// 3. Determining the set of keys that aren't plural variations (we're only
///    interested in the base terms being translated and not their variants)
/// 4. Determining the set of invalid keys; that is those that are (non-plural)
///    keys in the resources for this locale, but which _aren't_ keys in the
///    canonical list.
/// 5. Removes the invalid mappings from this resource's locale.
void removeUndefinedLocalizations(Map<LocaleInfo, Map<String, String>> localeToResources) {
  final Map<String, String> canonicalLocalizations =
      localeToResources[LocaleInfo.fromString('en')]!;
  final canonicalKeys = Set<String>.from(canonicalLocalizations.keys);

  localeToResources.forEach((LocaleInfo locale, Map<String, String> resources) {
    bool isPluralVariation(String key) {
      final Match? pluralMatch = kPluralRegexp.firstMatch(key);
      if (pluralMatch == null) {
        return false;
      }
      final String? prefix = pluralMatch[1];
      return resources.containsKey('${prefix}Other');
    }

    final keys = Set<String>.from(resources.keys.where((String key) => !isPluralVariation(key)));

    final Set<String> invalidKeys = keys.difference(canonicalKeys);
    resources.removeWhere((String key, String value) => invalidKeys.contains(key));
  });
}

/// Enforces the following invariants in our localizations:
///
/// - Resource keys are valid, i.e. they appear in the canonical list.
/// - Resource keys are complete for language-level locales, e.g. "es", "he".
///
/// Uses "en" localizations as the canonical source of locale keys that other
/// locales are compared against.
///
/// If validation fails, throws an exception.
void validateLocalizations(
  Map<LocaleInfo, Map<String, String>> localeToResources,
  Map<LocaleInfo, Map<String, dynamic>> localeToAttributes, {
  bool removeUndefined = false,
}) {
  final Map<String, String> canonicalLocalizations =
      localeToResources[LocaleInfo.fromString('en')]!;
  final canonicalKeys = Set<String>.from(canonicalLocalizations.keys);
  final errorMessages = StringBuffer();
  var explainMissingKeys = false;
  for (final LocaleInfo locale in localeToResources.keys) {
    final Map<String, String> resources = localeToResources[locale]!;

    // Whether `key` corresponds to one of the plural variations of a key with
    // the same prefix and suffix "Other".
    //
    // Many languages require only a subset of these variations, so we do not
    // require them so long as the "Other" variation exists.
    bool isPluralVariation(String key) {
      final Match? pluralMatch = kPluralRegexp.firstMatch(key);
      if (pluralMatch == null) {
        return false;
      }
      final String? prefix = pluralMatch[1];
      return resources.containsKey('${prefix}Other');
    }

    final keys = Set<String>.from(resources.keys.where((String key) => !isPluralVariation(key)));

    // Make sure keys are valid (i.e. they also exist in the canonical
    // localizations)
    final Set<String> invalidKeys = keys.difference(canonicalKeys);
    if (invalidKeys.isNotEmpty && !removeUndefined) {
      errorMessages.writeln(
        'Locale "$locale" contains invalid resource keys: ${invalidKeys.join(', ')}',
      );
    }

    // For language-level locales only, check that they have a complete list of
    // keys, or opted out of using certain ones.
    if (locale.length == 1) {
      final Map<String, dynamic>? attributes = localeToAttributes[locale];
      final missingKeys = <String?>[];
      for (final String missingKey in canonicalKeys.difference(keys)) {
        final dynamic attribute = attributes?[missingKey];
        final bool intentionallyOmitted = attribute is Map && attribute.containsKey('notUsed');
        if (!intentionallyOmitted && !isPluralVariation(missingKey)) {
          missingKeys.add(missingKey);
        }
      }
      if (missingKeys.isNotEmpty) {
        explainMissingKeys = true;
        errorMessages.writeln(
          'Locale "$locale" is missing the following resource keys: ${missingKeys.join(', ')}',
        );
      }
    }
  }

  if (errorMessages.isNotEmpty) {
    if (explainMissingKeys) {
      errorMessages
        ..writeln()
        ..writeln(
          'If a resource key is intentionally omitted, add an attribute corresponding '
          'to the key name with a "notUsed" property explaining why. Example:',
        )
        ..writeln()
        ..writeln('"@anteMeridiemAbbreviation": {')
        ..writeln('  "notUsed": "Sindhi time format does not use a.m. indicator"')
        ..writeln('}');
    }
    throw ValidationError(errorMessages.toString());
  }
}
