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

import 'package:flutter/widgets.dart';
import 'package:vector_math/vector_math_64.dart';

import 'ink_well.dart';
import 'material.dart';

/// Begin a Material 3 ink sparkle ripple, centered at the tap or click position
/// relative to the [referenceBox].
///
/// This effect relies on a shader, and therefore hardware acceleration.
/// Currently, this is only supported by certain C++ engine platforms. The
/// platforms that are currently supported are Android, iOS, MacOS, Windows,
/// and Linux. Support for CanvasKit web can be tracked here:
///  - https://github.com/flutter/flutter/issues/85238
///
/// To use this effect, pass an instance of [splashFactory] to the
/// `splashFactory` parameter of either the Material [ThemeData] or any
/// component that has a `splashFactory` parameter, such as buttons:
///  - [ElevatedButton]
///  - [TextButton]
///  - [OutlinedButton]
///
/// The [controller] argument is typically obtained via
/// `Material.of(context)`.
///
/// If [containedInkWell] is true, then the effect will be sized to fit
/// the well rectangle, and clipped to it when drawn. The well
/// rectangle is the box returned by [rectCallback], if provided, or
/// otherwise is the bounds of the [referenceBox].
///
/// If [containedInkWell] is false, then [rectCallback] should be null.
/// The ink ripple is clipped only to the edges of the [Material].
/// This is the default.
///
/// When the ripple is removed, [onRemoved] will be called.
///
/// {@tool snippet}
///
/// For typical use, pass the [InkSparkle.splashFactory] to the `splashFactory`
/// parameter of a button style or [ThemeData].
///
/// ```dart
/// ElevatedButton(
///   style: ElevatedButton.styleFrom(splashFactory: InkSparkle.splashFactory),
///   child: const Text('Sparkle!'),
///   onPressed: () { },
/// )
/// ```
/// {@end-tool}
class InkSparkle extends InteractiveInkFeature {
  /// Begin a sparkly ripple effect, centered at [position] relative to
  /// [referenceBox].
  ///
  /// The [color] defines the color of the splash itself. The sparkles are
  /// always white.
  ///
  /// The [controller] argument is typically obtained via
  /// `Material.of(context)`.
  ///
  /// [textDirection] is used by [customBorder] if it is non-null. This allows
  /// the [customBorder]'s path to be properly defined if it was the path was
  /// expressed in terms of "start" and "end" instead of
  /// "left" and "right".
  ///
  /// If [containedInkWell] is true, then the ripple will be sized to fit
  /// the well rectangle, then clipped to it when drawn. The well
  /// rectangle is the box returned by [rectCallback], if provided, or
  /// otherwise is the bounds of the [referenceBox].
  ///
  /// If [containedInkWell] is false, then [rectCallback] should be null.
  /// The ink ripple is clipped only to the edges of the [Material].
  /// This is the default.
  ///
  /// Clipping can happen in 3 different ways:
  ///  1. If [customBorder] is provided, it is used to determine the path for
  ///     clipping.
  ///  2. If [customBorder] is null, and [borderRadius] is provided, then the
  ///     canvas is clipped by an [RRect] created from [borderRadius].
  ///  3. If [borderRadius] is the default [BorderRadius.zero], then the canvas
  ///     is clipped with [rectCallback].
  /// When the ripple is removed, [onRemoved] will be called.
  ///
  /// [turbulenceSeed] can be passed if a non random seed should be used for
  /// the turbulence and sparkles. By default, the seed is a random number
  /// between 0.0 and 1000.0.
  ///
  /// Turbulence is an input to the shader and helps to provides a more natural,
  ///  non-circular, "splash" effect.
  ///
  /// Sparkle randomization is also driven by the [turbulenceSeed]. Sparkles are
  /// identified in the shader as "noise", and the sparkles are derived from
  /// pseudorandom triangular noise.
  InkSparkle({
    required super.controller,
    required super.referenceBox,
    required super.color,
    required Offset position,
    required TextDirection textDirection,
    bool containedInkWell = true,
    RectCallback? rectCallback,
    BorderRadius? borderRadius,
    ShapeBorder? customBorder,
    double? radius,
    super.onRemoved,
    double? turbulenceSeed,
  }) : assert(containedInkWell || rectCallback == null),
       _color = color,
       _position = position,
       _borderRadius = borderRadius ?? BorderRadius.zero,
       _customBorder = customBorder,
       _textDirection = textDirection,
       _targetRadius = (radius ?? _getTargetRadius(
                                    referenceBox,
                                    containedInkWell,
                                    rectCallback,
                                    position,
                                  )
                       ) * _targetRadiusMultiplier,
       _clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback) {
    // InkSparkle will not be painted until the async compilation completes.
    _InkSparkleFactory.initializeShader();
    controller.addInkFeature(this);

    // Immediately begin animating the ink.
    _animationController = AnimationController(
      duration: _animationDuration,
      vsync: controller.vsync,
    )..addListener(controller.markNeedsPaint)
     ..addStatusListener(_handleStatusChanged)
     ..forward();

    _radiusScale = TweenSequence<double>(
      <TweenSequenceItem<double>>[
        TweenSequenceItem<double>(
          tween: CurveTween(curve: Curves.fastOutSlowIn),
          weight: 75,
        ),
        TweenSequenceItem<double>(
          tween: ConstantTween<double>(1.0),
          weight: 25,
        ),
      ],
    ).animate(_animationController);

    // Functionally equivalent to Android 12's SkSL:
    //`return mix(u_touch, u_resolution, saturate(in_radius_scale * 2.0))`
    final Tween<Vector2> centerTween = Tween<Vector2>(
      begin: Vector2.array(<double>[_position.dx, _position.dy]),
      end: Vector2.array(<double>[referenceBox.size.width / 2, referenceBox.size.height / 2]),
    );
    final Animation<double> centerProgress = TweenSequence<double>(
      <TweenSequenceItem<double>>[
        TweenSequenceItem<double>(
          tween: Tween<double>(begin: 0.0, end: 1.0),
          weight: 50,
        ),
        TweenSequenceItem<double>(
          tween: ConstantTween<double>(1.0),
          weight: 50,
        ),
      ],
    ).animate(_radiusScale);
    _center = centerTween.animate(centerProgress);

    _alpha = TweenSequence<double>(
      <TweenSequenceItem<double>>[
        TweenSequenceItem<double>(
          tween: Tween<double>(begin: 0.0, end: 1.0),
          weight: 13,
        ),
        TweenSequenceItem<double>(
          tween: ConstantTween<double>(1.0),
          weight: 27,
        ),
        TweenSequenceItem<double>(
          tween: Tween<double>(begin: 1.0, end: 0.0),
          weight: 60,
        ),
      ],
    ).animate(_animationController);

    _sparkleAlpha = TweenSequence<double>(
      <TweenSequenceItem<double>>[
        TweenSequenceItem<double>(
          tween: Tween<double>(begin: 0.0, end: 1.0),
          weight: 13,
        ),
        TweenSequenceItem<double>(
          tween: ConstantTween<double>(1.0),
          weight: 27,
        ),
        TweenSequenceItem<double>(
          tween: Tween<double>(begin: 1.0, end: 0.0),
          weight: 50,
        ),
      ],
    ).animate(_animationController);

    // Creates an element of randomness so that ink eminating from the same
    // pixel have slightly different rings and sparkles.
    _turbulenceSeed = turbulenceSeed ?? math.Random().nextDouble() * 1000.0;
  }

  void _handleStatusChanged(AnimationStatus status) {
    if (status == AnimationStatus.completed) {
      dispose();
    }
  }

  static const Duration _animationDuration = Duration(milliseconds: 617);
  static const double _targetRadiusMultiplier = 2.3;
  static const double _rotateRight = math.pi * 0.0078125;
  static const double _rotateLeft = -_rotateRight;
  static const double _noiseDensity = 2.1;

  late AnimationController _animationController;

  // The Android 12 version has these values calculated in the GLSL. They are
  // constant for every pixel in the animation, so the Flutter implementation
  // computes these animation values in software in order to simplify the shader
  // implementation and provide better performance on most devices.
  late Animation<Vector2> _center;
  late Animation<double> _radiusScale;
  late Animation<double> _alpha;
  late Animation<double> _sparkleAlpha;

  late double _turbulenceSeed;

  final Color _color;
  final Offset _position;
  final BorderRadius _borderRadius;
  final ShapeBorder? _customBorder;
  final double _targetRadius;
  final RectCallback? _clipCallback;
  final TextDirection _textDirection;

  late final ui.FragmentShader _fragmentShader;
  bool _fragmentShaderInitialized = false;

  /// Used to specify this type of ink splash for an [InkWell], [InkResponse],
  /// material [Theme], or [ButtonStyle].
  ///
  /// Since no [turbulenceSeed] is passed, the effect will be random for
  /// subsequent presses in the same position.
  static const InteractiveInkFeatureFactory splashFactory = _InkSparkleFactory();

  /// Used to specify this type of ink splash for an [InkWell], [InkResponse],
  /// material [Theme], or [ButtonStyle].
  ///
  /// Since a [turbulenceSeed] is passed, the effect will not be random for
  /// subsequent presses in the same position. This can be used for testing.
  static const InteractiveInkFeatureFactory constantTurbulenceSeedSplashFactory = _InkSparkleFactory.constantTurbulenceSeed();

  @override
  void dispose() {
    _animationController.stop();
    _animationController.dispose();
    if (_fragmentShaderInitialized) {
      _fragmentShader.dispose();
    }
    super.dispose();
  }

  @override
  void paintFeature(Canvas canvas, Matrix4 transform) {
    assert(_animationController.isAnimating);

    // InkSparkle can only paint if its shader has been compiled.
    if (_InkSparkleFactory._program == null) {
      // Skipping paintFeature because the shader it relies on is not ready to
      // be used. InkSparkleFactory.initializeShader must complete
      // before InkSparkle can paint.
      return;
    }

    if (!_fragmentShaderInitialized) {
      _fragmentShader = _InkSparkleFactory._program!.fragmentShader();
      _fragmentShaderInitialized = true;
    }

    canvas.save();
    _transformCanvas(canvas: canvas, transform: transform);
    if (_clipCallback != null) {
      _clipCanvas(
        canvas: canvas,
        clipCallback: _clipCallback!,
        textDirection: _textDirection,
        customBorder: _customBorder,
        borderRadius: _borderRadius,
      );
    }

    _updateFragmentShader();

    final Paint paint = Paint()..shader = _fragmentShader;
    if (_clipCallback != null) {
      canvas.drawRect(_clipCallback!(), paint);
    } else {
      canvas.drawPaint(paint);
    }
    canvas.restore();
  }

  double get _width => referenceBox.size.width;
  double get _height => referenceBox.size.height;


  /// All double values for uniforms come from the Android 12 ripple
  /// implementation from the following files:
  /// - https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java
  /// - https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/drawable/RippleDrawable.java
  /// - https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/drawable/RippleAnimationSession.java
  void _updateFragmentShader() {
    const double turbulenceScale = 1.5;
    final double turbulencePhase = _turbulenceSeed + _radiusScale.value;
    final double noisePhase = turbulencePhase;
    final double rotation1 = turbulencePhase * _rotateRight + 1.7 * math.pi;
    final double rotation2 = turbulencePhase * _rotateLeft + 2.0 * math.pi;
    final double rotation3 = turbulencePhase * _rotateRight + 2.75 * math.pi;

    _fragmentShader
      // uColor
      ..setFloat(0, _color.red / 255.0)
      ..setFloat(1, _color.green / 255.0)
      ..setFloat(2, _color.blue / 255.0)
      ..setFloat(3, _color.alpha / 255.0)
      // uAlpha
      ..setFloat(4, _alpha.value)
      // uSparkleColor
      ..setFloat(5, 1.0)
      ..setFloat(6, 1.0)
      ..setFloat(7, 1.0)
      ..setFloat(8, 1.0)
      // uSparkleAlpha
      ..setFloat(9, _sparkleAlpha.value)
      // uBlur
      ..setFloat(10, 1.0)
      // uCenter
      ..setFloat(11, _center.value.x)
      ..setFloat(12, _center.value.y)
      // uRadiusScale
      ..setFloat(13, _radiusScale.value)
      // uMaxRadius
      ..setFloat(14, _targetRadius)
      // uResolutionScale
      ..setFloat(15, 1.0 / _width)
      ..setFloat(16, 1.0 / _height)
      // uNoiseScale
      ..setFloat(17, _noiseDensity / _width)
      ..setFloat(18, _noiseDensity / _height)
      // uNoisePhase
      ..setFloat(19, noisePhase / 1000.0)
      // uCircle1
      ..setFloat(20, turbulenceScale * 0.5 + (turbulencePhase * 0.01 * math.cos(turbulenceScale * 0.55)))
      ..setFloat(21, turbulenceScale * 0.5 + (turbulencePhase * 0.01 * math.sin(turbulenceScale * 0.55)))
      // uCircle2
      ..setFloat(22, turbulenceScale * 0.2 + (turbulencePhase * -0.0066 * math.cos(turbulenceScale * 0.45)))
      ..setFloat(23, turbulenceScale * 0.2 + (turbulencePhase * -0.0066 * math.sin(turbulenceScale * 0.45)))
      // uCircle3
      ..setFloat(24, turbulenceScale + (turbulencePhase * -0.0066 * math.cos(turbulenceScale * 0.35)))
      ..setFloat(25, turbulenceScale + (turbulencePhase * -0.0066 * math.sin(turbulenceScale * 0.35)))
      // uRotation1
      ..setFloat(26, math.cos(rotation1))
      ..setFloat(27, math.sin(rotation1))
      // uRotation2
      ..setFloat(28, math.cos(rotation2))
      ..setFloat(29, math.sin(rotation2))
      // uRotation3
      ..setFloat(30, math.cos(rotation3))
      ..setFloat(31, math.sin(rotation3));
  }

  /// Transforms the canvas for an ink feature to be painted on the [canvas].
  ///
  /// This should be called before painting ink features that do not use
  /// [paintInkCircle].
  ///
  /// The [transform] argument is the [Matrix4] transform that typically
  /// shifts the coordinate space of the canvas to the space in which
  /// the ink feature is to be painted.
  ///
  /// For examples on how the function is used, see [InkSparkle] and [paintInkCircle].
  void _transformCanvas({
    required Canvas canvas,
    required Matrix4 transform,
  }) {
    final Offset? originOffset = MatrixUtils.getAsTranslation(transform);
    if (originOffset == null) {
      canvas.transform(transform.storage);
    } else {
      canvas.translate(originOffset.dx, originOffset.dy);
    }
  }

  /// Clips the canvas for an ink feature to be painted on the [canvas].
  ///
  /// This should be called before painting ink features with [paintFeature]
  /// that do not use [paintInkCircle].
  ///
  /// The [clipCallback] is the callback used to obtain the [Rect] used for clipping
  /// the ink effect.
  ///
  /// If [clipCallback] is null, no clipping is performed on the ink circle.
  ///
  /// The [textDirection] is used by [customBorder] if it is non-null. This
  /// allows the [customBorder]'s path to be properly defined if the path was
  /// expressed in terms of "start" and "end" instead of "left" and "right".
  ///
  /// For examples on how the function is used, see [InkSparkle].
  void _clipCanvas({
    required Canvas canvas,
    required RectCallback clipCallback,
    TextDirection? textDirection,
    ShapeBorder? customBorder,
    BorderRadius borderRadius = BorderRadius.zero,
  }) {
    final Rect rect = clipCallback();
    if (customBorder != null) {
      canvas.clipPath(
          customBorder.getOuterPath(rect, textDirection: textDirection));
    } else if (borderRadius != BorderRadius.zero) {
      canvas.clipRRect(RRect.fromRectAndCorners(
        rect,
        topLeft: borderRadius.topLeft,
        topRight: borderRadius.topRight,
        bottomLeft: borderRadius.bottomLeft,
        bottomRight: borderRadius.bottomRight,
      ));
    } else {
      canvas.clipRect(rect);
    }
  }
}

