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

// @dart = 2.8

import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:mime/mime.dart' as mime;

import '../../artifacts.dart';
import '../../base/common.dart';
import '../../base/file_system.dart';
import '../../base/io.dart';
import '../../base/logger.dart';
import '../../convert.dart';
import '../../devfs.dart';
import '../build_system.dart';
import 'common.dart';

/// The build define controlling whether icon fonts should be stripped down to
/// only the glyphs used by the application.
const String kIconTreeShakerFlag = 'TreeShakeIcons';

/// Whether icon font subsetting is enabled by default.
const bool kIconTreeShakerEnabledDefault = true;

List<Map<String, dynamic>> _getList(dynamic object, String errorMessage) {
  if (object is List<dynamic>) {
    return object.cast<Map<String, dynamic>>();
  }
  throw IconTreeShakerException._(errorMessage);
}

/// A class that wraps the functionality of the const finder package and the
/// font subset utility to tree shake unused icons from fonts.
class IconTreeShaker {
  /// Creates a wrapper for icon font subsetting.
  ///
  /// The environment parameter must not be null.
  ///
  /// If the `fontManifest` parameter is null, [enabled] will return false since
  /// there are no fonts to shake.
  ///
  /// The constructor will validate the environment and print a warning if
  /// font subsetting has been requested in a debug build mode.
  IconTreeShaker(
    this._environment,
    DevFSStringContent fontManifest, {
    @required ProcessManager processManager,
    @required Logger logger,
    @required FileSystem fileSystem,
    @required Artifacts artifacts,
  }) : assert(_environment != null),
       assert(processManager != null),
       assert(logger != null),
       assert(fileSystem != null),
       assert(artifacts != null),
       _processManager = processManager,
       _logger = logger,
       _fs = fileSystem,
       _artifacts = artifacts,
       _fontManifest = fontManifest?.string {
    if (_environment.defines[kIconTreeShakerFlag] == 'true' &&
        _environment.defines[kBuildMode] == 'debug') {
      logger.printError('Font subsetting is not supported in debug mode. The '
                         '--tree-shake-icons flag will be ignored.');
    }
  }

  /// The MIME types for supported font sets.
  static const Set<String> kTtfMimeTypes = <String>{
    'font/ttf', // based on internet search
    'font/opentype',
    'font/otf',
    'application/x-font-opentype',
    'application/x-font-otf',
    'application/x-font-ttf', // based on running locally.
  };

  /// The [Source] inputs that targets using this should depend on.
  ///
  /// See [Target.inputs].
  static const List<Source> inputs = <Source>[
    Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/icon_tree_shaker.dart'),
    Source.artifact(Artifact.constFinder),
    Source.artifact(Artifact.fontSubset),
  ];

  final Environment _environment;
  final String _fontManifest;
  Future<void> _iconDataProcessing;
  Map<String, _IconTreeShakerData> _iconData;

  final ProcessManager _processManager;
  final Logger _logger;
  final FileSystem _fs;
  final Artifacts _artifacts;

  /// Whether font subsetting should be used for this [Environment].
  bool get enabled => _fontManifest != null
                   && _environment.defines[kIconTreeShakerFlag] == 'true'
                   && _environment.defines[kBuildMode] != 'debug';

  // Fills the [_iconData] map.
  Future<void> _getIconData(Environment environment) async {
    if (!enabled) {
      return;
    }

    final File appDill = environment.buildDir.childFile('app.dill');
    if (!appDill.existsSync()) {
      throw IconTreeShakerException._('Expected to find kernel file at ${appDill.path}, but no file found.');
    }
    final File constFinder = _fs.file(
      _artifacts.getArtifactPath(Artifact.constFinder),
    );
    final File dart = _fs.file(
      _artifacts.getArtifactPath(Artifact.engineDartBinary),
    );

    final Map<String, List<int>> iconData = await _findConstants(
      dart,
      constFinder,
      appDill,
    );
    final Set<String> familyKeys = iconData.keys.toSet();

    final Map<String, String> fonts = await _parseFontJson(
      _fontManifest,
      familyKeys,
    );

    if (fonts.length != iconData.length) {
      environment.logger.printStatus(
        'Expected to find fonts for ${iconData.keys}, but found '
        '${fonts.keys}. This usually means you are referring to '
        'font families in an IconData class but not including them '
        'in the assets section of your pubspec.yaml, are missing '
        'the package that would include them, or are missing '
        '"uses-material-design: true".',
      );
    }

    final Map<String, _IconTreeShakerData> result = <String, _IconTreeShakerData>{};
    for (final MapEntry<String, String> entry in fonts.entries) {
      result[entry.value] = _IconTreeShakerData(
        family: entry.key,
        relativePath: entry.value,
        codePoints: iconData[entry.key],
      );
    }
    _iconData = result;
  }

