// 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 ?? const <String, String>{};

  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));
    final Map<String, String>? files = content == null
        ? null
        : castStringKeyedMap(content['files'])?.cast<String, String>();
    return Fingerprint._(
      checksums: files ?? <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
  int get hashCode => Object.hash(Object.hashAllUnordered(_checksums.keys), Object.hashAllUnordered(_checksums.values));

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