class _InkSparkleFactory extends InteractiveInkFeatureFactory {
  const _InkSparkleFactory() : turbulenceSeed = null;

  const _InkSparkleFactory.constantTurbulenceSeed() : turbulenceSeed = 1337.0;

  static void initializeShader() {
    if (!_initCalled) {
      ui.FragmentProgram.fromAsset('shaders/ink_sparkle.frag').then(
        (ui.FragmentProgram program) {
          _program = program;
        },
      );
      _initCalled = true;
    }
  }

  static bool _initCalled = false;
  static ui.FragmentProgram? _program;

  final double? turbulenceSeed;

  @override
  InteractiveInkFeature create({
    required MaterialInkController controller,
    required RenderBox referenceBox,
    required ui.Offset position,
    required ui.Color color,
    required ui.TextDirection textDirection,
    bool containedInkWell = false,
    RectCallback? rectCallback,
    BorderRadius? borderRadius,
    ShapeBorder? customBorder,
    double? radius,
    ui.VoidCallback? onRemoved,
  }) {
    return InkSparkle(
      controller: controller,
      referenceBox: referenceBox,
      position: position,
      color: color,
      textDirection: textDirection,
      containedInkWell: containedInkWell,
      rectCallback: rectCallback,
      borderRadius: borderRadius,
      customBorder: customBorder,
      radius: radius,
      onRemoved: onRemoved,
      turbulenceSeed: turbulenceSeed,
    );
  }
}

RectCallback? _getClipCallback(
  RenderBox referenceBox,
  bool containedInkWell,
  RectCallback? rectCallback,
) {
  if (rectCallback != null) {
    assert(containedInkWell);
    return rectCallback;
  }
  if (containedInkWell) {
    return () => Offset.zero & referenceBox.size;
  }
  return null;
}

double _getTargetRadius(
  RenderBox referenceBox,
  bool containedInkWell,
  RectCallback? rectCallback,
  Offset position,
) {
  final Size size = rectCallback != null ? rectCallback().size : referenceBox.size;
  final double d1 = size.bottomRight(Offset.zero).distance;
  final double d2 = (size.topRight(Offset.zero) - size.bottomLeft(Offset.zero)).distance;
  return math.max(d1, d2) / 2.0;
}
