// Copyright 2013 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:html' as html;
import 'dart:math' as math;
import 'dart:typed_data';

import 'package:ui/ui.dart' as ui;

import '../../browser_detection.dart';
import '../../util.dart';
import '../../validators.dart';
import '../../vector_math.dart';
import '../offscreen_canvas.dart';
import '../path/path_utils.dart';
import '../render_vertices.dart';
import 'normalized_gradient.dart';
import 'shader_builder.dart';
import 'vertex_shaders.dart';
import 'webgl_context.dart';

const double kFltEpsilon = 1.19209290E-07; // == 1 / (2 ^ 23)
const double kFltEpsilonSquared = 1.19209290E-07 * 1.19209290E-07;

abstract class EngineGradient implements ui.Gradient {
  /// Hidden constructor to prevent subclassing.
  EngineGradient._();

  /// Creates a fill style to be used in painting.
  Object createPaintStyle(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density);

  /// Creates a CanvasImageSource to paint gradient.
  Object createImageBitmap(
      ui.Rect? shaderBounds, double density, bool createDataUrl);
}

class GradientSweep extends EngineGradient {
  GradientSweep(this.center, this.colors, this.colorStops, this.tileMode,
      this.startAngle, this.endAngle, this.matrix4)
      : assert(offsetIsValid(center)),
        assert(colors != null), // ignore: unnecessary_null_comparison
        assert(tileMode != null), // ignore: unnecessary_null_comparison
        assert(startAngle != null), // ignore: unnecessary_null_comparison
        assert(endAngle != null), // ignore: unnecessary_null_comparison
        assert(startAngle < endAngle),
        super._() {
    validateColorStops(colors, colorStops);
  }

  @override
  Object createImageBitmap(
      ui.Rect? shaderBounds, double density, bool createDataUrl) {
    assert(shaderBounds != null);
    final int widthInPixels = shaderBounds!.width.ceil();
    final int heightInPixels = shaderBounds.height.ceil();
    assert(widthInPixels > 0 && heightInPixels > 0);

    initWebGl();
    // Render gradient into a bitmap and create a canvas pattern.
    final OffScreenCanvas offScreenCanvas =
        OffScreenCanvas(widthInPixels, heightInPixels);
    final GlContext gl = GlContext(offScreenCanvas);
    gl.setViewportSize(widthInPixels, heightInPixels);

    final NormalizedGradient normalizedGradient =
        NormalizedGradient(colors, stops: colorStops);

    final GlProgram glProgram = gl.cacheProgram(VertexShaders.writeBaseVertexShader(),
        _createSweepFragmentShader(normalizedGradient, tileMode));
    gl.useProgram(glProgram);

    final Object tileOffset =
        gl.getUniformLocation(glProgram.program, 'u_tile_offset');
    final double centerX = (center.dx - shaderBounds.left) / (shaderBounds.width);
    final double centerY = (center.dy - shaderBounds.top) / (shaderBounds.height);
    gl.setUniform2f(tileOffset, 2 * (shaderBounds.width * (centerX - 0.5)),
        2 * (shaderBounds.height * (centerY - 0.5)));
    final Object angleRange = gl.getUniformLocation(glProgram.program, 'angle_range');
    gl.setUniform2f(angleRange, startAngle, endAngle);
    normalizedGradient.setupUniforms(gl, glProgram);
    if (matrix4 != null) {
      final Object gradientMatrix =
          gl.getUniformLocation(glProgram.program, 'm_gradient');
      gl.setUniformMatrix4fv(gradientMatrix, false, matrix4!);
    }
    if (createDataUrl) {
      return glRenderer!.drawRectToImageUrl(
          ui.Rect.fromLTWH(0, 0, shaderBounds.width, shaderBounds.height),
          gl,
          glProgram,
          normalizedGradient,
          widthInPixels,
          heightInPixels);
    } else {
      return glRenderer!.drawRect(
          ui.Rect.fromLTWH(0, 0, shaderBounds.width, shaderBounds.height),
          gl,
          glProgram,
          normalizedGradient,
          widthInPixels,
          heightInPixels)!;
    }
  }

  @override
  Object createPaintStyle(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    final Object imageBitmap = createImageBitmap(shaderBounds, density, false);
    return ctx!.createPattern(imageBitmap, 'no-repeat')!;
  }

