// 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';
import 'dart:io';

import 'package:args/args.dart' as argslib;
import 'package:meta/meta.dart';

import 'language_subtag_registry.dart';

typedef HeaderGenerator = String Function(String regenerateInstructions);
typedef ConstructorGenerator = String Function(LocaleInfo locale);

int sortFilesByPath(FileSystemEntity a, FileSystemEntity b) {
  return a.path.compareTo(b.path);
}

/// Simple data class to hold parsed locale. Does not promise validity of any data.
@immutable
class LocaleInfo implements Comparable<LocaleInfo> {
  const LocaleInfo({
    required this.languageCode,
    this.scriptCode,
    this.countryCode,
    required this.length,
    required this.originalString,
  });

  /// Simple parser. Expects the locale string to be in the form of 'language_script_COUNTRY'
  /// where the language is 2 characters, script is 4 characters with the first uppercase,
  /// and country is 2-3 characters and all uppercase.
  ///
  /// 'language_COUNTRY' or 'language_script' are also valid. Missing fields will be null.
  ///
  /// When `deriveScriptCode` is true, if [scriptCode] was unspecified, it will
  /// be derived from the [languageCode] and [countryCode] if possible.
  factory LocaleInfo.fromString(String locale, {bool deriveScriptCode = false}) {
    final List<String> codes = locale.split('_'); // [language, script, country]
    assert(codes.isNotEmpty && codes.length < 4);
    final String languageCode = codes[0];
    String? scriptCode;
    String? countryCode;
    int length = codes.length;
    var originalString = locale;
    if (codes.length == 2) {
      scriptCode = codes[1].length >= 4 ? codes[1] : null;
      countryCode = codes[1].length < 4 ? codes[1] : null;
    } else if (codes.length == 3) {
      scriptCode = codes[1].length > codes[2].length ? codes[1] : codes[2];
      countryCode = codes[1].length < codes[2].length ? codes[1] : codes[2];
    }
    assert(codes[0].isNotEmpty);
    assert(countryCode == null || countryCode.isNotEmpty);
    assert(scriptCode == null || scriptCode.isNotEmpty);

    /// Adds scriptCodes to locales where we are able to assume it to provide
    /// finer granularity when resolving locales.
    ///
    /// The basis of the assumptions here are based off of known usage of scripts
    /// across various countries. For example, we know Taiwan uses traditional (Hant)
    /// script, so it is safe to apply (Hant) to Taiwanese languages.
    if (deriveScriptCode && scriptCode == null) {
      scriptCode = switch ((languageCode, countryCode)) {
        ('zh', 'CN' || 'SG' || null) => 'Hans',
        ('zh', 'TW' || 'HK' || 'MO') => 'Hant',
        ('sr', null) => 'Cyrl',
        _ => null,
      };
      // Increment length if we were able to assume a scriptCode.
      if (scriptCode != null) {
        length += 1;
      }
      // Update the base string to reflect assumed scriptCodes.
      originalString = languageCode;
      if (scriptCode != null) {
        originalString += '_$scriptCode';
      }
      if (countryCode != null) {
        originalString += '_$countryCode';
      }
    }

    return LocaleInfo(
      languageCode: languageCode,
      scriptCode: scriptCode,
      countryCode: countryCode,
      length: length,
      originalString: originalString,
    );
  }

  final String languageCode;
  final String? scriptCode;
  final String? countryCode;
  final int length; // The number of fields. Ranges from 1-3.
  final String originalString; // Original un-parsed locale string.

  String camelCase() {
    return originalString
        .split('_')
        .map<String>(
          (String part) => part.substring(0, 1).toUpperCase() + part.substring(1).toLowerCase(),
        )
        .join();
  }

  @override
  bool operator ==(Object other) {
    return other is LocaleInfo && other.originalString == originalString;
  }

  @override
  int get hashCode => originalString.hashCode;