  /// Calls font-subset, which transforms the [input] font file to a
  /// subsetted version at [outputPath].
  ///
  /// All parameters are required.
  ///
  /// If [enabled] is false, or the relative path is not recognized as an icon
  /// font used in the Flutter application, this returns false.
  /// If the font-subset subprocess fails, it will [throwToolExit].
  /// Otherwise, it will return true.
  Future<bool> subsetFont({
    @required File input,
    @required String outputPath,
    @required String relativePath,
  }) async {
    if (!enabled) {
      return false;
    }
    if (input.lengthSync() < 12) {
      return false;
    }
    final String mimeType = mime.lookupMimeType(
      input.path,
      headerBytes: await input.openRead(0, 12).first,
    );
    if (!kTtfMimeTypes.contains(mimeType)) {
      return false;
    }
    await (_iconDataProcessing ??= _getIconData(_environment));
    assert(_iconData != null);

    final _IconTreeShakerData iconTreeShakerData = _iconData[relativePath];
    if (iconTreeShakerData == null) {
      return false;
    }

    final File fontSubset = _fs.file(
      _artifacts.getArtifactPath(Artifact.fontSubset),
    );
    if (!fontSubset.existsSync()) {
      throw IconTreeShakerException._('The font-subset utility is missing. Run "flutter doctor".');
    }

    final List<String> cmd = <String>[
      fontSubset.path,
      outputPath,
      input.path,
    ];
    final String codePoints = iconTreeShakerData.codePoints.join(' ');
    _logger.printTrace('Running font-subset: ${cmd.join(' ')}, '
                       'using codepoints $codePoints');
    final Process fontSubsetProcess = await _processManager.start(cmd);
    try {
      fontSubsetProcess.stdin.writeln(codePoints);
      await fontSubsetProcess.stdin.flush();
      await fontSubsetProcess.stdin.close();
    } on Exception {
      // handled by checking the exit code.
    }

    final int code = await fontSubsetProcess.exitCode;
    if (code != 0) {
      _logger.printTrace(await utf8.decodeStream(fontSubsetProcess.stdout));
      _logger.printError(await utf8.decodeStream(fontSubsetProcess.stderr));
      throw IconTreeShakerException._('Font subsetting failed with exit code $code.');
    }
    return true;
  }

  /// Returns a map of { fontFamily: relativePath } pairs.
  Future<Map<String, String>> _parseFontJson(
    String fontManifestData,
    Set<String> families,
  ) async {
    final Map<String, String> result = <String, String>{};
    final List<Map<String, dynamic>> fontList = _getList(
      json.decode(fontManifestData),
      'FontManifest.json invalid: expected top level to be a list of objects.',
    );

    for (final Map<String, dynamic> map in fontList) {
      if (map['family'] is! String) {
        throw IconTreeShakerException._(
          'FontManifest.json invalid: expected the family value to be a string, '
          'got: ${map['family']}.');
      }
      final String familyKey = map['family'] as String;
      if (!families.contains(familyKey)) {
        continue;
      }
      final List<Map<String, dynamic>> fonts = _getList(
        map['fonts'],
        'FontManifest.json invalid: expected "fonts" to be a list of objects.',
      );
      if (fonts.length != 1) {
        throw IconTreeShakerException._(
          'This tool cannot process icon fonts with multiple fonts in a '
          'single family.');
      }
      if (fonts.first['asset'] is! String) {
        throw IconTreeShakerException._(
          'FontManifest.json invalid: expected "asset" value to be a string, '
          'got: ${map['assets']}.');
      }
      result[familyKey] = fonts.first['asset'] as String;
    }
    return result;
  }