  String _createSweepFragmentShader(
      NormalizedGradient gradient, ui.TileMode tileMode) {
    final ShaderBuilder builder = ShaderBuilder.fragment(webGLVersion);
    builder.floatPrecision = ShaderPrecision.kMedium;
    builder.addIn(ShaderType.kVec4, name: 'v_color');
    builder.addUniform(ShaderType.kVec2, name: 'u_resolution');
    builder.addUniform(ShaderType.kVec2, name: 'u_tile_offset');
    builder.addUniform(ShaderType.kVec2, name: 'angle_range');
    builder.addUniform(ShaderType.kMat4, name: 'm_gradient');
    final ShaderDeclaration fragColor = builder.fragmentColor;
    final ShaderMethod method = builder.addMethod('main');
    // Sweep gradient
    method.addStatement('vec2 center = 0.5 * (u_resolution + u_tile_offset);');
    method.addStatement(
        'vec4 localCoord = vec4(gl_FragCoord.x - center.x, center.y - gl_FragCoord.y, 0, 1) * m_gradient;');
    method.addStatement(
        'float angle = atan(-localCoord.y, -localCoord.x) + ${math.pi};');
    method.addStatement('float sweep = angle_range.y - angle_range.x;');
    method.addStatement('angle = (angle - angle_range.x) / sweep;');
    method.addStatement(''
        'float st = angle;');

    final String probeName =
        _writeSharedGradientShader(builder, method, gradient, tileMode);
    method.addStatement('${fragColor.name} = $probeName * scale + bias;');

    final String shader = builder.build();
    return shader;
  }

  final ui.Offset center;
  final List<ui.Color> colors;
  final List<double>? colorStops;
  final ui.TileMode tileMode;
  final double startAngle;
  final double endAngle;
  final Float32List? matrix4;
}

class GradientLinear extends EngineGradient {
  GradientLinear(
    this.from,
    this.to,
    this.colors,
    this.colorStops,
    this.tileMode,
    Float32List? matrix,
  )   : assert(offsetIsValid(from)),
        assert(offsetIsValid(to)),
        assert(colors != null), // ignore: unnecessary_null_comparison
        assert(tileMode != null), // ignore: unnecessary_null_comparison
        matrix4 = matrix == null ? null : FastMatrix32(matrix),
        super._() {
    if (assertionsEnabled) {
      validateColorStops(colors, colorStops);
    }
  }

  final ui.Offset from;
  final ui.Offset to;
  final List<ui.Color> colors;
  final List<double>? colorStops;
  final ui.TileMode tileMode;
  final FastMatrix32? matrix4;

  @override
  Object createPaintStyle(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    if (tileMode == ui.TileMode.clamp || tileMode == ui.TileMode.decal) {
      return _createCanvasGradient(ctx, shaderBounds, density);
    } else {
      return _createGlGradient(ctx, shaderBounds, density);
    }
  }

  html.CanvasGradient _createCanvasGradient(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    final FastMatrix32? matrix4 = this.matrix4;
    html.CanvasGradient gradient;
    final double offsetX = shaderBounds!.left;
    final double offsetY = shaderBounds.top;
    if (matrix4 != null) {
      // The matrix is relative to shaderBounds so we shift center by
      // shaderBounds top-left origin.
      final double centerX = (from.dx + to.dx) / 2.0 - shaderBounds.left;
      final double centerY = (from.dy + to.dy) / 2.0 - shaderBounds.top;

      matrix4.transform(from.dx - centerX, from.dy - centerY);
      final double fromX = matrix4.transformedX + centerX;
      final double fromY = matrix4.transformedY + centerY;
      matrix4.transform(to.dx - centerX, to.dy - centerY);
      gradient = ctx!.createLinearGradient(
          fromX - offsetX,
          fromY - offsetY,
          matrix4.transformedX + centerX - offsetX,
          matrix4.transformedY + centerY - offsetY);
    } else {
      gradient = ctx!.createLinearGradient(from.dx - offsetX, from.dy - offsetY,
          to.dx - offsetX, to.dy - offsetY);
    }
    _addColorStopsToCanvasGradient(
        gradient, colors, colorStops, tileMode == ui.TileMode.decal);
    return gradient;
  }

