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

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

const Key key = Key('testContainer');
const Color trueColor = Colors.red;
const Color falseColor = Colors.green;

/// Mock widget which plays the role of a button -- it can emit notifications
/// that [MaterialState] values are now in or out of play.
class _InnerWidget extends StatefulWidget {
  const _InnerWidget({required this.onValueChanged, required this.controller});
  final ValueChanged<bool> onValueChanged;
  final StreamController<bool> controller;

  @override
  _InnerWidgetState createState() => _InnerWidgetState();
}

class _InnerWidgetState extends State<_InnerWidget> {
  @override
  void initState() {
    super.initState();
    widget.controller.stream.listen((bool val) => widget.onValueChanged(val));
  }
  @override
  Widget build(BuildContext context) => Container();
}

class _MyWidget extends StatefulWidget {
  const _MyWidget({
    required this.controller,
    required this.evaluator,
    required this.materialState,
  });

  /// Wrapper around `MaterialStateMixin.isPressed/isHovered/isFocused/etc`.
  final bool Function(_MyWidgetState state) evaluator;

  /// Stream passed down to the child [_InnerWidget] to begin the process.
  /// This plays the role of an actual user interaction in the wild, but allows
  /// us to engage the system without mocking pointers/hovers etc.
  final StreamController<bool> controller;

  /// The value we're watching in the given test.
  final MaterialState materialState;

  @override
  State createState() => _MyWidgetState();
}

class _MyWidgetState extends State<_MyWidget> with MaterialStateMixin {

  @override
  Widget build(BuildContext context) {
    return ColoredBox(
      key: key,
      color: widget.evaluator(this) ? trueColor : falseColor,
      child: _InnerWidget(
        onValueChanged: updateMaterialState(widget.materialState),
        controller: widget.controller,
      ),
    );
  }
}

void main() {
  Future<void> verify(WidgetTester tester, Widget widget, StreamController<bool> controller,) async {
    await tester.pumpWidget(MaterialApp(home: Scaffold(body: widget)));
    // Set the value to True
    controller.sink.add(true);
    await tester.pumpAndSettle();
    expect(tester.widget<ColoredBox>(find.byKey(key)).color, trueColor);

    // Set the value to False
    controller.sink.add(false);
    await tester.pumpAndSettle();
    expect(tester.widget<ColoredBox>(find.byKey(key)).color, falseColor);
  }

  testWidgets('MaterialState.pressed is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isPressed,
      materialState: MaterialState.pressed,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.focused is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isFocused,
      materialState: MaterialState.focused,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.hovered is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isHovered,
      materialState: MaterialState.hovered,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.disabled is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isDisabled,
      materialState: MaterialState.disabled,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.selected is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isSelected,
      materialState: MaterialState.selected,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.scrolledUnder is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isScrolledUnder,
      materialState: MaterialState.scrolledUnder,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.dragged is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isDragged,
      materialState: MaterialState.dragged,
    );
    await verify(tester, widget, controller);
  });

  testWidgets('MaterialState.error is tracked', (WidgetTester tester) async {
    final StreamController<bool> controller = StreamController<bool>();
    final _MyWidget widget = _MyWidget(
      controller: controller,
      evaluator: (_MyWidgetState state) => state.isErrored,
      materialState: MaterialState.error,
    );
    await verify(tester, widget, controller);
  });
}
