// 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, Key? key}) : super(key: key);
  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,
    Key? key,
  }) : super(key: key);

  /// 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);
  });
}