  @override
  Object createImageBitmap(
      ui.Rect? shaderBounds, double density, bool createDataUrl) {
    assert(shaderBounds != null);
    final int widthInPixels = shaderBounds!.width.ceil();
    final int heightInPixels = shaderBounds.height.ceil();
    assert(widthInPixels > 0 && heightInPixels > 0);
    initWebGl();
    // Render gradient into a bitmap and create a canvas pattern.
    final OffScreenCanvas offScreenCanvas =
        OffScreenCanvas(widthInPixels, heightInPixels);
    final GlContext gl = GlContext(offScreenCanvas);
    gl.setViewportSize(widthInPixels, heightInPixels);

    final NormalizedGradient normalizedGradient =
        NormalizedGradient(colors, stops: colorStops);

    final GlProgram glProgram = gl.cacheProgram(VertexShaders.writeBaseVertexShader(),
        _createLinearFragmentShader(normalizedGradient, tileMode));
    gl.useProgram(glProgram);

    /// When creating an image to apply to a dom element, render
    /// contents at 0,0 and adjust gradient vector for shaderBounds.
    final bool translateToOrigin = createDataUrl;

    if (translateToOrigin) {
      shaderBounds = shaderBounds.translate(-shaderBounds.left, -shaderBounds.top);
    }

    // Setup from/to uniforms.
    //
    // From/to is relative to shaderBounds.
    //
    // To compute t value between 0..1 for any point on the screen,
    // we need to use from,to point pair to construct a matrix that will
    // take any fragment coordinate and transform it to a t value.
    //
    // We compute the matrix by:
    // 1- Shift from,to vector to origin.
    // 2- Rotate the vector to align with x axis.
    // 3- Scale it to unit vector.
    final double fromX = from.dx;
    final double fromY = from.dy;
    final double toX = to.dx;
    final double toY = to.dy;

    final double dx = toX - fromX;
    final double dy = toY - fromY;
    final double length = math.sqrt(dx * dx + dy * dy);
    // sin(theta) = dy / length.
    // cos(theta) = dx / length.
    // Flip dy for gl flip.
    final double sinVal = length < kFltEpsilon ? 0 : -dy / length;
    final double cosVal = length < kFltEpsilon ? 1 : dx / length;
    // If tile mode is repeated we need to shift the center of from->to
    // vector to the center of shader bounds.
    final bool isRepeated = tileMode != ui.TileMode.clamp;
    final double originX = isRepeated
        ? (shaderBounds.width / 2)
        : (fromX + toX) / 2.0 - shaderBounds.left;
    final double originY = isRepeated
        ? (shaderBounds.height / 2)
        : (fromY + toY) / 2.0 - shaderBounds.top;

    final Matrix4 originTranslation =
        Matrix4.translationValues(-originX, -originY, 0);
    // Rotate around Z axis.
    final Matrix4 rotationZ = Matrix4.identity();
    final Float32List storage = rotationZ.storage;
    storage[0] = cosVal;
    // Sign is flipped since gl coordinate system is flipped around y axis.
    storage[1] = sinVal;
    storage[4] = -sinVal;
    storage[5] = cosVal;
    final Matrix4 gradientTransform = Matrix4.identity();
    // We compute location based on gl_FragCoord to center distance which
    // returns 0.0 at center. To make sure we align center of gradient to this
    // point, we shift by 0.5 to get st value for center of gradient.
    if (tileMode != ui.TileMode.repeated) {
      gradientTransform.translate(0.5, 0);
    }
    if (length > kFltEpsilon) {
      gradientTransform.scale(1.0 / length);
    }
    if (matrix4 != null) {
      // Flutter GradientTransform is defined in shaderBounds coordinate system
      // with flipped y axis.
      // We flip y axis, translate to center, multiply matrix and translate
      // and flip back so it is applied correctly.
      final Matrix4 m4 = Matrix4.fromFloat32List(matrix4!.matrix);
      gradientTransform.scale(1, -1);
      gradientTransform.translate(
          -shaderBounds.center.dx, -shaderBounds.center.dy);
      gradientTransform.multiply(m4);
      gradientTransform.translate(
          shaderBounds.center.dx, shaderBounds.center.dy);
      gradientTransform.scale(1, -1);
    }

    gradientTransform.multiply(rotationZ);
    gradientTransform.multiply(originTranslation);
    // Setup gradient uniforms for t search.
    normalizedGradient.setupUniforms(gl, glProgram);
    // Setup matrix transform uniform.
    final Object gradientMatrix =
        gl.getUniformLocation(glProgram.program, 'm_gradient');
    gl.setUniformMatrix4fv(gradientMatrix, false, gradientTransform.storage);

    final Object uRes = gl.getUniformLocation(glProgram.program, 'u_resolution');
    gl.setUniform2f(uRes, widthInPixels.toDouble(), heightInPixels.toDouble());

    if (createDataUrl) {
      return glRenderer!.drawRectToImageUrl(
        ui.Rect.fromLTWH(0, 0, shaderBounds.width,
            shaderBounds.height) /* !! shaderBounds */,
        gl,
        glProgram,
        normalizedGradient,
        widthInPixels,
        heightInPixels,
      );
    } else {
      return glRenderer!.drawRect(
        ui.Rect.fromLTWH(0, 0, shaderBounds.width,
            shaderBounds.height) /* !! shaderBounds */,
        gl,
        glProgram,
        normalizedGradient,
        widthInPixels,
        heightInPixels,
      )!;
    }
  }

