// 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 'package:flutter/material.dart';

import '../common.dart';

// Various tests to verify that the Opacity layer propagates the opacity to various
// combinations of children that can apply it themselves.
// See https://github.com/flutter/flutter/issues/75697
class OpacityPeepholePage extends StatelessWidget {
  const OpacityPeepholePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Opacity Peephole tests')),
      body: ListView(
        key: const Key(kOpacityScrollableName),
        children: <Widget>[
          for (OpacityPeepholeCase variant in allOpacityPeepholeCases)
            ElevatedButton(
              key: Key(variant.route),
              child: Text(variant.name),
              onPressed: () {
                Navigator.pushNamed(context, variant.route);
              },
            ),
        ],
      ),
    );
  }
}

typedef ValueBuilder = Widget Function(double v);
typedef AnimationBuilder = Widget Function(Animation<double> animation);

double _opacity(double v) => v * 0.5 + 0.25;
int _red(double v) => (v * 255).round();
int _green(double v) => _red(1 - v);
int _blue(double v) => 0;

class OpacityPeepholeCase {
  OpacityPeepholeCase.forValue({required String route, required String name, required ValueBuilder builder})
      : this.forAnimation(
    route: route,
    name: name,
    builder: (Animation<double> animation) => AnimatedBuilder(
      animation: animation,
      builder: (BuildContext context, Widget? child) => builder(animation.value),
    ),
  );

  OpacityPeepholeCase.forAnimation({required this.route, required this.name, required AnimationBuilder builder})
      : animationBuilder = builder;

  final String route;
  final String name;
  final AnimationBuilder animationBuilder;

  Widget buildPage(BuildContext context) {
    return VariantPage(variant: this);
  }
}