  Future<Map<String, List<int>>> _findConstants(
    File dart,
    File constFinder,
    File appDill,
  ) async {
    final List<String> cmd = <String>[
      dart.path,
      '--disable-dart-dev',
      constFinder.path,
      '--kernel-file', appDill.path,
      '--class-library-uri', 'package:flutter/src/widgets/icon_data.dart',
      '--class-name', 'IconData',
    ];
    _logger.printTrace('Running command: ${cmd.join(' ')}');
    final ProcessResult constFinderProcessResult = await _processManager.run(cmd);

    if (constFinderProcessResult.exitCode != 0) {
      throw IconTreeShakerException._('ConstFinder failure: ${constFinderProcessResult.stderr}');
    }
    final dynamic jsonDecode = json.decode(constFinderProcessResult.stdout as String);
    if (jsonDecode is! Map<String, dynamic>) {
      throw IconTreeShakerException._(
        'Invalid ConstFinder output: expected a top level JSON object, '
        'got $jsonDecode.');
    }
    final Map<String, dynamic> constFinderMap = jsonDecode as Map<String, dynamic>;
    final _ConstFinderResult constFinderResult = _ConstFinderResult(constFinderMap);
    if (constFinderResult.hasNonConstantLocations) {
      _logger.printError('This application cannot tree shake icons fonts. '
                         'It has non-constant instances of IconData at the '
                         'following locations:', emphasis: true);
      for (final Map<String, dynamic> location in constFinderResult.nonConstantLocations) {
        _logger.printError(
          '- ${location['file']}:${location['line']}:${location['column']}',
          indent: 2,
          hangingIndent: 4,
        );
      }
      throwToolExit('Avoid non-constant invocations of IconData or try to '
                    'build again with --no-tree-shake-icons.');
    }
    return _parseConstFinderResult(constFinderResult);
  }

  Map<String, List<int>> _parseConstFinderResult(_ConstFinderResult constants) {
    final Map<String, List<int>> result = <String, List<int>>{};
    for (final Map<String, dynamic> iconDataMap in constants.constantInstances) {
      if ((iconDataMap['fontPackage'] ?? '') is! String || // Null is ok here.
           iconDataMap['fontFamily'] is! String ||
           iconDataMap['codePoint'] is! num) {
        throw IconTreeShakerException._(
          'Invalid ConstFinder result. Expected "fontPackage" to be a String, '
          '"fontFamily" to be a String, and "codePoint" to be an int, '
          'got: $iconDataMap.');
      }
      final String package = iconDataMap['fontPackage'] as String;
      final String family = iconDataMap['fontFamily'] as String;
      final String key = package == null
        ? family
        : 'packages/$package/$family';
      result[key] ??= <int>[];
      result[key].add((iconDataMap['codePoint'] as num).round());
    }
    return result;
  }
}

class _ConstFinderResult {
  _ConstFinderResult(this.result);

  final Map<String, dynamic> result;

  List<Map<String, dynamic>> _constantInstances;
  List<Map<String, dynamic>> get constantInstances {
    _constantInstances ??= _getList(
      result['constantInstances'],
      'Invalid ConstFinder output: Expected "constInstances" to be a list of objects.',
    );
    return _constantInstances;
  }

  List<Map<String, dynamic>> _nonConstantLocations;
  List<Map<String, dynamic>> get nonConstantLocations {
    _nonConstantLocations ??= _getList(
      result['nonConstantLocations'],
      'Invalid ConstFinder output: Expected "nonConstLocations" to be a list of objects',
    );
    return _nonConstantLocations;
  }

  bool get hasNonConstantLocations => nonConstantLocations.isNotEmpty;
}

/// The font family name, relative path to font file, and list of code points
/// the application is using.
class _IconTreeShakerData {
  /// All parameters are required.
  const _IconTreeShakerData({
    @required this.family,
    @required this.relativePath,
    @required this.codePoints,
  }) : assert(family != null),
       assert(relativePath != null),
       assert(codePoints != null);

  /// The font family name, e.g. "MaterialIcons".
  final String family;

  /// The relative path to the font file.
  final String relativePath;

  /// The list of code points for the font.
  final List<int> codePoints;

  @override
  String toString() => 'FontSubsetData($family, $relativePath, $codePoints)';
}

class IconTreeShakerException implements Exception {
  IconTreeShakerException._(this.message);

  final String message;

  @override
  String toString() => 'IconTreeShakerException: $message\n\n'
    'To disable icon tree shaking, pass --no-tree-shake-icons to the requested '
    'flutter build command';
}
