// 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:ui';

import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import 'utils/fake_and_mock_utils.dart';

void main() {
  group('TestDisplay', () {
    Display trueDisplay() => PlatformDispatcher.instance.displays.single;
    TestDisplay boundDisplay() =>
        WidgetsBinding.instance.platformDispatcher.displays.single as TestDisplay;

    tearDown(() {
      boundDisplay().reset();
    });

    testWidgets('can handle new methods without breaking', (WidgetTester tester) async {
      final dynamic testDisplay = tester.view.display;
      //ignore: avoid_dynamic_calls
      expect(testDisplay.someNewProperty, null);
    });

    testWidgets('can fake devicePixelRatio', (WidgetTester tester) async {
      verifyPropertyFaked<double>(
        tester: tester,
        realValue: trueDisplay().devicePixelRatio,
        fakeValue: trueDisplay().devicePixelRatio + 1,
        propertyRetriever: () => boundDisplay().devicePixelRatio,
        propertyFaker: (_, double fake) {
          boundDisplay().devicePixelRatio = fake;
        },
      );
    });

    testWidgets('can reset devicePixelRatio', (WidgetTester tester) async {
      verifyPropertyReset<double>(
        tester: tester,
        fakeValue: trueDisplay().devicePixelRatio + 1,
        propertyRetriever: () => boundDisplay().devicePixelRatio,
        propertyResetter: () => boundDisplay().resetDevicePixelRatio(),
        propertyFaker: (double fake) {
          boundDisplay().devicePixelRatio = fake;
        },
      );
    });

    testWidgets('resetting devicePixelRatio also resets view.devicePixelRatio', (
      WidgetTester tester,
    ) async {
      verifyPropertyReset(
        tester: tester,
        fakeValue: trueDisplay().devicePixelRatio + 1,
        propertyRetriever: () => tester.view.devicePixelRatio,
        propertyResetter: () => boundDisplay().resetDevicePixelRatio(),
        propertyFaker: (double dpr) => boundDisplay().devicePixelRatio = dpr,
      );
    });

    testWidgets('updating devicePixelRatio also updates view.devicePixelRatio', (
      WidgetTester tester,
    ) async {
      tester.view.display.devicePixelRatio = tester.view.devicePixelRatio + 1;

      expect(tester.view.devicePixelRatio, tester.view.display.devicePixelRatio);
    });

    testWidgets('can fake refreshRate', (WidgetTester tester) async {
      verifyPropertyFaked<double>(
        tester: tester,
        realValue: trueDisplay().refreshRate,
        fakeValue: trueDisplay().refreshRate + 1,
        propertyRetriever: () => boundDisplay().refreshRate,
        propertyFaker: (_, double fake) {
          boundDisplay().refreshRate = fake;
        },
      );
    });

    testWidgets('can reset refreshRate', (WidgetTester tester) async {
      verifyPropertyReset<double>(
        tester: tester,
        fakeValue: trueDisplay().refreshRate + 1,
        propertyRetriever: () => boundDisplay().refreshRate,
        propertyResetter: () => boundDisplay().resetRefreshRate(),
        propertyFaker: (double fake) {
          boundDisplay().refreshRate = fake;
        },
      );
    });

    testWidgets('can fake size', (WidgetTester tester) async {
      verifyPropertyFaked<Size>(
        tester: tester,
        realValue: trueDisplay().size,
        fakeValue: const Size(354, 856),
        propertyRetriever: () => boundDisplay().size,
        propertyFaker: (_, Size fake) {
          boundDisplay().size = fake;
        },
      );
    });

    testWidgets('can reset size', (WidgetTester tester) async {
      verifyPropertyReset<Size>(
        tester: tester,
        fakeValue: const Size(465, 980),
        propertyRetriever: () => boundDisplay().size,
        propertyResetter: () => boundDisplay().resetSize(),
        propertyFaker: (Size fake) {
          boundDisplay().size = fake;
        },
      );
    });

    testWidgets('can reset all values', (WidgetTester tester) async {
      addTearDown(tester.binding.resetLayers);
      final initial = DisplaySnapshot(tester.view.display);

      tester.view.display.devicePixelRatio = 7;
      tester.view.display.refreshRate = 40;
      tester.view.display.size = const Size(476, 823);

      final faked = DisplaySnapshot(tester.view.display);

      tester.view.display.reset();

      final reset = DisplaySnapshot(tester.view.display);

      expect(initial, isNot(matchesSnapshot(faked)));
      expect(initial, matchesSnapshot(reset));
    });
  });
}

class DisplaySnapshot {
  DisplaySnapshot(Display display)
    : devicePixelRatio = display.devicePixelRatio,
      refreshRate = display.refreshRate,
      id = display.id,
      size = display.size;

  final double devicePixelRatio;
  final double refreshRate;
  final int id;
  final Size size;
}

Matcher matchesSnapshot(DisplaySnapshot expected) => _DisplaySnapshotMatcher(expected);

class _DisplaySnapshotMatcher extends Matcher {
  _DisplaySnapshotMatcher(this.expected);

  final DisplaySnapshot expected;

  @override
  Description describe(Description description) {
    description.add('snapshot of a Display matches');
    return description;
  }

  @override
  Description describeMismatch(
    dynamic item,
    Description mismatchDescription,
    Map<dynamic, dynamic> matchState,
    bool verbose,
  ) {
    assert(item is DisplaySnapshot, 'Can only match against snapshots of Display.');
    final actual = item as DisplaySnapshot;

    if (actual.devicePixelRatio != expected.devicePixelRatio) {
      mismatchDescription.add(
        'actual.devicePixelRatio (${actual.devicePixelRatio}) did not match expected.devicePixelRatio (${expected.devicePixelRatio})',
      );
    }
    if (actual.refreshRate != expected.refreshRate) {
      mismatchDescription.add(
        'actual.refreshRate (${actual.refreshRate}) did not match expected.refreshRate (${expected.refreshRate})',
      );
    }
    if (actual.size != expected.size) {
      mismatchDescription.add(
        'actual.size (${actual.size}) did not match expected.size (${expected.size})',
      );
    }
    if (actual.id != expected.id) {
      mismatchDescription.add(
        'actual.id (${actual.id}) did not match expected.id (${expected.id})',
      );
    }

    return mismatchDescription;
  }

  @override
  bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
    assert(item is DisplaySnapshot, 'Can only match against snapshots of Display.');
    final actual = item as DisplaySnapshot;

    return actual.devicePixelRatio == expected.devicePixelRatio &&
        actual.refreshRate == expected.refreshRate &&
        actual.size == expected.size &&
        actual.id == expected.id;
  }
}
