// 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 'package:crypto/crypto.dart' show md5;
import 'package:meta/meta.dart';

import '../convert.dart' show json;
import 'file_system.dart';
import 'logger.dart';
import 'utils.dart';

/// A tool that can be used to compute, compare, and write [Fingerprint]s for a
/// set of input files and associated build settings.
///
/// This class should only be used in situations where `assemble` is not appropriate,
/// such as checking if Cocoapods should be run.
class Fingerprinter {
  Fingerprinter({
    @required this.fingerprintPath,
    @required Iterable<String> paths,
    @required FileSystem fileSystem,
    @required Logger logger,
  }) : _paths = paths.toList(),
       assert(fingerprintPath != null),
       assert(paths != null && paths.every((String path) => path != null)),
       _logger = logger,
       _fileSystem = fileSystem;

  final String fingerprintPath;
  final List<String> _paths;
  final Logger _logger;
  final FileSystem _fileSystem;

  Fingerprint buildFingerprint() {
    final List<String> paths = _getPaths();
    return Fingerprint.fromBuildInputs(paths, _fileSystem);
  }

  bool doesFingerprintMatch() {
    try {
      final File fingerprintFile = _fileSystem.file(fingerprintPath);
      if (!fingerprintFile.existsSync()) {
        return false;
      }

      final List<String> paths = _getPaths();
      if (!paths.every(_fileSystem.isFileSync)) {
        return false;
      }

      final Fingerprint oldFingerprint = Fingerprint.fromJson(fingerprintFile.readAsStringSync());
      final Fingerprint newFingerprint = buildFingerprint();
      return oldFingerprint == newFingerprint;
    } on Exception catch (e) {
      // Log exception and continue, fingerprinting is only a performance improvement.
      _logger.printTrace('Fingerprint check error: $e');
    }
    return false;
  }

  void writeFingerprint() {
    try {
      final Fingerprint fingerprint = buildFingerprint();
      _fileSystem.file(fingerprintPath).writeAsStringSync(fingerprint.toJson());
    } on Exception catch (e) {
      // Log exception and continue, fingerprinting is only a performance improvement.
      _logger.printTrace('Fingerprint write error: $e');
    }
  }

  List<String> _getPaths() => _paths;
}

/// A fingerprint that uniquely identifies a set of build input files and
/// properties.
///
/// See [Fingerprinter].
@immutable
class Fingerprint {
  const Fingerprint._({
    Map<String, String> checksums,
  })  : _checksums = checksums;

  factory Fingerprint.fromBuildInputs(Iterable<String> inputPaths, FileSystem fileSystem) {
    final Iterable<File> files = inputPaths.map<File>(fileSystem.file);
    final Iterable<File> missingInputs = files.where((File file) => !file.existsSync());
    if (missingInputs.isNotEmpty) {
      throw Exception('Missing input files:\n' + missingInputs.join('\n'));
    }
    return Fingerprint._(
      checksums: <String, String>{
        for (final File file in files)
          file.path: md5.convert(file.readAsBytesSync()).toString(),
      },
    );
  }

  /// Creates a Fingerprint from serialized JSON.
  ///
  /// Throws [Exception], if there is a version mismatch between the
  /// serializing framework and this framework.
  factory Fingerprint.fromJson(String jsonData) {
    final Map<String, dynamic> content = castStringKeyedMap(json.decode(jsonData));
    return Fingerprint._(
      checksums: castStringKeyedMap(content['files'])?.cast<String,String>() ?? <String, String>{},
    );
  }

  final Map<String, String> _checksums;

  String toJson() => json.encode(<String, dynamic>{
    'files': _checksums,
  });

  @override
  bool operator==(Object other) {
    return other is Fingerprint
        && _equalMaps(other._checksums, _checksums);
  }

  bool _equalMaps(Map<String, String> a, Map<String, String> b) {
    return a.length == b.length
        && a.keys.every((String key) => a[key] == b[key]);
  }

  @override
  // Ignore map entries here to avoid becoming inconsistent with equals
  // due to differences in map entry order. This is a really bad hash
  // function and should eventually be deprecated and removed.
  int get hashCode => _checksums.length.hashCode;

  @override
  String toString() => '{checksums: $_checksums}';
}
