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

// Regenerates a Dart file with a class containing IconData constants.
// See https://github.com/flutter/flutter/blob/main/docs/libraries/material/Updating-Material-Design-Fonts-%26-Icons.md
// Should be idempotent with:
// dart dev/tools/update_icons.dart --new-codepoints bin/cache/artifacts/material_fonts/codepoints

import 'dart:collection';
import 'dart:convert' show LineSplitter;
import 'dart:io';

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

const String _iconsPathOption = 'icons';
const String _iconsTemplatePathOption = 'icons-template';
const String _newCodepointsPathOption = 'new-codepoints';
const String _oldCodepointsPathOption = 'old-codepoints';
const String _fontFamilyOption = 'font-family';
const String _possibleStyleSuffixesOption = 'style-suffixes';
const String _classNameOption = 'class-name';
const String _enforceSafetyChecks = 'enforce-safety-checks';
const String _dryRunOption = 'dry-run';

const String _defaultIconsPath = 'packages/flutter/lib/src/material/icons.dart';
const String _defaultNewCodepointsPath = 'codepoints';
const String _defaultOldCodepointsPath = 'bin/cache/artifacts/material_fonts/codepoints';
const String _defaultFontFamily = 'MaterialIcons';
const List<String> _defaultPossibleStyleSuffixes = <String>['_outlined', '_rounded', '_sharp'];
const String _defaultClassName = 'Icons';
const String _defaultDemoFilePath = '/tmp/new_icons_demo.dart';

const String _beginGeneratedMark = '// BEGIN GENERATED ICONS';
const String _endGeneratedMark = '// END GENERATED ICONS';
const String _beginPlatformAdaptiveGeneratedMark = '// BEGIN GENERATED PLATFORM ADAPTIVE ICONS';
const String _endPlatformAdaptiveGeneratedMark = '// END GENERATED PLATFORM ADAPTIVE ICONS';

const Map<String, List<String>> _platformAdaptiveIdentifiers = <String, List<String>>{
  // Mapping of Flutter IDs to an Android/agnostic ID and an iOS ID.
  // Flutter IDs can be anything, but should be chosen to be agnostic.
  'arrow_back': <String>['arrow_back', 'arrow_back_ios'],
  'arrow_forward': <String>['arrow_forward', 'arrow_forward_ios'],
  'flip_camera': <String>['flip_camera_android', 'flip_camera_ios'],
  'more': <String>['more_vert', 'more_horiz'],
  'share': <String>['share', 'ios_share'],
};

// Rewrite certain Flutter IDs (numbers) using prefix matching.
const Map<String, String> _identifierPrefixRewrites = <String, String>{
  '1': 'one_',
  '2': 'two_',
  '3': 'three_',
  '4': 'four_',
  '5': 'five_',
  '6': 'six_',
  '7': 'seven_',
  '8': 'eight_',
  '9': 'nine_',
  '10': 'ten_',
  '11': 'eleven_',
  '12': 'twelve_',
  '13': 'thirteen_',
  '14': 'fourteen_',
  '15': 'fifteen_',
  '16': 'sixteen_',
  '17': 'seventeen_',
  '18': 'eighteen_',
  '19': 'nineteen_',
  '20': 'twenty_',
  '21': 'twenty_one_',
  '22': 'twenty_two_',
  '23': 'twenty_three_',
  '24': 'twenty_four_',
  '30': 'thirty_',
  '60': 'sixty_',
  '123': 'onetwothree',
  '360': 'threesixty',
  '2d': 'twod',
  '3d': 'threed',
  '3d_rotation': 'threed_rotation',
};

// Rewrite certain Flutter IDs (reserved keywords) using exact matching.
const Map<String, String> _identifierExactRewrites = <String, String>{
  'class': 'class_',
  'new': 'new_',
  'switch': 'switch_',
  'try': 'try_sms_star',
  'door_back': 'door_back_door',
  'door_front': 'door_front_door',
};