  @override
  String toString() {
    return originalString;
  }

  @override
  int compareTo(LocaleInfo other) {
    return originalString.compareTo(other.originalString);
  }
}

/// Parse the data for a locale from a file, and store it in the [attributes]
/// and [resources] keys.
void loadMatchingArbsIntoBundleMaps({
  required Directory directory,
  required RegExp filenamePattern,
  required Map<LocaleInfo, Map<String, String>> localeToResources,
  required Map<LocaleInfo, Map<String, dynamic>> localeToResourceAttributes,
}) {
  /// Set that holds the locales that were assumed from the existing locales.
  ///
  /// For example, when the data lacks data for zh_Hant, we will use the data of
  /// the first Hant Chinese locale as a default by repeating the data. If an
  /// explicit match is later found, we can reference this set to see if we should
  /// overwrite the existing assumed data.
  final assumedLocales = <LocaleInfo>{};

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

      // Helper method to fill the maps with the correct data from file.
      void populateResources(LocaleInfo locale, File file) {
        final Map<String, String> resources = localeToResources[locale]!;
        final Map<String, dynamic> attributes = localeToResourceAttributes[locale]!;
        final bundle = json.decode(file.readAsStringSync()) as Map<String, dynamic>;
        for (final String key in bundle.keys) {
          // The ARB file resource "attributes" for foo are called @foo.
          if (key.startsWith('@')) {
            attributes[key.substring(1)] = bundle[key];
          } else {
            resources[key] = bundle[key] as String;
          }
        }
      }

      // Only pre-assume scriptCode if there is a country or script code to assume off of.
      // When we assume scriptCode based on languageCode-only, we want this initial pass
      // to use the un-assumed version as a base class.
      var locale = LocaleInfo.fromString(
        localeString,
        deriveScriptCode: localeString.split('_').length > 1,
      );
      // Allow overwrite if the existing data is assumed.
      if (assumedLocales.contains(locale)) {
        localeToResources[locale] = <String, String>{};
        localeToResourceAttributes[locale] = <String, dynamic>{};
        assumedLocales.remove(locale);
      } else {
        localeToResources[locale] ??= <String, String>{};
        localeToResourceAttributes[locale] ??= <String, dynamic>{};
      }
      populateResources(locale, arbFile);
      // Add an assumed locale to default to when there is no info on scriptOnly locales.
      locale = LocaleInfo.fromString(localeString, deriveScriptCode: true);
      if (locale.scriptCode != null) {
        final scriptLocale = LocaleInfo.fromString('${locale.languageCode}_${locale.scriptCode}');
        if (!localeToResources.containsKey(scriptLocale)) {
          assumedLocales.add(scriptLocale);
          localeToResources[scriptLocale] ??= <String, String>{};
          localeToResourceAttributes[scriptLocale] ??= <String, dynamic>{};
          populateResources(scriptLocale, arbFile);
        }
      }
    }
  }
}

void exitWithError(String errorMessage) {
  stderr.writeln('fatal: $errorMessage');
  exit(1);
}

void checkCwdIsRepoRoot(String commandName) {
  final bool isRepoRoot = Directory('.git').existsSync() || File('.git').existsSync();

  if (!isRepoRoot) {
    exitWithError(
      '$commandName must be run from the root of the flutter/packages '
      'repository. The current working directory is: '
      '${Directory.current.path}',
    );
  }
}

