import 'dart:math';

import 'package:flutter/material.dart';
import 'package:keyboard/utils/common_expand.dart';

import '../resource/assets.gen.dart';

class HeartFillAnimation extends StatefulWidget {
  const HeartFillAnimation({
    super.key,
    required this.fillProgress,
    this.width = 250.0,
  });

  final double fillProgress;
  final double width;

  @override
  State createState() => _HeartFillAnimationState();
}

class _HeartFillAnimationState extends State<HeartFillAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _waveController;

  @override
  void initState() {
    super.initState();
    _waveController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1000),
    )..repeat();
  }

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

  @override
  Widget build(BuildContext context) {
    final height = widget.width * 208 / 250;
    return Stack(
      alignment: Alignment.center,
      children: [
        AnimatedBuilder(
          animation: _waveController,
          builder: (context, child) {
            return CustomPaint(
              size: Size(widget.width, height),
              painter: HeartFillPainter(
                fillProgress: widget.fillProgress,
                waveOffset: -_waveController.value * 2 * pi,
              ),
            );
          },
        ),
        Image(
          image: Assets.images.bgHeartFill.provider(),
          width: widget.width,
          height: height,
          fit: BoxFit.fill,
        ),
      ],
    );
  }
}

class HeartFillPainter extends CustomPainter {
  HeartFillPainter({required this.fillProgress, required this.waveOffset});

  final double fillProgress;
  final double waveOffset;

  static final _originalHeartPath = _createOriginalHeartPath();

  static Path _createOriginalHeartPath() {
    final path = Path();
    path.moveTo(182.981, 0);
    path.cubicTo(158.332, 0, 136.822, 13.4803, 125.435, 33.4817);
    path.cubicTo(125.07, 34.1387, 124.121, 34.1387, 123.756, 33.4817);
    path.cubicTo(112.344, 13.4803, 90.8336, 0, 66.1847, 0);
    path.cubicTo(29.6371, 0, 0, 29.6371, 0, 66.1847);
    path.cubicTo(0, 134.504, 85.9676, 188.719, 115.078, 205.119);
    path.cubicTo(121.041, 208.478, 128.123, 208.473, 134.081, 205.106);
    path.cubicTo(163.184, 188.66, 249.166, 134.307, 249.166, 66.1847);
    path.cubicTo(249.166, 29.6371, 219.529, 0, 182.981, 0);
    return path;
  }

  @override
  void paint(Canvas canvas, Size size) {
    // 应用缩放矩阵
    final scaleX = size.width / 250;
    final scaleY = size.height / 208;
    final matrix = Matrix4.identity()..scale(scaleX, scaleY);

    // 创建缩放后的爱心路径
    final heartPath = _originalHeartPath.transform(matrix.storage);

    // 设置裁剪区域
    canvas.save();
    canvas.clipPath(heartPath);

    // 计算填充高度
    final fillHeight = size.height * (1 - fillProgress);
    final fillRect = Rect.fromLTRB(0, fillHeight, size.width, size.height);

    // 绘制次级波浪
    final subWavePath = _createWavePath(
      fillHeight,
      size,
      offset: -pi / 5,
      amplitude: 15,
      frequency: 0.02,
    );
    canvas.drawPath(
      subWavePath,
      Paint()
        ..shader = LinearGradient(
          colors: ["#66FFB9D5".color, "#66FF219B".color],
        ).createShader(fillRect),
    );

    // 绘制主波浪
    final wavePath = _createWavePath(fillHeight, size);
    canvas.drawPath(
      wavePath,
      Paint()
        ..shader = LinearGradient(
          colors: ["#FF458C".color, "#FF74BC".color],
        ).createShader(fillRect),
    );

    canvas.restore();
  }

  Path _createWavePath(
    double fillHeight,
    Size size, {
    double offset = 0,
    double amplitude = 10.0,
    double frequency = 0.03,
  }) {
    final path = Path()..moveTo(0, fillHeight);

    for (double x = 0; x <= size.width; x++) {
      final y =
          fillHeight + sin(x * frequency + waveOffset + offset) * amplitude;
      path.lineTo(x, y);
    }

    path
      ..lineTo(size.width, size.height)
      ..lineTo(0, size.height)
      ..close();
    return path;
  }

  @override
  bool shouldRepaint(HeartFillPainter oldDelegate) {
    return fillProgress != oldDelegate.fillProgress ||
        waveOffset != oldDelegate.waveOffset;
  }
}
