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

import 'package:flutter/material.dart';

class PostBackdropFilterPage extends StatefulWidget {
  const PostBackdropFilterPage({super.key});

  @override
  State<PostBackdropFilterPage> createState() => _PostBackdropFilterPageState();
}

class _PostBackdropFilterPageState extends State<PostBackdropFilterPage> with TickerProviderStateMixin {
  bool _includeBackdropFilter = false;
  late AnimationController animation;

  @override
  void initState() {
    super.initState();
    animation = AnimationController(vsync: this, duration: const Duration(seconds: 1));
  }

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

  @override
  Widget build(BuildContext context) {
    Widget getConditionalBackdrop() {
      if (_includeBackdropFilter) {
        return Column(
          children: <Widget>[
            const SizedBox(height: 20),
            ClipRect(
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
                child: const Text('BackdropFilter'),
              ),
            ),
            const SizedBox(height: 20),
          ],
        );
      } else {
        return const SizedBox(height: 20);
      }
    }

    return Scaffold(
      backgroundColor: Colors.grey,
      body: Stack(
        children: <Widget>[
          Text('0' * 10000, style: const TextStyle(color: Colors.yellow)),
          Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Expanded(
                child: RepaintBoundary(
                    child: Center(
                      child: AnimatedBuilder(
                          animation: animation,
                          builder: (BuildContext c, Widget? w) {
                            final int val = (animation.value * 255).round();
                            return Container(
                                width: 50,
                                height: 50,
                                color: Color.fromARGB(255, val, val, val));
                          }),
                    )),
              ),
              getConditionalBackdrop(),
              RepaintBoundary(
                child: Container(
                  color: Colors.white,
                  child:Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      const Text('Include BackdropFilter:'),
                      Checkbox(
                        key: const Key('bdf-checkbox'), // this key is used by the driver test
                        value: _includeBackdropFilter,
                        onChanged: (bool? v) => setState(() { _includeBackdropFilter = v ?? false; }),
                      ),
                      MaterialButton(
                        key: const Key('bdf-animate'), // this key is used by the driver test
                        child: const Text('Animate'),
                        onPressed: () => setState(() { animation.repeat(); }),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