GeneratorOptions parseArgs(List<String> rawArgs) {
  final argParser = argslib.ArgParser()
    ..addFlag('help', abbr: 'h', help: 'Print the usage message for this command')
    ..addFlag('overwrite', abbr: 'w', help: 'Overwrite existing localizations')
    ..addFlag(
      'remove-undefined',
      help: 'Remove any localizations that are not defined in the canonical locale.',
    )
    ..addFlag(
      'widgets',
      help:
          'Whether to print the generated classes for the Widgets package only. Ignored when --overwrite is passed.',
    )
    ..addFlag(
      'material',
      help:
          'Whether to print the generated classes for the Material package only. Ignored when --overwrite is passed.',
    )
    ..addFlag(
      'cupertino',
      help:
          'Whether to print the generated classes for the Cupertino package only. Ignored when --overwrite is passed.',
    );
  final argslib.ArgResults args = argParser.parse(rawArgs);
  if (args.wasParsed('help') && args['help'] == true) {
    stderr.writeln(argParser.usage);
    exit(0);
  }
  final writeToFile = args['overwrite'] as bool;
  final removeUndefined = args['remove-undefined'] as bool;
  final widgetsOnly = args['widgets'] as bool;
  final materialOnly = args['material'] as bool;
  final cupertinoOnly = args['cupertino'] as bool;

  return GeneratorOptions(
    writeToFile: writeToFile,
    materialOnly: materialOnly,
    cupertinoOnly: cupertinoOnly,
    widgetsOnly: widgetsOnly,
    removeUndefined: removeUndefined,
  );
}

class GeneratorOptions {
  GeneratorOptions({
    required this.writeToFile,
    required this.removeUndefined,
    required this.materialOnly,
    required this.cupertinoOnly,
    required this.widgetsOnly,
  });

  final bool writeToFile;
  final bool removeUndefined;
  final bool materialOnly;
  final bool cupertinoOnly;
  final bool widgetsOnly;
}

// See also //master/tools/gen_locale.dart in the engine repo.
Map<String, List<String>> _parseSection(String section) {
  final result = <String, List<String>>{};
  late List<String> lastHeading;
  for (final String line in section.split('\n')) {
    if (line == '') {
      continue;
    }
    if (line.startsWith('  ')) {
      lastHeading[lastHeading.length - 1] = '${lastHeading.last}${line.substring(1)}';
      continue;
    }
    final int colon = line.indexOf(':');
    if (colon <= 0) {
      throw ArgumentError('not sure how to deal with "$line"');
    }
    final String name = line.substring(0, colon);
    final String value = line.substring(colon + 2);
    lastHeading = result.putIfAbsent(name, () => <String>[]);
    result[name]!.add(value);
  }
  return result;
}

final Map<String, String> _languages = <String, String>{};
final Map<String, String> _regions = <String, String>{};
final Map<String, String> _scripts = <String, String>{};
const String kProvincePrefix = ', Province of ';
const String kParentheticalPrefix = ' (';

/// Prepares the data for the [describeLocale] method below.
///
/// The data is obtained from the official IANA registry.
void precacheLanguageAndRegionTags() {
  final List<Map<String, List<String>>> sections = languageSubtagRegistry
      .split('%%')
      .skip(1)
      .map<Map<String, List<String>>>(_parseSection)
      .toList();
  for (final section in sections) {
    assert(section.containsKey('Type'), section.toString());
    final String type = section['Type']!.single;
    if (type == 'language' || type == 'region' || type == 'script') {
      assert(
        section.containsKey('Subtag') && section.containsKey('Description'),
        section.toString(),
      );
      final String subtag = section['Subtag']!.single;
      String description = section['Description']!.join(' ');
      if (description.startsWith('United ')) {
        description = 'the $description';
      }
      if (description.contains(kParentheticalPrefix)) {
        description = description.substring(0, description.indexOf(kParentheticalPrefix));
      }
      if (description.contains(kProvincePrefix)) {
        description = description.substring(0, description.indexOf(kProvincePrefix));
      }
      if (description.endsWith(' Republic')) {
        description = 'the $description';
      }
      switch (type) {
        case 'language':
          _languages[subtag] = description;
        case 'region':
          _regions[subtag] = description;
        case 'script':
          _scripts[subtag] = description;
      }
    }
  }
}

