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

import 'package:flutter/material.dart';

enum FilterType {
  opacity, rotateTransform, rotateFilter,
}

class FilteredChildAnimationPage extends StatefulWidget {
  const FilteredChildAnimationPage(this.initialFilterType, {
    Key? key,
    this.initialComplexChild = true,
    this.initialUseRepaintBoundary = true,
  }) : super(key: key);

  final FilterType initialFilterType;
  final bool initialComplexChild;
  final bool initialUseRepaintBoundary;

  @override
  State<FilteredChildAnimationPage> createState() => _FilteredChildAnimationPageState();
}

class _FilteredChildAnimationPageState extends State<FilteredChildAnimationPage> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  final GlobalKey _childKey = GlobalKey(debugLabel: 'child to animate');
  Offset _childCenter = Offset.zero;

  FilterType? _filterType;
  late bool _complexChild;
  late bool _useRepaintBoundary;

  @override
  void initState() {
    super.initState();
    _filterType = widget.initialFilterType;
    _complexChild = widget.initialComplexChild;
    _useRepaintBoundary = widget.initialUseRepaintBoundary;
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      final RenderBox childBox = _childKey.currentContext!.findRenderObject()! as RenderBox;
      _childCenter = childBox.paintBounds.center;
    });
    _controller = AnimationController(vsync: this, duration: const Duration(seconds: 2));
    _controller.repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _setFilterType(FilterType type, bool selected) {
    setState(() => _filterType = selected ? type : null);
  }

  String get _title {
    switch (_filterType) {
      case FilterType.opacity: return 'Fading Child Animation';
      case FilterType.rotateTransform: return 'Transformed Child Animation';
      case FilterType.rotateFilter: return 'Matrix Filtered Child Animation';
      case null: return 'Static Child';
    }
  }

  static Widget _makeChild(int rows, int cols, double fontSize, bool complex) {
    final BoxDecoration decoration = BoxDecoration(
      color: Colors.green,
      boxShadow: complex ? <BoxShadow>[
        const BoxShadow(
          blurRadius: 10.0,
        ),
      ] : null,
      borderRadius: BorderRadius.circular(10.0),
    );
    return Stack(
      alignment: Alignment.center,
      children: <Widget>[
        Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: List<Widget>.generate(rows, (int r) => Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: List<Widget>.generate(cols, (int c) => Container(
              decoration: decoration,
              child: Text('text', style: TextStyle(fontSize: fontSize)),
            )),
          )),
        ),
        const Text('child',
          style: TextStyle(
            color: Colors.blue,
            fontSize: 36,
          ),
        ),
      ],
    );
  }

  Widget _animate({required Widget child, required bool protectChild}) {
    if (_filterType == null) {
      _controller.reset();
      return child;
    }
    final FilterType filterType = _filterType!;
    _controller.repeat();
    Widget Function(BuildContext, Widget?) builder;
    switch (filterType) {
      case FilterType.opacity:
        builder = (BuildContext context, Widget? child) => Opacity(
          opacity: (_controller.value * 2.0 - 1.0).abs(),
          child: child,
        );
        break;
      case FilterType.rotateTransform:
        builder = (BuildContext context, Widget? child) => Transform(
          transform: Matrix4.rotationZ(_controller.value * 2.0 * pi),
          alignment: Alignment.center,
          filterQuality: FilterQuality.low,
          child: child,
        );
        break;
      case FilterType.rotateFilter:
        builder = (BuildContext context, Widget? child) => ImageFiltered(
          imageFilter: ImageFilter.matrix((
              Matrix4.identity()
                ..translate(_childCenter.dx, _childCenter.dy)
                ..rotateZ(_controller.value * 2.0 * pi)
                ..translate(- _childCenter.dx, - _childCenter.dy)
          ).storage),
          child: child,
        );
        break;
    }
    return RepaintBoundary(
      child: AnimatedBuilder(
        animation: _controller,
        builder: builder,
        child: protectChild ? RepaintBoundary(child: child) : child,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_title),
      ),
      body: Center(
        child: _animate(
          child: Container(
            key: _childKey,
            color: Colors.yellow,
            width: 300,
            height: 300,
            child: Center(
              child: _makeChild(4, 3, 24.0, _complexChild),
            ),
          ),
          protectChild: _useRepaintBoundary,
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text('Opacity:'),
                Checkbox(
                  value: _filterType == FilterType.opacity,
                  onChanged: (bool? b) => _setFilterType(FilterType.opacity, b ?? false),
                ),
                const Text('Tx Rotate:'),
                Checkbox(
                  value: _filterType == FilterType.rotateTransform,
                  onChanged: (bool? b) => _setFilterType(FilterType.rotateTransform, b ?? false),
                ),
                const Text('IF Rotate:'),
                Checkbox(
                  value: _filterType == FilterType.rotateFilter,
                  onChanged: (bool? b) => _setFilterType(FilterType.rotateFilter, b ?? false),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text('Complex child:'),
                Checkbox(
                  value: _complexChild,
                  onChanged: (bool? b) => setState(() => _complexChild = b ?? false),
                ),
                const Text('RPB on child:'),
                Checkbox(
                  value: _useRepaintBoundary,
                  onChanged: (bool? b) => setState(() => _useRepaintBoundary = b ?? false),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
