// 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:flutter/gestures.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:vector_math/vector_math_64.dart';

void main() {
  test('wrapped HitTestResult gets HitTestEntry added to wrapping HitTestResult', () async {
    final HitTestEntry entry1 = HitTestEntry(_DummyHitTestTarget());
    final HitTestEntry entry2 = HitTestEntry(_DummyHitTestTarget());
    final HitTestEntry entry3 = HitTestEntry(_DummyHitTestTarget());
    final Matrix4 transform = Matrix4.translationValues(40.0, 150.0, 0.0);

    final HitTestResult wrapped = MyHitTestResult()
      ..publicPushTransform(transform);
    wrapped.add(entry1);
    expect(wrapped.path, equals(<HitTestEntry>[entry1]));
    expect(entry1.transform, transform);

    final HitTestResult wrapping = HitTestResult.wrap(wrapped);
    expect(wrapping.path, equals(<HitTestEntry>[entry1]));
    expect(wrapping.path, same(wrapped.path));

    wrapping.add(entry2);
    expect(wrapping.path, equals(<HitTestEntry>[entry1, entry2]));
    expect(wrapped.path, equals(<HitTestEntry>[entry1, entry2]));
    expect(entry2.transform, transform);

    wrapped.add(entry3);
    expect(wrapping.path, equals(<HitTestEntry>[entry1, entry2, entry3]));
    expect(wrapped.path, equals(<HitTestEntry>[entry1, entry2, entry3]));
    expect(entry3.transform, transform);
  });

  test('HitTestResult should correctly push and pop transforms', () {
    Matrix4? currentTransform(HitTestResult targetResult) {
      final HitTestEntry entry = HitTestEntry(_DummyHitTestTarget());
      targetResult.add(entry);
      return entry.transform;
    }

    final MyHitTestResult result = MyHitTestResult();

    final Matrix4 m1 = Matrix4.translationValues(10, 20, 0);
    final Matrix4 m2 = Matrix4.rotationZ(1);
    final Matrix4 m3 = Matrix4.diagonal3Values(1.1, 1.2, 1.0);

    result.publicPushTransform(m1);
    expect(currentTransform(result), equals(m1));

    result.publicPushTransform(m2);
    expect(currentTransform(result), equals(m2 * m1));
    expect(currentTransform(result), equals(m2 * m1)); // Test repeated add

    // The `wrapped` is wrapped at [m1, m2]
    final MyHitTestResult wrapped = MyHitTestResult.wrap(result);
    expect(currentTransform(wrapped), equals(m2 * m1));

    result.publicPushTransform(m3);
    // ignore: avoid_dynamic_calls
    expect(currentTransform(result), equals(m3 * m2 * m1));
    // ignore: avoid_dynamic_calls
    expect(currentTransform(wrapped), equals(m3 * m2 * m1));

    result.publicPopTransform();
    result.publicPopTransform();
    expect(currentTransform(result), equals(m1));

    result.publicPopTransform();
    result.publicPushTransform(m3);
    expect(currentTransform(result), equals(m3));

    result.publicPushTransform(m2);
    expect(currentTransform(result), equals(m2 * m3));
  });

  test('HitTestResult should correctly push and pop offsets', () {
    Matrix4? currentTransform(HitTestResult targetResult) {
      final HitTestEntry entry = HitTestEntry(_DummyHitTestTarget());
      targetResult.add(entry);
      return entry.transform;
    }

    final MyHitTestResult result = MyHitTestResult();

    final Matrix4 m1 = Matrix4.rotationZ(1);
    final Matrix4 m2 = Matrix4.diagonal3Values(1.1, 1.2, 1.0);
    const Offset o3 = Offset(10, 20);
    final Matrix4 m3 = Matrix4.translationValues(o3.dx, o3.dy, 0.0);

    // Test pushing offset as the first element
    result.publicPushOffset(o3);
    expect(currentTransform(result), equals(m3));
    result.publicPopTransform();

    result.publicPushOffset(o3);
    result.publicPushTransform(m1);
    expect(currentTransform(result), equals(m1 * m3));
    expect(currentTransform(result), equals(m1 * m3)); // Test repeated add

    // The `wrapped` is wrapped at [m1, m2]
    final MyHitTestResult wrapped = MyHitTestResult.wrap(result);
    expect(currentTransform(wrapped), equals(m1 * m3));

    result.publicPushTransform(m2);
    // ignore: avoid_dynamic_calls
    expect(currentTransform(result), equals(m2 * m1 * m3));
    // ignore: avoid_dynamic_calls
    expect(currentTransform(wrapped), equals(m2 * m1 * m3));

    result.publicPopTransform();
    result.publicPopTransform();
    result.publicPopTransform();
    expect(currentTransform(result), equals(Matrix4.identity()));

    result.publicPushTransform(m2);
    result.publicPushOffset(o3);
    result.publicPushTransform(m1);

    // ignore: avoid_dynamic_calls
    expect(currentTransform(result), equals(m1 * m3 * m2));

    result.publicPopTransform();

    expect(currentTransform(result), equals(m3 * m2));
  });
}

class _DummyHitTestTarget implements HitTestTarget {
  @override
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    // Nothing to do.
  }
}

class MyHitTestResult extends HitTestResult {
  MyHitTestResult();
  MyHitTestResult.wrap(HitTestResult result) : super.wrap(result);

  void publicPushTransform(Matrix4 transform) => pushTransform(transform);
  void publicPushOffset(Offset offset) => pushOffset(offset);
  void publicPopTransform() => popTransform();
}