const Set<String> _iconsMirroredWhenRTL = <String>{
  // This list is obtained from:
  // https://developers.google.com/fonts/docs/material_icons#which_icons_should_be_mirrored_for_rtl
  'arrow_back',
  'arrow_back_ios',
  'arrow_forward',
  'arrow_forward_ios',
  'arrow_left',
  'arrow_right',
  'assignment',
  'assignment_return',
  'backspace',
  'battery_unknown',
  'call_made',
  'call_merge',
  'call_missed',
  'call_missed_outgoing',
  'call_received',
  'call_split',
  'chevron_left',
  'chevron_right',
  'chrome_reader_mode',
  'device_unknown',
  'dvr',
  'event_note',
  'featured_play_list',
  'featured_video',
  'first_page',
  'flight_land',
  'flight_takeoff',
  'format_indent_decrease',
  'format_indent_increase',
  'format_list_bulleted',
  'forward',
  'functions',
  'help',
  'help_outline',
  'input',
  'keyboard_backspace',
  'keyboard_tab',
  'label',
  'label_important',
  'label_outline',
  'last_page',
  'launch',
  'list',
  'live_help',
  'mobile_screen_share',
  'multiline_chart',
  'navigate_before',
  'navigate_next',
  'next_week',
  'note',
  'open_in',
  'playlist_add',
  'queue_music',
  'redo',
  'reply',
  'reply_all',
  'screen_share',
  'send',
  'short_text',
  'show_chart',
  'sort',
  'star_half',
  'subject',
  'trending_flat',
  'toc',
  'trending_down',
  'trending_up',
  'undo',
  'view_list',
  'view_quilt',
  'wrap_text',
};

void main(List<String> args) {
  // If we're run from the `tools` dir, set the cwd to the repo root.
  if (path.basename(Directory.current.path) == 'tools') {
    Directory.current = Directory.current.parent.parent;
  }

  final ArgResults argResults = _handleArguments(args);

  final File iconsFile = File(
    path.normalize(path.absolute(argResults[_iconsPathOption] as String)),
  );
  if (!iconsFile.existsSync()) {
    stderr.writeln('Error: Icons file not found: ${iconsFile.path}');
    exit(1);
  }
  final File iconsTemplateFile = File(
    path.normalize(path.absolute(argResults[_iconsTemplatePathOption] as String)),
  );
  if (!iconsTemplateFile.existsSync()) {
    stderr.writeln('Error: Icons template file not found: ${iconsTemplateFile.path}');
    exit(1);
  }
  final File newCodepointsFile = File(argResults[_newCodepointsPathOption] as String);
  if (!newCodepointsFile.existsSync()) {
    stderr.writeln('Error: New codepoints file not found: ${newCodepointsFile.path}');
    exit(1);
  }
  final File oldCodepointsFile = File(argResults[_oldCodepointsPathOption] as String);
  if (!oldCodepointsFile.existsSync()) {
    stderr.writeln('Error: Old codepoints file not found: ${oldCodepointsFile.path}');
    exit(1);
  }

  final String newCodepointsString = newCodepointsFile.readAsStringSync();
  final Map<String, String> newTokenPairMap = stringToTokenPairMap(newCodepointsString);

  final String oldCodepointsString = oldCodepointsFile.readAsStringSync();
  final Map<String, String> oldTokenPairMap = stringToTokenPairMap(oldCodepointsString);

  stderr.writeln('Performing safety checks');
  final bool isSuperset = testIsSuperset(newTokenPairMap, oldTokenPairMap);
  final bool isStable = testIsStable(newTokenPairMap, oldTokenPairMap);
  if ((!isSuperset || !isStable) && argResults[_enforceSafetyChecks] as bool) {
    exit(1);
  }
  final String iconsTemplateContents = iconsTemplateFile.readAsStringSync();

  stderr.writeln(
    "Generating icons ${argResults[_dryRunOption] as bool ? '' : 'to ${iconsFile.path}'}",
  );
  final String newIconsContents = _regenerateIconsFile(
    iconsTemplateContents,
    newTokenPairMap,
    argResults[_fontFamilyOption] as String,
    argResults[_classNameOption] as String,
    argResults[_enforceSafetyChecks] as bool,
  );

  if (argResults[_dryRunOption] as bool) {
    stdout.write(newIconsContents);
  } else {
    iconsFile.writeAsStringSync(newIconsContents);

    final SplayTreeMap<String, String> sortedNewTokenPairMap = SplayTreeMap<String, String>.of(
      newTokenPairMap,
    );
    _regenerateCodepointsFile(oldCodepointsFile, sortedNewTokenPairMap);

    sortedNewTokenPairMap.removeWhere(
      (String key, String value) => oldTokenPairMap.containsKey(key),
    );
    _generateIconDemo(File(_defaultDemoFilePath), sortedNewTokenPairMap);
  }
}

