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