List<OpacityPeepholeCase> allOpacityPeepholeCases = <OpacityPeepholeCase>[
  // Tests that Opacity can hand down value to a simple child
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeOneRectRouteName,
    name: 'One Big Rectangle',
    builder: (double v) {
      return Opacity(
        opacity: _opacity(v),
        child: Container(
          width: 300,
          height: 400,
          color: Color.fromARGB(255, _red(v), _green(v), _blue(v)),
        ),
      );
    }
  ),
  // Tests that a column of Opacity widgets can individually hand their values down to simple children
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeColumnOfOpacityRouteName,
    name: 'Column of Opacity',
    builder: (double v) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          for (int i = 0; i < 10; i++, v = 1 - v)
            Opacity(
              opacity: _opacity(v),
              child: Padding(
                padding: const EdgeInsets.all(5),
                child: Container(
                  width: 300,
                  height: 30,
                  color: Color.fromARGB(255, _red(v), _green(v), _blue(v)),
                ),
              ),
            ),
        ],
      );
    },
  ),
  // Tests that an Opacity can hand value down to a cached child
  OpacityPeepholeCase.forValue(
      route: kOpacityPeepholeOpacityOfCachedChildRouteName,
      name: 'Opacity of Cached Child',
      builder: (double v) {
        // ChildV starts as a constant so the same color pattern always appears and the child will be cached
        double childV = 0;
        return Opacity(
          opacity: _opacity(v),
          child: RepaintBoundary(
            child: SizedBox(
              width: 300,
              height: 400,
              child: Stack(
                children: <Widget>[
                  for (double i = 0; i < 100; i += 10, childV = 1 - childV)
                    Positioned.fromRelativeRect(
                      rect: RelativeRect.fromLTRB(i, i, i, i),
                      child: Container(
                        color: Color.fromARGB(255, _red(childV), _green(childV), _blue(childV)),
                      ),
                    ),
                ],
              ),
            ),
          ),
        );
      }
  ),
  // Tests that an Opacity can hand a value down to a Column of simple non-overlapping children
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeOpacityOfColumnRouteName,
    name: 'Opacity of Column',
    builder: (double v) {
      return Opacity(
        opacity: _opacity(v),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            for (int i = 0; i < 10; i++, v = 1 - v)
              Padding(
                padding: const EdgeInsets.all(5),
                // RepaintBoundary here to avoid combining children into 1 big Picture
                child: RepaintBoundary(
                  child: Container(
                    width: 300,
                    height: 30,
                    color: Color.fromARGB(255, _red(v), _green(v), _blue(v)),
                  ),
                ),
              ),
          ],
        ),
      );
    },
  ),
  // Tests that an entire grid of Opacity objects can hand their values down to their simple children
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeGridOfOpacityRouteName,
    name: 'Grid of Opacity',
    builder: (double v) {
      double rowV = v;
      double colV = rowV;
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          for (int i = 0; i < 10; i++, rowV = 1 - rowV, colV = rowV)
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                for (int j = 0; j < 7; j++, colV = 1 - colV)
                  Opacity(
                    opacity: _opacity(colV),
                    child: Padding(
                      padding: const EdgeInsets.all(5),
                      child: Container(
                        width: 30,
                        height: 30,
                        color: Color.fromARGB(255, _red(colV), _green(colV), _blue(colV)),
                      ),
                    ),
                  ),
              ],
            ),
        ],
      );
    },
  ),
  // tests if an Opacity can hand its value down to a 2D grid of simple non-overlapping children.
  // The success of this case would depend on the sophistication of the non-overlapping tests.
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeOpacityOfGridRouteName,
    name: 'Opacity of Grid',
    builder: (double v) {
      double rowV = v;
      double colV = rowV;
      return Opacity(
        opacity: _opacity(v),
        child: SizedBox(
          width: 300,
          height: 400,
          child: Stack(
            children: <Widget>[
              for (int i = 0; i < 10; i++, rowV = 1 - rowV, colV = rowV)
                for (int j = 0; j < 7; j++, colV = 1 - colV)
                  Positioned.fromRect(
                    rect: Rect.fromLTWH(j * 40 + 5, i * 40 + 5, 30, 30),
                    // RepaintBoundary here to avoid combining the 70 children into a single Picture
                    child: RepaintBoundary(
                      child: Container(
                        color: Color.fromARGB(255, _red(colV), _green(colV), _blue(colV)),
                      ),
                    ),
                  ),
            ],
          ),
        ),
      );
    },
  ),
  // tests if an Opacity can hand its value down to a Column of non-overlapping rows of non-overlapping simple children.
  // This test only requires linear non-overlapping tests to succeed.
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeOpacityOfColOfRowsRouteName,
    name: 'Opacity of Column of Rows',
    builder: (double v) {
      double rowV = v;
      double colV = v;
      return Opacity(
        opacity: _opacity(v),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            for (int i = 0; i < 10; i++, rowV = 1 - rowV, colV = rowV)
              Padding(
                padding: const EdgeInsets.only(top: 5, bottom: 5),
                // RepaintBoundary here to separate each row into a separate layer child
                child: RepaintBoundary(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      for (int j = 0; j < 7; j++, colV = 1 - colV)
                        Padding(
                          padding: const EdgeInsets.only(left: 5, right: 5),
                          // RepaintBoundary here to prevent the row children combining into a single Picture
                          child: RepaintBoundary(
                            child: Container(
                              width: 30,
                              height: 30,
                              color: Color.fromARGB(255, _red(colV), _green(colV), _blue(colV)),
                            ),
                          ),
                        ),
                    ],
                  ),
                ),
              ),
          ],
        ),
      );
    },
  ),
  OpacityPeepholeCase.forAnimation(
    route: kOpacityPeepholeFadeTransitionTextRouteName,
    name: 'FadeTransition text',
    builder: (Animation<double> animation) {
      return FadeTransition(
        opacity: Tween<double>(begin: 0.25, end: 0.75).animate(animation),
        child: const SizedBox(
          width: 300,
          height: 400,
          child: Center(
            child: Text('Hello, World',
              style: TextStyle(fontSize: 48),
            ),
          ),
        ),
      );
    },
  ),
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeGridOfRectsWithAlphaRouteName,
    name: 'Grid of Rectangles with alpha',
    builder: (double v) {
      return Opacity(
        opacity: _opacity(v),
        child: SizedBox.expand(
          child: CustomPaint(
            painter: RectGridPainter((Canvas canvas, Size size) {
              const int numRows = 10;
              const int numCols = 7;
              const double rectWidth = 30;
              const double rectHeight = 30;
              final double hGap = (size.width - numCols * rectWidth) / (numCols + 1);
              final double vGap = (size.height - numRows * rectHeight) / (numRows + 1);
              final double gap = min(hGap, vGap);
              final double xOffset = (size.width - (numCols * (rectWidth + gap) - gap)) * 0.5;
              final double yOffset = (size.height - (numRows * (rectHeight + gap) - gap)) * 0.5;
              final Paint rectPaint = Paint();
              for (int r = 0; r < numRows; r++, v = 1 - v) {
                final double y = yOffset + r * (rectHeight + gap);
                double cv = v;
                for (int c = 0; c < numCols; c++, cv = 1 - cv) {
                  final double x = xOffset + c * (rectWidth + gap);
                  rectPaint.color = Color.fromRGBO(_red(cv), _green(cv), _blue(cv), _opacity(cv));
                  final Rect rect = Rect.fromLTWH(x, y, rectWidth, rectHeight);
                  canvas.drawRect(rect, rectPaint);
                }
              }
            }),
          ),
        ),
      );
    },
  ),
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeGridOfAlphaSaveLayerRectsRouteName,
    name: 'Grid of alpha SaveLayers of Rectangles',
    builder: (double v) {
      return Opacity(
        opacity: _opacity(v),
        child: SizedBox.expand(
          child: CustomPaint(
            painter: RectGridPainter((Canvas canvas, Size size) {
              const int numRows = 10;
              const int numCols = 7;
              const double rectWidth = 30;
              const double rectHeight = 30;
              final double hGap = (size.width - numCols * rectWidth) / (numCols + 1);
              final double vGap = (size.height - numRows * rectHeight) / (numRows + 1);
              final double gap = min(hGap, vGap);
              final double xOffset = (size.width - (numCols * (rectWidth + gap) - gap)) * 0.5;
              final double yOffset = (size.height - (numRows * (rectHeight + gap) - gap)) * 0.5;
              final Paint rectPaint = Paint();
              final Paint layerPaint = Paint();
              for (int r = 0; r < numRows; r++, v = 1 - v) {
                final double y = yOffset + r * (rectHeight + gap);
                double cv = v;
                for (int c = 0; c < numCols; c++, cv = 1 - cv) {
                  final double x = xOffset + c * (rectWidth + gap);
                  rectPaint.color = Color.fromRGBO(_red(cv), _green(cv), _blue(cv), 1.0);
                  layerPaint.color = Color.fromRGBO(255, 255, 255, _opacity(cv));
                  final Rect rect = Rect.fromLTWH(x, y, rectWidth, rectHeight);
                  canvas.saveLayer(null, layerPaint);
                  canvas.drawRect(rect, rectPaint);
                  canvas.restore();
                }
              }
            }),
          ),
        ),
      );
    },
  ),
  OpacityPeepholeCase.forValue(
    route: kOpacityPeepholeColumnOfAlphaSaveLayerRowsOfRectsRouteName,
    name: 'Grid with alpha SaveLayer on Rows',
    builder: (double v) {
      return Opacity(
        opacity: _opacity(v),
        child: SizedBox.expand(
          child: CustomPaint(
            painter: RectGridPainter((Canvas canvas, Size size) {
              const int numRows = 10;
              const int numCols = 7;
              const double rectWidth = 30;
              const double rectHeight = 30;
              final double hGap = (size.width - numCols * rectWidth) / (numCols + 1);
              final double vGap = (size.height - numRows * rectHeight) / (numRows + 1);
              final double gap = min(hGap, vGap);
              final double xOffset = (size.width - (numCols * (rectWidth + gap) - gap)) * 0.5;
              final double yOffset = (size.height - (numRows * (rectHeight + gap) - gap)) * 0.5;
              final Paint rectPaint = Paint();
              final Paint layerPaint = Paint();
              for (int r = 0; r < numRows; r++, v = 1 - v) {
                final double y = yOffset + r * (rectHeight + gap);
                layerPaint.color = Color.fromRGBO(255, 255, 255, _opacity(v));
                canvas.saveLayer(null, layerPaint);
                double cv = v;
                for (int c = 0; c < numCols; c++, cv = 1 - cv) {
                  final double x = xOffset + c * (rectWidth + gap);
                  rectPaint.color = Color.fromRGBO(_red(cv), _green(cv), _blue(cv), 1.0);
                  final Rect rect = Rect.fromLTWH(x, y, rectWidth, rectHeight);
                  canvas.drawRect(rect, rectPaint);
                }
                canvas.restore();
              }
            }),
          ),
        ),
      );
    },
  ),
];

class RectGridPainter extends CustomPainter {
  RectGridPainter(this.painter);

  final void Function(Canvas canvas, Size size) painter;

  @override
  void paint(Canvas canvas, Size size) => painter(canvas, size);

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

Map<String, WidgetBuilder> opacityPeepholeRoutes = <String, WidgetBuilder>{
  for (OpacityPeepholeCase variant in allOpacityPeepholeCases)
    variant.route: variant.buildPage,
};

class VariantPage extends StatefulWidget {
  const VariantPage({super.key, required this.variant});

  final OpacityPeepholeCase variant;

  @override
  State<VariantPage> createState() => VariantPageState();
}

class VariantPageState extends State<VariantPage> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

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

    _controller = AnimationController(vsync: this, duration: const Duration(seconds: 4));
    _controller.repeat(reverse: true);
  }

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

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.variant.name),
      ),
      body: Center(
        child: widget.variant.animationBuilder(_controller),
      ),
    );
  }
}
