// 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 StringBuffer errorMessages = StringBuffer();

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

  final Map<String, dynamic> 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 String? description = atResource['description'] as String?;
    if (description == null && !optional)
      errorMessages.writeln('No description specified for $atResourceId');

    final String? plural = atResource['plural'] as String?;
    final String resourceId = atResourceId.substring(1);
    if (plural != null) {
      final String 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());
}

/// 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,
) {
  final Map<String, String> canonicalLocalizations = localeToResources[LocaleInfo.fromString('en')]!;
  final Set<String> canonicalKeys = Set<String>.from(canonicalLocalizations.keys);
  final StringBuffer errorMessages = StringBuffer();
  bool 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 Set<String> 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)
      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 List<String?> 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());
  }
}