ArgResults _handleArguments(List<String> args) {
  final ArgParser argParser = ArgParser()
    ..addOption(
      _iconsPathOption,
      defaultsTo: _defaultIconsPath,
      help: 'Location of the material icons file',
    )
    ..addOption(
      _iconsTemplatePathOption,
      defaultsTo: _defaultIconsPath,
      help: 'Location of the material icons file template. Usually the same as --$_iconsPathOption',
    )
    ..addOption(
      _newCodepointsPathOption,
      defaultsTo: _defaultNewCodepointsPath,
      help: 'Location of the new codepoints directory',
    )
    ..addOption(
      _oldCodepointsPathOption,
      defaultsTo: _defaultOldCodepointsPath,
      help: 'Location of the existing codepoints directory',
    )
    ..addOption(
      _fontFamilyOption,
      defaultsTo: _defaultFontFamily,
      help: 'The font family to use for the IconData constants',
    )
    ..addMultiOption(
      _possibleStyleSuffixesOption,
      defaultsTo: _defaultPossibleStyleSuffixes,
      help:
          'A comma-separated list of suffixes (typically an optional '
          'family + a style) e.g. _outlined, _monoline_filled',
    )
    ..addOption(
      _classNameOption,
      defaultsTo: _defaultClassName,
      help: 'The containing class for all icons',
    )
    ..addFlag(
      _enforceSafetyChecks,
      defaultsTo: true,
      help: 'Whether to exit if safety checks fail (e.g. codepoints are missing or unstable',
    )
    ..addFlag(_dryRunOption);
  argParser.addFlag(
    'help',
    abbr: 'h',
    negatable: false,
    callback: (bool help) {
      if (help) {
        print(argParser.usage);
        exit(1);
      }
    },
  );
  return argParser.parse(args);
}

Map<String, String> stringToTokenPairMap(String codepointData) {
  final Iterable<String> cleanData = LineSplitter.split(
    codepointData,
  ).map((String line) => line.trim()).where((String line) => line.isNotEmpty);

  final Map<String, String> pairs = <String, String>{};

  for (final String line in cleanData) {
    final List<String> tokens = line.split(' ');
    if (tokens.length != 2) {
      throw FormatException('Unexpected codepoint data: $line');
    }
    pairs.putIfAbsent(tokens[0], () => tokens[1]);
  }

  return pairs;
}

String _regenerateIconsFile(
  String templateFileContents,
  Map<String, String> tokenPairMap,
  String fontFamily,
  String className,
  bool enforceSafetyChecks,
) {
  final List<Icon> newIcons = tokenPairMap.entries
      .map(
        (MapEntry<String, String> entry) =>
            Icon(entry, fontFamily: fontFamily, className: className),
      )
      .toList();
  newIcons.sort((Icon a, Icon b) => a._compareTo(b));

  final StringBuffer buf = StringBuffer();
  bool generating = false;

  for (final String line in LineSplitter.split(templateFileContents)) {
    if (!generating) {
      buf.writeln(line);
    }

    // Generate for PlatformAdaptiveIcons
    if (line.contains(_beginPlatformAdaptiveGeneratedMark)) {
      generating = true;
      final List<String> platformAdaptiveDeclarations = <String>[];
      _platformAdaptiveIdentifiers.forEach((String flutterId, List<String> ids) {
        // Automatically finds and generates all icon declarations.
        for (final String style in <String>['', '_outlined', '_rounded', '_sharp']) {
          try {
            final Icon agnosticIcon = newIcons.firstWhere(
              (Icon icon) => icon.id == '${ids[0]}$style',
              orElse: () => throw ids[0],
            );
            final Icon iOSIcon = newIcons.firstWhere(
              (Icon icon) => icon.id == '${ids[1]}$style',
              orElse: () => throw ids[1],
            );
            platformAdaptiveDeclarations.add(
              agnosticIcon.platformAdaptiveDeclaration('$flutterId$style', iOSIcon),
            );
          } catch (e) {
            if (style == '') {
              // Throw an error for baseline icons.
              stderr.writeln("❌ Platform adaptive icon '$e' not found.");
              if (enforceSafetyChecks) {
                stderr.writeln('Safety checks failed');
                exit(1);
              }
            } else {
              // Ignore errors for styled icons since some don't exist.
            }
          }
        }
      });
      buf.write(platformAdaptiveDeclarations.join());
    } else if (line.contains(_endPlatformAdaptiveGeneratedMark)) {
      generating = false;
      buf.writeln(line);
    }

    // Generate for Icons
    if (line.contains(_beginGeneratedMark)) {
      generating = true;
      final String iconDeclarationsString = newIcons
          .map((Icon icon) => icon.fullDeclaration)
          .join();
      buf.write(iconDeclarationsString);
    } else if (line.contains(_endGeneratedMark)) {
      generating = false;
      buf.writeln(line);
    }
  }
  return buf.toString();
}

