import 'package:flutter/material.dart';

class EcgPainter extends CustomPainter {
  final List<List<int>> newPoints;
  final List<List<int>> oldPoints;
  final int xDataCount;
  final List<double> yMaxList;
  final bool isInitPoints;

  EcgPainter({
    required this.newPoints,
    required this.oldPoints,
    required this.xDataCount,
    required this.yMaxList,
    required this.isInitPoints,
  });

  @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < 12; i++) {
      double y = (size.height / 6 * 2);
      bool isRight = i > 5;
      Size currentSize = Size(size.width / 2, y);

      if (i > 5) {
        currentSize = Size(size.width / 2, (y * (i - 5.5)));
      } else {
        currentSize = Size(size.width / 2, (y * (i + 0.5)));
      }

      try {
        if (newPoints.isNotEmpty && oldPoints.isEmpty) {
          drawPoints(
            canvas,
            currentSize,
            newPoints[i],
            yMaxList[i],
            isRight: isRight,
          );
        } else if (newPoints[i].isNotEmpty && oldPoints[i].isNotEmpty) {
          drawPointsWithFade(
            canvas,
            currentSize,
            oldPoints[i],
            yMaxList[i],
            offset: newPoints[i].length,
            isRight: isRight,
          );
          drawPoints(
            canvas,
            currentSize,
            newPoints[i],
            yMaxList[i],
            isRight: isRight,
          );
        } else if (isInitPoints) {
          allPointsDraw(
            canvas,
            currentSize,
            newPoints[i],
            yMaxList[i],
            isRight: isRight,
          );
        } else {
          drawPoints(
            canvas,
            currentSize,
            newPoints[i],
            yMaxList[i],
            isRight: isRight,
          );
        }
      } catch (err) {
        print("🥓$err");
      }
    }
  }

  void allPointsDraw(
    Canvas canvas,
    Size size,
    List<int> points,
    double yMax, {
    bool isRight = false,
    int offset = 0,
  }) {
    final paint = Paint()
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    final double xGridSize = size.width / xDataCount;
    final double yScale = size.height / 2 / yMax;
    final double yCenter = size.height / 2;
    final path = Path();

    for (int i = offset; i < points.length; i++) {
      if (i % 5 == 0) {
        final offsetX = i * xGridSize;
        final offsetY = -points[i] * yScale + yCenter;
        if (isRight) {
          if (i == offset) {
            path.moveTo(offsetX + size.width, offsetY);
          } else {
            path.lineTo(offsetX + size.width, offsetY);
          }
        } else {
          if (i == offset) {
            path.moveTo(offsetX - size.width * 5, offsetY);
          } else {
            path.lineTo(offsetX - size.width * 5, offsetY);
          }
        }
      }
    }
    canvas.drawPath(path, paint);
  }

  void drawPoints(
    Canvas canvas,
    Size size,
    List<int> points,
    double yMax, {
    bool isRight = false,
    int offset = 0,
  }) {
    final paint = Paint()
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    final double xGridSize = size.width / xDataCount;
    final double yScale = size.height / 2 / yMax;
    final double yCenter = size.height / 2;
    final path = Path();

    for (int i = offset; i < points.length; i++) {
      if (i % 5 == 0) {
        final offsetX = i * xGridSize;
        final offsetY = -points[i] * yScale + yCenter;
        if (isRight) {
          if (i == offset) {
            path.moveTo(offsetX + size.width, offsetY);
          } else {
            path.lineTo(offsetX + size.width, offsetY);
          }
        } else {
          if (i == offset) {
            path.moveTo(offsetX, offsetY);
          } else {
            path.lineTo(offsetX, offsetY);
          }
        }
      }
    }
    canvas.drawPath(path, paint);
  }

  void drawPointsWithFade(
    Canvas canvas,
    Size size,
    List<int> points,
    double yMax, {
    bool isRight = false,
    int offset = 0,
  }) {
    final paint = Paint()
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    final double xGridSize = size.width / xDataCount;
    final double yScale = size.height / 2 / yMax;
    final double yCenter = size.height / 2;
    final path = Path();

    for (int i = offset; i < points.length; i++) {
      if (i % 5 == 0) {
        final offsetX = i * xGridSize;
        final offsetY = -points[i] * yScale + yCenter;
        if (isRight) {
          if (i == offset) {
            path.moveTo(offsetX + size.width, offsetY);
          } else {
            path.lineTo(offsetX + size.width, offsetY);
          }
        } else {
          if (i == offset) {
            path.moveTo(offsetX, offsetY);
          } else {
            path.lineTo(offsetX, offsetY);
          }
        }
      }
    }

    double shaderStartX = offset * xGridSize;
    if (isRight) {
      shaderStartX = offset * xGridSize + size.width;
    }
    final double shaderWidth = 300 * xGridSize;
    Rect rect = Rect.fromLTWH(shaderStartX, 0, shaderWidth, size.height);
    paint.shader = const LinearGradient(
      begin: Alignment.centerLeft,
      end: Alignment.center,
      colors: [Colors.transparent, Colors.green],
    ).createShader(rect);

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
