import 'dart:async';
import 'dart:convert';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:ui' as ui;
import 'index.dart';

class TwelveEcgViewController extends GetxController {
  TwelveEcgViewController({
    required this.initPoints,
  });

  List<int> initPoints;

  /// 每秒的数据量
  static int get dataPerSecond => 200;

  /// 更新帧率
  static int updateFrameRate = 15;

  /// 更新周期
  static int updatePeriod = 1000 ~/ updateFrameRate;

  /// 画布时间跨度（秒）
  int get timeSpan => 5;

  /// 横坐标数据量
  int get xDataCount => (dataPerSecond * timeSpan).toInt();

  /// 所有心电数据
  List<int> allPoints = [];

  /// 需绘制的新数据
  List<List<int>> newPointsToDraw = [
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    []
  ];

  /// 需绘制的历史数据
  List<List<int>> oldPointsToDraw = [
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    []
  ];
  List<double> yMaxList = [
    1000,
    5000,
    2000,
    8000,
    8000,
    8000,
    1000,
    8000,
    8000,
    8000,
    8000,
    8000,
  ];

  /// 启动时时间戳
  int startTime = DateTime.now().millisecondsSinceEpoch;

  /// 当前数据位（根据时间戳计算）
  int currentDataIndex = 0;

  /// 数据刷新定时器
  Timer timer = Timer(Duration.zero, () {});

  /// 发生错误时暂停了
  bool isPaused = false;

  /// 是否有初始值
  bool isInitPoints = false;

  /// 读取到数据的回调
  void addData(List<int> data) {
    if (allPoints.isEmpty) {
      startTime = DateTime.now().millisecondsSinceEpoch;
      _startTimer();
    }
    allPoints.addAll(data);
    if (isPaused) {
      isPaused = false;
      _startTimer();
    }
  }

  /// 打开全屏心电图弹窗
  void openFullScreenDialog() {
    Get.dialog(
      const FullScreenEcgDataDialog(),
    );
  }

  // 重置
  void reset() {
    timer.cancel();
    isPaused = false;
    allPoints = [];
    newPointsToDraw = [[], [], [], [], [], [], [], [], [], [], [], []];
    oldPointsToDraw = [[], [], [], [], [], [], [], [], [], [], [], []];
    startTime = DateTime.now().millisecondsSinceEpoch;
    currentDataIndex = 0;
    update(['twelve_ecg_view']);
  }

  /// 开始采集
  void startSave() {
    timer.cancel();
    allPoints = [];
    startTime = DateTime.now().millisecondsSinceEpoch;
    currentDataIndex = 0;
  }

  /// 因为实时数据请求量太大，就是延迟俩秒数据
  void updateTwelveEcgView() {
    initPoints = allPoints;
    update(['twelve_ecg_view']);
  }

  /// 获取完整心电图的base64（带base64头）
  Future<String> getFullDataImageBase64() async {
    final painter = EcgPainterForAll(
      allPoints: allPoints,
      yMaxList: yMaxList,
    );
    final bgPainter = GridBackgroundPainterForAll();
    const size = Size(5000, 650);
    // 使用离屏Canvas绘制
    final Uint8List? bytes =
        await _capturePainterToImage(painter, bgPainter, size);
    if (bytes == null) {
      return "";
    } else {
      return _convertToBase64Url(bytes);
    }
  }

  /// 开启定时器，每隔一定时间添加一次数据，并且更新UI
  void _startTimer() {
    timer = Timer.periodic(
      Duration(milliseconds: updatePeriod),
      (timer) {
        // print("timer: ${timer.tick}");

        _updateData();
      },
    );
  }

  List<List<int>> separateLines(List<int> array) {
    // 将数据拆分成12条线的数据
    List<List<int>> lines = List.generate(12, (_) => []);
    for (int i = 0; i < array.length; i++) {
      int lineIndex = i % 12; // 计算当前数据所属的线的索引
      lines[lineIndex].add(array[i]); // 将数据添加到对应的线中
    }
    return lines;
  }

  /// 每帧更新数据
  void _updateData() {
    // 计算当前数据位
    currentDataIndex = (DateTime.now().millisecondsSinceEpoch - startTime) ~/
        (1000 ~/ dataPerSecond);

    /// 需显示的数据量 不能为0
    int needDataCount = (currentDataIndex % xDataCount) == 0
        ? 25
        : currentDataIndex % xDataCount;

    /// 当前周期数
    int currentPeriod = currentDataIndex ~/ xDataCount;
    // 计算新数据
    try {
      for (int i = 0; i < 12; i++) {
        newPointsToDraw[i] = separateLines(allPoints)[i].sublist(
          currentDataIndex - needDataCount,
          currentDataIndex,
        );
        if (currentPeriod > 0) {
          oldPointsToDraw[i] = separateLines(allPoints)[i].sublist(
            (currentPeriod - 1) * xDataCount,
            currentPeriod * xDataCount,
          );
        }
      }

      if (currentDataIndex > dataPerSecond * 30) {
        startSave();
      }
      print(
          "update newPointsToDraw: $currentDataIndex $needDataCount ${newPointsToDraw[0].length} --currentPeriod $currentPeriod");
    } catch (e) {
      print("allPoints.length${allPoints.length}");
      timer.cancel();
      isPaused = true;
    }
    update(['twelve_ecg_view']);
  }

  /// 将字节数组转换为base64
  String _convertToBase64Url(Uint8List imageData) {
    String base64Image = base64Encode(imageData);
    String base64Url = base64Image;
    return base64Url;
  }

  /// 将CustomPainter绘制的内容转换为图片
  Future<Uint8List?> _capturePainterToImage(
      CustomPainter painter, CustomPainter bgPainter, Size size) async {
    final bounds = Offset.zero & size;
    final picture = PictureRecorder();
    final pictureCanvas = Canvas(picture);

    // 给Canvas设置绘制范围
    pictureCanvas.clipRect(bounds);

    /// 绘制背景(纯白)
    pictureCanvas.drawColor(Colors.white, BlendMode.color);

    // 在Canvas上进行绘制
    bgPainter.paint(pictureCanvas, size);
    painter.paint(pictureCanvas, size);

    /// 绘制一圈边框
    final borderPaint = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1.0;
    pictureCanvas.drawRect(bounds, borderPaint);

    // 结束绘制
    final recordedPicture = picture.endRecording();
    final image =
        await recordedPicture.toImage(size.width.toInt(), size.height.toInt());

    // 转换为字节数组
    final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    final bytes = byteData?.buffer.asUint8List();

    return bytes;
  }

  // @override
  // void onInit() {
  //   super.onInit();
  // }

  @override
  void onReady() {
    super.onReady();
    if (initPoints.isNotEmpty) {
      isInitPoints = true;
      List<List<int>> initPointsLists = separateLines(initPoints);
      for (int i = 0; i < 12; i++) {
        newPointsToDraw[i] = initPointsLists[i];
      }
      update(['twelve_ecg_view']);
      allPoints = initPoints;
    }

    // if (initPoints.length >= 3750) {
    //   newPointsToDraw = initPoints.sublist(3375, 3750);
    //   update(['twelve_ecg_view']);
    //   allPoints = initPoints;
    // } else {
    //   newPointsToDraw = initPoints;
    //   update(['twelve_ecg_view']);
    //   allPoints = initPoints;
    // }
  }

  @override
  void onClose() {
    super.onClose();
    timer.cancel();
  }
}