@visibleForTesting
bool testIsSuperset(Map<String, String> newCodepoints, Map<String, String> oldCodepoints) {
  final Set<String> newCodepointsSet = newCodepoints.keys.toSet();
  final Set<String> oldCodepointsSet = oldCodepoints.keys.toSet();

  final int diff = newCodepointsSet.length - oldCodepointsSet.length;
  if (diff > 0) {
    stderr.writeln('🆕 $diff new codepoints: ${newCodepointsSet.difference(oldCodepointsSet)}');
  }
  if (!newCodepointsSet.containsAll(oldCodepointsSet)) {
    stderr.writeln(
      '❌ new codepoints file does not contain all ${oldCodepointsSet.length} '
      'existing codepoints. Missing: ${oldCodepointsSet.difference(newCodepointsSet)}',
    );
    return false;
  } else {
    stderr.writeln(
      '✅ new codepoints file contains all ${oldCodepointsSet.length} existing codepoints',
    );
  }
  return true;
}

@visibleForTesting
bool testIsStable(Map<String, String> newCodepoints, Map<String, String> oldCodepoints) {
  final int oldCodepointsCount = oldCodepoints.length;
  final List<String> unstable = <String>[
    for (final MapEntry<String, String>(:String key, :String value) in oldCodepoints.entries)
      if (newCodepoints.containsKey(key) && value != newCodepoints[key]) key,
  ];

  if (unstable.isNotEmpty) {
    stderr.writeln(
      '❌ out of $oldCodepointsCount existing codepoints, ${unstable.length} were unstable: $unstable',
    );
    return false;
  } else {
    stderr.writeln('✅ all existing $oldCodepointsCount codepoints are stable');
    return true;
  }
}

void _regenerateCodepointsFile(File oldCodepointsFile, Map<String, String> tokenPairMap) {
  stderr.writeln('Regenerating old codepoints file ${oldCodepointsFile.path}');

  final StringBuffer buf = StringBuffer();
  tokenPairMap.forEach((String key, String value) => buf.writeln('$key $value'));
  oldCodepointsFile.writeAsStringSync(buf.toString());
}

void _generateIconDemo(File demoFilePath, Map<String, String> tokenPairMap) {
  if (tokenPairMap.isEmpty) {
    stderr.writeln('No new icons, skipping generating icon demo');
    return;
  }
  stderr.writeln('Generating icon demo at $_defaultDemoFilePath');

  final StringBuffer newIconUsages = StringBuffer();
  for (final MapEntry<String, String> entry in tokenPairMap.entries) {
    newIconUsages.writeln(Icon(entry).usage);
  }
  final String demoFileContents =
      '''
    import 'package:flutter/material.dart';

    void main() => runApp(const IconDemo());

    class IconDemo extends StatelessWidget {
      const IconDemo({ Key? key }) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            body: Wrap(
              children: const [
                $newIconUsages
              ],
            ),
          ),
        );
      }
    }
    ''';
  demoFilePath.writeAsStringSync(demoFileContents);
}

class Icon {
  // Parse tokenPair (e.g. {"6_ft_apart_outlined": "e004"}).
  Icon(
    MapEntry<String, String> tokenPair, {
    this.fontFamily = _defaultFontFamily,
    this.possibleStyleSuffixes = _defaultPossibleStyleSuffixes,
    this.className = _defaultClassName,
  }) {
    id = tokenPair.key;
    hexCodepoint = tokenPair.value;

    // Determine family and HTML class suffix for Dartdoc.
    if (id.endsWith('_gm_outlined')) {
      dartdocFamily = 'GM';
      dartdocHtmlSuffix = '-outlined';
    } else if (id.endsWith('_gm_filled')) {
      dartdocFamily = 'GM';
      dartdocHtmlSuffix = '-filled';
    } else if (id.endsWith('_monoline_outlined')) {
      dartdocFamily = 'Monoline';
      dartdocHtmlSuffix = '-outlined';
    } else if (id.endsWith('_monoline_filled')) {
      dartdocFamily = 'Monoline';
      dartdocHtmlSuffix = '-filled';
    } else {
      dartdocFamily = 'material';
      if (id.endsWith('_baseline')) {
        id = _removeLast(id, '_baseline');
        dartdocHtmlSuffix = '';
      } else if (id.endsWith('_outlined')) {
        dartdocHtmlSuffix = '-outlined';
      } else if (id.endsWith('_rounded')) {
        dartdocHtmlSuffix = '-round';
      } else if (id.endsWith('_sharp')) {
        dartdocHtmlSuffix = '-sharp';
      }
    }

    _generateShortId();
    _generateFlutterId();
  }

