// 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 'dart:convert' show json;

import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/fingerprint.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/utils.dart';

import '../../src/common.dart';

void main() {
  group('Fingerprinter', () {
    late MemoryFileSystem fileSystem;

    setUp(() {
      fileSystem = MemoryFileSystem.test();
    });

    testWithoutContext('creates fingerprint with specified properties and files', () {
      fileSystem.file('a.dart').createSync();

      final Fingerprinter fingerprinter = Fingerprinter(
        fingerprintPath: 'out.fingerprint',
        paths: <String>['a.dart'],
        fileSystem: fileSystem,
        logger: BufferLogger.test(),
      );
      final Fingerprint fingerprint = fingerprinter.buildFingerprint();
      expect(fingerprint, Fingerprint.fromBuildInputs(const <String>['a.dart'], fileSystem));
    });

    testWithoutContext('creates fingerprint with file checksums', () {
      fileSystem.file('a.dart').createSync();

      final Fingerprinter fingerprinter = Fingerprinter(
        fingerprintPath: 'out.fingerprint',
        paths: <String>['a.dart'],
        fileSystem: fileSystem,
        logger: BufferLogger.test(),
      );
      final Fingerprint fingerprint = fingerprinter.buildFingerprint();
      expect(fingerprint, Fingerprint.fromBuildInputs(const <String>['a.dart'], fileSystem));
    });

    testWithoutContext('fingerprint does not match if not present', () {
      fileSystem.file('a.dart').createSync();
      fileSystem.file('b.dart').createSync();

      final Fingerprinter fingerprinter = Fingerprinter(
        fingerprintPath: 'out.fingerprint',
        paths: <String>['a.dart', 'b.dart'],
        fileSystem: fileSystem,
        logger: BufferLogger.test(),
      );
      expect(fingerprinter.doesFingerprintMatch(), isFalse);
    });
    testWithoutContext('fingerprint does match if identical', () {
      fileSystem.file('a.dart').createSync();
      fileSystem.file('b.dart').createSync();

      final Fingerprinter fingerprinter = Fingerprinter(
        fingerprintPath: 'out.fingerprint',
        paths: <String>['a.dart', 'b.dart'],
        fileSystem: fileSystem,
        logger: BufferLogger.test(),
      );
      fingerprinter.writeFingerprint();
      expect(fingerprinter.doesFingerprintMatch(), isTrue);
    });

    testWithoutContext('fails to write fingerprint if inputs are missing', () {
      final Fingerprinter fingerprinter = Fingerprinter(
        fingerprintPath: 'out.fingerprint',
        paths: <String>['a.dart'],
        fileSystem: fileSystem,
        logger: BufferLogger.test(),
      );
      fingerprinter.writeFingerprint();
      expect(fileSystem.file('out.fingerprint').existsSync(), isFalse);
    });

  group('Fingerprint', () {
    group('fromBuildInputs', () {
      late MemoryFileSystem fileSystem;

      setUp(() {
        fileSystem = MemoryFileSystem.test();
      });

      testWithoutContext('throws if any input file does not exist', () {
        fileSystem.file('a.dart').createSync();
        expect(
          () => Fingerprint.fromBuildInputs(const <String>['a.dart', 'b.dart'], fileSystem),
          throwsException,
        );
      });

      testWithoutContext('populates checksums for valid files', () {
        fileSystem.file('a.dart').writeAsStringSync('This is a');
        fileSystem.file('b.dart').writeAsStringSync('This is b');
        final Fingerprint fingerprint = Fingerprint.fromBuildInputs(const <String>['a.dart', 'b.dart'], fileSystem);

        final Map<String, dynamic>? jsonObject = castStringKeyedMap(json.decode(fingerprint.toJson()));
        final Map<String, dynamic> files = jsonObject!['files'] as Map<String, dynamic>;
        expect(files, hasLength(2));
        expect(files['a.dart'], '8a21a15fad560b799f6731d436c1b698');
        expect(files['b.dart'], '6f144e08b58cd0925328610fad7ac07c');
      });
    });

    group('fromJson', () {
      testWithoutContext('throws if JSON is invalid', () {
        expect(() => Fingerprint.fromJson('<xml></xml>'), throwsA(anything));
      });

      testWithoutContext('creates fingerprint from valid JSON', () {
        final String jsonString = json.encode(<String, dynamic>{
          'files': <String, dynamic>{
            'a.dart': '8a21a15fad560b799f6731d436c1b698',
            'b.dart': '6f144e08b58cd0925328610fad7ac07c',
          },
        });
        final Fingerprint fingerprint = Fingerprint.fromJson(jsonString);
        final Map<String, dynamic>? content = castStringKeyedMap(json.decode(fingerprint.toJson()));
        final Map<String, dynamic> files = content!['files'] as Map<String, dynamic>;
        expect(content, hasLength(1));
        expect(files, hasLength(2));
        expect(files['a.dart'], '8a21a15fad560b799f6731d436c1b698');
        expect(files['b.dart'], '6f144e08b58cd0925328610fad7ac07c');
      });
      testWithoutContext('treats missing properties and files entries as if empty', () {
        final String jsonString = json.encode(<String, dynamic>{});
        expect(Fingerprint.fromJson(jsonString), Fingerprint.fromBuildInputs(const <String>[], fileSystem));
      });
    });

    group('operator ==', () {
      testWithoutContext('reports not equal if file checksums do not match', () {
        final Map<String, dynamic> a = <String, dynamic>{
          'files': <String, dynamic>{
            'a.dart': '8a21a15fad560b799f6731d436c1b698',
            'b.dart': '6f144e08b58cd0925328610fad7ac07c',
          },
        };
        final Map<String, dynamic> b = Map<String, dynamic>.of(a);
        b['files'] = <String, dynamic>{
          'a.dart': '8a21a15fad560b799f6731d436c1b698',
          'b.dart': '6f144e08b58cd0925328610fad7ac07d',
        };
        expect(Fingerprint.fromJson(json.encode(a)) == Fingerprint.fromJson(json.encode(b)), isFalse);
      });

      testWithoutContext('reports not equal if file paths do not match', () {
        final Map<String, dynamic> a = <String, dynamic>{
          'files': <String, dynamic>{
            'a.dart': '8a21a15fad560b799f6731d436c1b698',
            'b.dart': '6f144e08b58cd0925328610fad7ac07c',
          },
        };
        final Map<String, dynamic> b = Map<String, dynamic>.of(a);
        b['files'] = <String, dynamic>{
          'a.dart': '8a21a15fad560b799f6731d436c1b698',
          'c.dart': '6f144e08b58cd0925328610fad7ac07d',
        };
        expect(Fingerprint.fromJson(json.encode(a)) == Fingerprint.fromJson(json.encode(b)), isFalse);
      });

      testWithoutContext('reports equal if properties and file checksums match', () {
        final Map<String, dynamic> a = <String, dynamic>{
          'files': <String, dynamic>{
            'a.dart': '8a21a15fad560b799f6731d436c1b698',
            'b.dart': '6f144e08b58cd0925328610fad7ac07c',
          },
        };
        expect(Fingerprint.fromJson(json.encode(a)) == Fingerprint.fromJson(json.encode(a)), isTrue);
      });
    });
    group('hashCode', () {
      testWithoutContext('is consistent with equals, even if map entries are reordered', () {
        final Fingerprint a = Fingerprint.fromJson('{"properties":{"a":"A","b":"B"},"files":{}}');
        final Fingerprint b = Fingerprint.fromJson('{"properties":{"b":"B","a":"A"},"files":{}}');
        expect(a, b);
        expect(a.hashCode, b.hashCode);
      });
    });
  });
});
}