  /// Creates a linear gradient with tiling repeat or mirror.
  html.CanvasPattern _createGlGradient(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    final Object imageBitmap = createImageBitmap(shaderBounds, density, false);
    return ctx!.createPattern(imageBitmap, 'no-repeat')!;
  }

  String _createLinearFragmentShader(
      NormalizedGradient gradient, ui.TileMode tileMode) {
    final ShaderBuilder builder = ShaderBuilder.fragment(webGLVersion);
    builder.floatPrecision = ShaderPrecision.kMedium;
    builder.addIn(ShaderType.kVec4, name: 'v_color');
    builder.addUniform(ShaderType.kVec2, name: 'u_resolution');
    builder.addUniform(ShaderType.kMat4, name: 'm_gradient');
    final ShaderDeclaration fragColor = builder.fragmentColor;
    final ShaderMethod method = builder.addMethod('main');
    // Linear gradient.
    // Multiply with m_gradient transform to convert from fragment coordinate to
    // distance on the from-to line.
    method.addStatement('vec4 localCoord = m_gradient * vec4(gl_FragCoord.x, '
        'u_resolution.y - gl_FragCoord.y, 0, 1);');
    method.addStatement('float st = localCoord.x;');
    final String probeName =
        _writeSharedGradientShader(builder, method, gradient, tileMode);
    method.addStatement('${fragColor.name} = $probeName * scale + bias;');
    final String shader = builder.build();
    return shader;
  }
}

void _addColorStopsToCanvasGradient(html.CanvasGradient gradient,
    List<ui.Color> colors, List<double>? colorStops, bool isDecal) {
  double scale, offset;
  if (isDecal) {
    scale = 0.999;
    offset = (1.0 - scale) / 2.0;
    gradient.addColorStop(0, '#00000000');
  } else {
    scale = 1.0;
    offset = 0.0;
  }
  if (colorStops == null) {
    assert(colors.length == 2);
    gradient.addColorStop(offset, colorToCssString(colors[0])!);
    gradient.addColorStop(1 - offset, colorToCssString(colors[1])!);
  } else {
    for (int i = 0; i < colors.length; i++) {
      final double colorStop = colorStops[i].clamp(0.0, 1.0);
      gradient.addColorStop(
          colorStop * scale + offset, colorToCssString(colors[i])!);
    }
  }
  if (isDecal) {
    gradient.addColorStop(1, '#00000000');
  }
}

