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

import 'package:flutter/material.dart';

// This tests whether the Opacity layer raster cache works with color filters.
// See https://github.com/flutter/flutter/issues/51975.
class ColorFilterAndFadePage extends StatefulWidget {
  const ColorFilterAndFadePage({Key key}) : super(key: key);

  @override
  State<ColorFilterAndFadePage> createState() => _ColorFilterAndFadePageState();
}

class _ColorFilterAndFadePageState extends State<ColorFilterAndFadePage> with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    final Widget shadowWidget = _ShadowWidget(
      width: 24,
      height: 24,
      useColorFilter: _useColorFilter,
      shadow: const ui.Shadow(
        color: Colors.black45,
        offset: Offset(0.0, 2.0),
        blurRadius: 4.0,
      ),
    );

    final Widget row = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        shadowWidget,
        const SizedBox(width: 12),
        shadowWidget,
        const SizedBox(width: 12),
        shadowWidget,
        const SizedBox(width: 12),
        shadowWidget,
        const SizedBox(width: 12),
        shadowWidget,
        const SizedBox(width: 12),
      ],
    );

    final Widget column = Column(mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          row,
          const SizedBox(height: 12),
          row,
          const SizedBox(height: 12),
          row,
          const SizedBox(height: 12),
          row,
          const SizedBox(height: 12),
        ],
    );

    final Widget fadeTransition = FadeTransition(
      opacity: _opacityAnimation,
      // This RepaintBoundary is necessary to not let the opacity change
      // invalidate the layer raster cache below. This is necessary with
      // or without the color filter.
      child: RepaintBoundary(
        child: column,
      ),
    );

    return Scaffold(
        backgroundColor: Colors.lightBlue,
        body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                fadeTransition,
                Container(height: 20),
                const Text('Use Color Filter:'),
                Checkbox(
                  value: _useColorFilter,
                  onChanged: (bool value) {
                    setState(() {
                      _useColorFilter = value;
                    });
                  },
                ),
              ],
            ),
        ),
    );
  }

  // Create a looping fade-in fade-out animation for opacity.
  void _initAnimation() {
    _controller = AnimationController(duration: const Duration(seconds: 3), vsync: this);
    _opacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller);
    _opacityAnimation.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
    _controller.forward();
  }

  @override
  void initState() {
    super.initState();
    _initAnimation();
  }

  AnimationController _controller;
  Animation<double> _opacityAnimation;
  bool _useColorFilter = true;
}

class _ShadowWidget extends StatelessWidget {
  const _ShadowWidget({
    @required this.width,
    @required this.height,
    @required this.useColorFilter,
    @required this.shadow,
  });

  final double width;
  final double height;
  final bool useColorFilter;
  final Shadow shadow;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      height: height,
      child: CustomPaint(
        painter: _ShadowPainter(
          useColorFilter: useColorFilter,
          shadow: shadow,
        ),
        size: Size(width, height),
        isComplex: true,
        willChange: false,
      ),
    );
  }
}

class _ShadowPainter extends CustomPainter {
  const _ShadowPainter({this.useColorFilter, @required this.shadow});

  final bool useColorFilter;
  final Shadow shadow;

  @override
  void paint(Canvas canvas, Size size) {
    final Rect rect = Offset.zero & size;

    final Paint paint = Paint();
    if (useColorFilter) {
      paint.colorFilter = ColorFilter.mode(shadow.color, BlendMode.srcIn);
    }

    canvas.saveLayer(null, paint);
    canvas.translate(shadow.offset.dx, shadow.offset.dy);
    canvas.drawRect(rect, Paint());
    canvas.drawRect(rect, Paint()..maskFilter = MaskFilter.blur(BlurStyle.normal, shadow.blurSigma));
    canvas.restore();

    canvas.drawRect(rect, Paint()..color = useColorFilter ? Colors.white : Colors.black);
  }

  @override
  bool shouldRepaint(_ShadowPainter oldDelegate) => oldDelegate.useColorFilter != useColorFilter;
}