  late String id; // e.g. 5g, 5g_outlined, 5g_rounded, 5g_sharp
  late String shortId; // e.g. 5g
  late String flutterId; // e.g. five_g, five_g_outlined, five_g_rounded, five_g_sharp
  late String hexCodepoint; // e.g. e547
  late String dartdocFamily; // e.g. material
  late String dartdocHtmlSuffix = ''; // The suffix for the 'material-icons' HTML class.
  String fontFamily; // The IconData font family.
  List<String>
  possibleStyleSuffixes; // A list of possible suffixes e.g. _outlined, _monoline_filled.
  String className; // The containing class.

  String get name => shortId.replaceAll('_', ' ').trim();

  String get style =>
      dartdocHtmlSuffix == '' ? '' : ' (${dartdocHtmlSuffix.replaceFirst('-', '')})';

  String get dartDoc =>
      '<i class="material-icons$dartdocHtmlSuffix md-36">$shortId</i> &#x2014; $dartdocFamily icon named "$name"$style';

  String get usage => 'Icon($className.$flutterId),';

  bool get isMirroredInRTL {
    // Remove common suffixes (e.g. "_new" or "_alt") from the shortId.
    final String normalizedShortId = shortId.replaceAll(RegExp(r'_(new|alt|off|on)$'), '');
    return _iconsMirroredWhenRTL.any(
      (String shortIdMirroredWhenRTL) => normalizedShortId == shortIdMirroredWhenRTL,
    );
  }

  String get declaration =>
      "static const IconData $flutterId = IconData(0x$hexCodepoint, fontFamily: '$fontFamily'${isMirroredInRTL ? ', matchTextDirection: true' : ''});";

  String get fullDeclaration =>
      '''

  /// $dartDoc.
  $declaration
''';

  String platformAdaptiveDeclaration(String fullFlutterId, Icon iOSIcon) =>
      '''

  /// Platform-adaptive icon for $dartDoc and ${iOSIcon.dartDoc}.;
  IconData get $fullFlutterId => !_isCupertino() ? $className.$flutterId : $className.${iOSIcon.flutterId};
''';

  @override
  String toString() => id;

  /// Analogous to [String.compareTo]
  int _compareTo(Icon b) {
    if (shortId == b.shortId) {
      // Sort a regular icon before its variants.
      return id.length - b.id.length;
    }
    return shortId.compareTo(b.shortId);
  }

  static String _removeLast(String string, String toReplace) {
    return string.replaceAll(RegExp('$toReplace\$'), '');
  }

  /// See [shortId].
  void _generateShortId() {
    shortId = id;
    for (final String styleSuffix in possibleStyleSuffixes) {
      shortId = _removeLast(shortId, styleSuffix);
      if (shortId != id) {
        break;
      }
    }
  }

  /// See [flutterId].
  void _generateFlutterId() {
    flutterId = id;
    // Exact identifier rewrites.
    for (final MapEntry<String, String> rewritePair in _identifierExactRewrites.entries) {
      if (shortId == rewritePair.key) {
        flutterId = id.replaceFirst(rewritePair.key, _identifierExactRewrites[rewritePair.key]!);
      }
    }
    // Prefix identifier rewrites.
    for (final MapEntry<String, String> rewritePair in _identifierPrefixRewrites.entries) {
      if (id.startsWith(rewritePair.key)) {
        flutterId = id.replaceFirst(rewritePair.key, _identifierPrefixRewrites[rewritePair.key]!);
      }
    }

    // Prevent double underscores.
    flutterId = flutterId.replaceAll('__', '_');
  }
}
