// 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.

// The utility function `encodeKnArbFiles` replaces the material_kn.arb
// and cupertino_kn.arb files in flutter_localizations/packages/lib/src/l10n
// with versions where the contents of the localized strings have been
// replaced by JSON escapes. This is done because some of those strings
// contain characters that can crash Emacs on Linux. There is more information
// here: https://github.com/flutter/flutter/issues/36704 and in the README
// in flutter_localizations/packages/lib/src/l10n.
//
// This utility is run by `gen_localizations.dart` if --overwrite is passed
// in as an option.

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

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

import '../localizations_utils.dart';

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 _encodeBundleTranslations(Map<String, dynamic> bundle) {
  for (final String key in bundle.keys) {
    // The ARB file resource "attributes" for foo are called @foo. Don't need
    // to encode them.
    if (key.startsWith('@'))
      continue;
    final String translation = bundle[key] as String;
    // Rewrite the string as a series of unicode characters in JSON format.
    // Like "\u0012\u0123\u1234".
    bundle[key] = translation.runes.map((int code) {
      final String codeString = '00${code.toRadixString(16)}';
      return '\\u${codeString.substring(codeString.length - 4)}';
    }).join();
  }
}

void _checkEncodedTranslations(Map<String, dynamic> encodedBundle, Map<String, dynamic> bundle) {
  bool errorFound = false;
  const JsonDecoder decoder = JsonDecoder();
  for (final String key in bundle.keys) {
    if (decoder.convert('"${encodedBundle[key]}"') != bundle[key]) {
      stderr.writeln('  encodedTranslation for $key does not match original value "${bundle[key]}"');
      errorFound = true;
    }
  }
  if (errorFound)
    exitWithError('JSON unicode translation encoding failed');
}

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

void encodeKnArbFiles(Directory directory) {
  final File materialArbFile = File(path.join(directory.path, 'material_kn.arb'));
  final File cupertinoArbFile = File(path.join(directory.path, 'cupertino_kn.arb'));

  final Map<String, dynamic> materialBundle = _loadBundle(materialArbFile);
  final Map<String, dynamic> cupertinoBundle = _loadBundle(cupertinoArbFile);

  _encodeBundleTranslations(materialBundle);
  _encodeBundleTranslations(cupertinoBundle);

  _checkEncodedTranslations(materialBundle, _loadBundle(materialArbFile));
  _checkEncodedTranslations(cupertinoBundle, _loadBundle(cupertinoArbFile));

  _rewriteBundle(materialArbFile, materialBundle);
  _rewriteBundle(cupertinoArbFile, cupertinoBundle);
}
