// 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 Container(
      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<Container>(find.byKey(key)).color, trueColor);

    // Set the value to False
    controller.sink.add(false);
    await tester.pumpAndSettle();
    expect(tester.widget<Container>(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);
  });
}