/// Writes shader code to map fragment value to gradient color.
///
/// Returns name of gradient treshold variable to use to compute color.
String _writeSharedGradientShader(ShaderBuilder builder, ShaderMethod method,
    NormalizedGradient gradient, ui.TileMode tileMode) {
  method.addStatement('vec4 bias;');
  method.addStatement('vec4 scale;');
  // Write uniforms for each threshold, bias and scale.
  for (int i = 0; i < (gradient.thresholdCount - 1) ~/ 4 + 1; i++) {
    builder.addUniform(ShaderType.kVec4, name: 'threshold_$i');
  }
  for (int i = 0; i < gradient.thresholdCount; i++) {
    builder.addUniform(ShaderType.kVec4, name: 'bias_$i');
    builder.addUniform(ShaderType.kVec4, name: 'scale_$i');
  }

  // Use st variable name if clamped or decaled, otherwise write code to compute
  // tiled_st.
  String probeName = 'st';
  switch (tileMode) {
    case ui.TileMode.clamp:
      method.addStatement('float tiled_st = clamp(st, 0.0, 1.0);');
      probeName = 'tiled_st';
      break;
    case ui.TileMode.decal:
      break;
    case ui.TileMode.repeated:
      // st represents our distance from center. Flutter maps the center to
      // center of gradient ramp so we need to add 0.5 to make sure repeated
      // pattern center is at origin.
      method.addStatement('float tiled_st = fract(st);');
      probeName = 'tiled_st';
      break;
    case ui.TileMode.mirror:
      method.addStatement('float t_1 = (st - 1.0);');
      method.addStatement(
          'float tiled_st = abs((t_1 - 2.0 * floor(t_1 * 0.5)) - 1.0);');
      probeName = 'tiled_st';
      break;
  }
  writeUnrolledBinarySearch(method, 0, gradient.thresholdCount - 1,
      probe: probeName,
      sourcePrefix: 'threshold',
      biasName: 'bias',
      scaleName: 'scale');
  return probeName;
}

class GradientRadial extends EngineGradient {
  GradientRadial(this.center, this.radius, this.colors, this.colorStops,
      this.tileMode, this.matrix4)
      : super._();

  final ui.Offset center;
  final double radius;
  final List<ui.Color> colors;
  final List<double>? colorStops;
  final ui.TileMode tileMode;
  final Float32List? matrix4;

  @override
  Object createPaintStyle(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    if (tileMode == ui.TileMode.clamp || tileMode == ui.TileMode.decal) {
      return _createCanvasGradient(ctx, shaderBounds, density);
    } else {
      return _createGlGradient(ctx, shaderBounds, density);
    }
  }

  Object _createCanvasGradient(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    final double offsetX = shaderBounds!.left;
    final double offsetY = shaderBounds.top;
    final html.CanvasGradient gradient = ctx!.createRadialGradient(
        center.dx - offsetX,
        center.dy - offsetY,
        0,
        center.dx - offsetX,
        center.dy - offsetY,
        radius);
    _addColorStopsToCanvasGradient(
        gradient, colors, colorStops, tileMode == ui.TileMode.decal);
    return gradient;
  }

  @override
  Object createImageBitmap(
      ui.Rect? shaderBounds, double density, bool createDataUrl) {
    assert(shaderBounds != null);
    final int widthInPixels = shaderBounds!.width.ceil();
    final int heightInPixels = shaderBounds.height.ceil();
    assert(widthInPixels > 0 && heightInPixels > 0);

    initWebGl();
    // Render gradient into a bitmap and create a canvas pattern.
    final OffScreenCanvas offScreenCanvas =
        OffScreenCanvas(widthInPixels, heightInPixels);
    final GlContext gl = GlContext(offScreenCanvas);
    gl.setViewportSize(widthInPixels, heightInPixels);

    final NormalizedGradient normalizedGradient =
        NormalizedGradient(colors, stops: colorStops);

    final GlProgram glProgram = gl.cacheProgram(
        VertexShaders.writeBaseVertexShader(),
        _createRadialFragmentShader(
            normalizedGradient, shaderBounds, tileMode));
    gl.useProgram(glProgram);

    final Object tileOffset =
        gl.getUniformLocation(glProgram.program, 'u_tile_offset');
    final double centerX = (center.dx - shaderBounds.left) / (shaderBounds.width);
    final double centerY = (center.dy - shaderBounds.top) / (shaderBounds.height);
    gl.setUniform2f(tileOffset, 2 * (shaderBounds.width * (centerX - 0.5)),
        2 * (shaderBounds.height * (centerY - 0.5)));
    final Object radiusUniform = gl.getUniformLocation(glProgram.program, 'u_radius');
    gl.setUniform1f(radiusUniform, radius);
    normalizedGradient.setupUniforms(gl, glProgram);

    final Object gradientMatrix =
        gl.getUniformLocation(glProgram.program, 'm_gradient');
    gl.setUniformMatrix4fv(gradientMatrix, false,
        matrix4 == null ? Matrix4.identity().storage : matrix4!);

    if (createDataUrl) {
      return glRenderer!.drawRectToImageUrl(
          ui.Rect.fromLTWH(0, 0, shaderBounds.width, shaderBounds.height),
          gl,
          glProgram,
          normalizedGradient,
          widthInPixels,
          heightInPixels);
    } else {
      return glRenderer!.drawRect(
          ui.Rect.fromLTWH(0, 0, shaderBounds.width, shaderBounds.height),
          gl,
          glProgram,
          normalizedGradient,
          widthInPixels,
          heightInPixels)!;
    }
  }