String describeLocale(String tag) {
  final List<String> subtags = tag.split('_');
  assert(subtags.isNotEmpty);
  assert(_languages.containsKey(subtags[0]));
  final String language = _languages[subtags[0]]!;
  var output = language;
  String? region;
  String? script;
  if (subtags.length == 2) {
    region = _regions[subtags[1]];
    script = _scripts[subtags[1]];
    assert(region != null || script != null);
  } else if (subtags.length >= 3) {
    region = _regions[subtags[2]];
    script = _scripts[subtags[1]];
    assert(region != null && script != null);
  }
  if (region != null) {
    output += ', as used in $region';
  }
  if (script != null) {
    output += ', using the $script script';
  }
  return output;
}

/// Writes the header of each class which corresponds to a locale.
String generateClassDeclaration(LocaleInfo locale, String classNamePrefix, String superClass) {
  final String camelCaseName = locale.camelCase();
  return '''

/// The translations for ${describeLocale(locale.originalString)} (`${locale.originalString}`).
class $classNamePrefix$camelCaseName extends $superClass {''';
}

/// Return the input string as a Dart-parseable string.
///
/// ```none
/// foo => 'foo'
/// foo "bar" => 'foo "bar"'
/// foo 'bar' => "foo 'bar'"
/// foo 'bar' "baz" => '''foo 'bar' "baz"'''
/// ```
///
/// This function is used by tools that take in a JSON-formatted file to
/// generate Dart code. For this reason, characters with special meaning
/// in JSON files are escaped. For example, the backspace character (\b)
/// has to be properly escaped by this function so that the generated
/// Dart code correctly represents this character:
/// ```none
/// foo\bar => 'foo\\bar'
/// foo\nbar => 'foo\\nbar'
/// foo\\nbar => 'foo\\\\nbar'
/// foo\\bar => 'foo\\\\bar'
/// foo\ bar => 'foo\\ bar'
/// foo$bar = 'foo\$bar'
/// ```
String generateString(String value) {
  if (<String>['\n', '\f', '\t', '\r', '\b'].every((String pattern) => !value.contains(pattern))) {
    final bool hasDollar = value.contains(r'$');
    final bool hasBackslash = value.contains(r'\');
    final bool hasQuote = value.contains("'");
    final bool hasDoubleQuote = value.contains('"');
    if (!hasQuote) {
      return hasBackslash || hasDollar ? "r'$value'" : "'$value'";
    }
    if (!hasDoubleQuote) {
      return hasBackslash || hasDollar ? 'r"$value"' : '"$value"';
    }
  }

  const backslash = '__BACKSLASH__';
  assert(
    !value.contains(backslash),
    'Input string cannot contain the sequence: '
    '"__BACKSLASH__", as it is used as part of '
    'backslash character processing.',
  );

  value = value
      // Replace backslashes with a placeholder for now to properly parse
      // other special characters.
      .replaceAll(r'\', backslash)
      .replaceAll(r'$', r'\$')
      .replaceAll("'", r"\'")
      .replaceAll('"', r'\"')
      .replaceAll('\n', r'\n')
      .replaceAll('\f', r'\f')
      .replaceAll('\t', r'\t')
      .replaceAll('\r', r'\r')
      .replaceAll('\b', r'\b')
      // Reintroduce escaped backslashes into generated Dart string.
      .replaceAll(backslash, r'\\');

  return "'$value'";
}

/// Only used to generate localization strings for the Kannada locale ('kn') because
/// some of the localized strings contain characters that can crash Emacs on Linux.
/// See packages/flutter_localizations/lib/src/l10n/README in the Flutter SDK
/// for more information.
String generateEncodedString(String? locale, String value) {
  if (locale != 'kn' || value.runes.every((int code) => code <= 0xFF)) {
    return generateString(value);
  }

  final String unicodeEscapes = value.runes
      .map((int code) => '\\u{${code.toRadixString(16)}}')
      .join();
  return "'$unicodeEscapes'";
}