  /// Creates a radial gradient with tiling repeat or mirror.
  html.CanvasPattern _createGlGradient(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    final Object imageBitmap = createImageBitmap(shaderBounds, density, false);
    return ctx!.createPattern(imageBitmap, 'no-repeat')!;
  }

  String _createRadialFragmentShader(
      NormalizedGradient gradient, ui.Rect shaderBounds, ui.TileMode tileMode) {
    final ShaderBuilder builder = ShaderBuilder.fragment(webGLVersion);
    builder.floatPrecision = ShaderPrecision.kMedium;
    builder.addIn(ShaderType.kVec4, name: 'v_color');
    builder.addUniform(ShaderType.kVec2, name: 'u_resolution');
    builder.addUniform(ShaderType.kVec2, name: 'u_tile_offset');
    builder.addUniform(ShaderType.kFloat, name: 'u_radius');
    builder.addUniform(ShaderType.kMat4, name: 'm_gradient');
    final ShaderDeclaration fragColor = builder.fragmentColor;
    final ShaderMethod method = builder.addMethod('main');
    // Sweep gradient
    method.addStatement('vec2 center = 0.5 * (u_resolution + u_tile_offset);');
    method.addStatement(
        'vec4 localCoord = vec4(gl_FragCoord.x - center.x, center.y - gl_FragCoord.y, 0, 1) * m_gradient;');
    method.addStatement('float dist = length(localCoord);');
    method.addStatement(''
        'float st = abs(dist / u_radius);');
    final String probeName =
        _writeSharedGradientShader(builder, method, gradient, tileMode);
    method.addStatement('${fragColor.name} = $probeName * scale + bias;');
    final String shader = builder.build();
    return shader;
  }
}

/// TODO: Implement focal https://github.com/flutter/flutter/issues/76643.
class GradientConical extends GradientRadial {
  GradientConical(
      this.focal,
      this.focalRadius,
      ui.Offset center,
      double radius,
      List<ui.Color> colors,
      List<double>? colorStops,
      ui.TileMode tileMode,
      Float32List? matrix4)
      : super(center, radius, colors, colorStops, tileMode, matrix4);

  final ui.Offset focal;
  final double focalRadius;

  @override
  Object createPaintStyle(html.CanvasRenderingContext2D? ctx,
      ui.Rect? shaderBounds, double density) {
    if ((tileMode == ui.TileMode.clamp || tileMode == ui.TileMode.decal) &&
        focalRadius == 0.0 &&
        focal == const ui.Offset(0, 0)) {
      return _createCanvasGradient(ctx, shaderBounds, density);
    } else {
      initWebGl();
      return _createGlGradient(ctx, shaderBounds, density);
    }
  }

  @override
  String _createRadialFragmentShader(
      NormalizedGradient gradient, ui.Rect shaderBounds, ui.TileMode tileMode) {
    /// If distance between centers is nearly zero we can pretend we're radial
    /// to prevent divide by zero in computing gradient.
    final double centerDistanceX = center.dx - focal.dx;
    final double centerDistanceY = center.dy - focal.dy;
    final double centerDistanceSq =
        centerDistanceX * centerDistanceX + centerDistanceY * centerDistanceY;
    if (centerDistanceSq < kFltEpsilonSquared) {
      return super
          ._createRadialFragmentShader(gradient, shaderBounds, tileMode);
    }
    final double centerDistance = math.sqrt(centerDistanceSq);
    double r0 = focalRadius / centerDistance;
    double r1 = radius / centerDistance;
    double fFocalX = r0 / (r0 - r1);

    if ((fFocalX - 1).abs() < SPath.scalarNearlyZero) {
      // swap r0, r1
      final double temp = r0;
      r0 = r1;
      r1 = temp;
      fFocalX = 0.0; // because r0 is now 0
    }

    final ShaderBuilder builder = ShaderBuilder.fragment(webGLVersion);
    builder.floatPrecision = ShaderPrecision.kMedium;
    builder.addIn(ShaderType.kVec4, name: 'v_color');
    builder.addUniform(ShaderType.kVec2, name: 'u_resolution');
    builder.addUniform(ShaderType.kVec2, name: 'u_tile_offset');
    builder.addUniform(ShaderType.kFloat, name: 'u_radius');
    builder.addUniform(ShaderType.kMat4, name: 'm_gradient');
    final ShaderDeclaration fragColor = builder.fragmentColor;
    final ShaderMethod method = builder.addMethod('main');
    // Sweep gradient
    method.addStatement('vec2 center = 0.5 * (u_resolution + u_tile_offset);');
    method.addStatement(
        'vec4 localCoord = vec4(gl_FragCoord.x - center.x, center.y - gl_FragCoord.y, 0, 1) * m_gradient;');
    method.addStatement('float dist = length(localCoord);');
    final String f = (focalRadius /
            (math.min(shaderBounds.width, shaderBounds.height) / 2.0))
        .toStringAsPrecision(8);
    method.addStatement(focalRadius == 0.0
        ? 'float st = dist / u_radius;'
        : 'float st = ((dist / u_radius) - $f) / (1.0 - $f);');
    if (tileMode == ui.TileMode.clamp) {
      method.addStatement('if (st < 0.0) { st = -1.0; }');
    }
    final String probeName =
        _writeSharedGradientShader(builder, method, gradient, tileMode);
    method.addStatement('${fragColor.name} = $probeName * scale + bias;');
    return builder.build();
  }
}

/// Backend implementation of [ui.ImageFilter].
///
/// Currently only `blur` and `matrix` are supported.
abstract class EngineImageFilter implements ui.ImageFilter {
  factory EngineImageFilter.blur({
    required double sigmaX,
    required double sigmaY,
    required ui.TileMode tileMode,
  }) = _BlurEngineImageFilter;

  factory EngineImageFilter.matrix({
    required Float64List matrix,
    required ui.FilterQuality filterQuality,
  }) = _MatrixEngineImageFilter;

  EngineImageFilter._();

  String get filterAttribute => '';
  String get transformAttribute => '';
}

class _BlurEngineImageFilter extends EngineImageFilter {
  _BlurEngineImageFilter({ this.sigmaX = 0.0, this.sigmaY = 0.0, this.tileMode = ui.TileMode.clamp }) : super._();

  final double sigmaX;
  final double sigmaY;
  final ui.TileMode tileMode;

  // TODO(flutter_web): implement TileMode.
  @override
  String get filterAttribute => blurSigmasToCssString(sigmaX, sigmaY);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is _BlurEngineImageFilter &&
        other.tileMode == tileMode &&
        other.sigmaX == sigmaX &&
        other.sigmaY == sigmaY;
  }

  @override
  int get hashCode => ui.hashValues(sigmaX, sigmaY, tileMode);

  @override
  String toString() {
    return 'ImageFilter.blur($sigmaX, $sigmaY, $tileMode)';
  }
}

class _MatrixEngineImageFilter extends EngineImageFilter {
  _MatrixEngineImageFilter({ required Float64List matrix, required this.filterQuality })
      : webMatrix = Float64List.fromList(matrix),
        super._();

  final Float64List webMatrix;
  final ui.FilterQuality filterQuality;

  // TODO(flutter_web): implement FilterQuality.
  @override
  String get transformAttribute => float64ListToCssTransform(webMatrix);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is _MatrixEngineImageFilter
        && other.filterQuality == filterQuality
        && listEquals<double>(other.webMatrix, webMatrix);
  }

  @override
  int get hashCode => ui.hashValues(ui.hashList(webMatrix), filterQuality);

  @override
  String toString() {
    return 'ImageFilter.matrix($webMatrix, $filterQuality)';
  }
}
