import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:making_school_asignment_app/common/utils/gesture_recognition/ramer_douglas_peucker.dart';
import 'package:making_school_asignment_app/common/utils/gesture_recognition/shape_recognizer.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(375, 812),
      builder: () => MaterialApp(
        title: '手势识别实验',
        theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
        home: const GestureCanvasPage(),
      ),
    );
  }
}

class GestureCanvasPage extends StatefulWidget {
  const GestureCanvasPage({super.key});

  @override
  State<GestureCanvasPage> createState() => _GestureCanvasPageState();
}

class _GestureCanvasPageState extends State<GestureCanvasPage> {
  final List<List<Offset>> _allStrokes = [];
  final _currentStrokeNotifier = ValueNotifier<List<Offset>>([]);
  ui.Image? _cachedImage;

  GestureType _recognizedGesture = GestureType.none;
  late ShapeRecognizer _recognizer;

  // 用于控制是否显示可视化特征点的状态
  bool _showSimplifiedPoints = true;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        // 在这里初始化识别器，可以方便地调整参数
        _recognizer = ShapeRecognizer(
          rdpEpsilon: 8.r, // 你可以集中在这里调整这个值
          /// 勾的最小角度调小一些，避免漏识别
          checkAngleMin: 30.0,

          /// 勾的最大角度调大一些，避免误识别
          checkAngleMax: 150.0,

          crossAngleMin: 30.0,
          crossAngleMax: 160.0,
          minIntersectionDistance: 0.1,
          checkLengthRatio: 1.1,
          // [核心修改] 放宽对斜线斜率的限制
          slashSlopeMin: 0.2, // 这个值允许用户绘制相当平缓的斜线（角度低至约11度），这覆盖了绝大多数的书写习惯，同时这个斜率也足以和基本水平的线条区分开。
          slashSlopeMax:
              5.0, // 这个值允许用户绘制非常陡峭的斜线（角度高达约79度）。对于比这更陡峭的线条，它们已经非常接近垂直线，而我们之前优化过的 _isSlash 函数中有专门处理垂直线的逻辑 (deltaX < 1e-6)，所以这个组合非常稳健，几乎可以覆盖所有非水平的直线。
        );
      }
    });
  }

  Future<void> _updateCachedImage() async {
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder);
    final size = context.size!;
    _GestureCachePainter(allStrokes: _allStrokes).paint(canvas, size);
    final picture = recorder.endRecording();
    final newImage = await picture.toImage(size.width.toInt(), size.height.toInt());
    if (mounted) {
      setState(() {
        _cachedImage = newImage;
      });
    }
  }

  void _onPanStart(DragStartDetails details) {
    _currentStrokeNotifier.value = [details.localPosition];
  }

  void _onPanUpdate(DragUpdateDetails details) {
    _currentStrokeNotifier.value = List.from(_currentStrokeNotifier.value)..add(details.localPosition);
  }

  void _onPanEnd(DragEndDetails details) {
    if (_currentStrokeNotifier.value.isNotEmpty) {
      _allStrokes.add(List.from(_currentStrokeNotifier.value));
      _currentStrokeNotifier.value = [];

      _updateCachedImage().then((_) {
        if (mounted) {
          setState(() {
            _recognizedGesture = _recognizer.recognize(_allStrokes);
            print('识别到的手势: $_recognizedGesture');
          });
        }
      });
    }
  }

  void _clearCanvas() {
    setState(() {
      _allStrokes.clear();
      _recognizedGesture = GestureType.none;
      _cachedImage = null;
    });
    _currentStrokeNotifier.value = [];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('手势识别 (可视化调试)'),
        actions: [
          // 在AppBar中添加一个信息提示
          Padding(
            padding: const EdgeInsets.only(right: 16.0),
            child: Icon(
              Icons.science_outlined,
              color: _showSimplifiedPoints ? Colors.green : Colors.grey,
            ),
          )
        ],
      ),
      body: Stack(
        children: [
          GestureDetector(
            onPanStart: _onPanStart,
            onPanUpdate: _onPanUpdate,
            onPanEnd: _onPanEnd,
            child: ValueListenableBuilder<List<Offset>>(
              valueListenable: _currentStrokeNotifier,
              builder: (context, currentStroke, child) {
                return CustomPaint(
                  painter: _GestureCanvasPainter(
                    cachedImage: _cachedImage,
                    currentStroke: currentStroke,
                    // [修改] 将调试所需的数据传入Painter
                    allStrokes: _allStrokes,
                    rdpEpsilon: _recognizer.rdpEpsilon,
                    showSimplifiedPoints: _showSimplifiedPoints,
                  ),
                  size: Size.infinite,
                );
              },
            ),
          ),
          Align(
            alignment: Alignment.topLeft,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                '识别结果: ${_recognizedGesture.toString().split('.').last}\nEpsilon: ${_recognizer.rdpEpsilon.toStringAsFixed(2)}',
                style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.blue),
              ),
            ),
          ),
        ],
      ),
      // [修改] 使用Column包裹多个FAB
      floatingActionButton: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: _clearCanvas,
            tooltip: '清空画布',
            child: const Icon(Icons.clear),
          ),
          const SizedBox(height: 10),
          // 用于切换可视化模式的按钮
          FloatingActionButton(
            onPressed: () {
              setState(() {
                _showSimplifiedPoints = !_showSimplifiedPoints;
              });
            },
            tooltip: '切换特征点显示',
            backgroundColor: _showSimplifiedPoints ? Colors.green : Colors.grey[400],
            child: const Icon(Icons.science_outlined),
          ),
        ],
      ),
    );
  }
}

class _GestureCanvasPainter extends CustomPainter {
  final ui.Image? cachedImage;
  final List<Offset> currentStroke;
  final Paint _paint;

  // [修改] 接收新增的调试参数
  final List<List<Offset>> allStrokes;
  final double rdpEpsilon;
  final bool showSimplifiedPoints;
  final Paint _debugPaint; // 专门用于绘制特征点的画笔

  _GestureCanvasPainter({
    required this.cachedImage,
    required this.currentStroke,
    required this.allStrokes,
    required this.rdpEpsilon,
    required this.showSimplifiedPoints,
  })  : _paint = Paint()
          ..color = Colors.black
          ..strokeCap = StrokeCap.round
          ..strokeWidth = 5.0
          ..style = PaintingStyle.stroke,
        // 初始化调试画笔
        _debugPaint = Paint()
          ..color = Colors.red
          ..strokeCap = StrokeCap.round
          ..strokeWidth = 8.0;

  @override
  void paint(Canvas canvas, Size size) {
    // 步骤1: 绘制缓存的图片 (非常快)
    if (cachedImage != null) {
      canvas.drawImage(cachedImage!, Offset.zero, Paint());
    }

    // 步骤2: 绘制当前正在画的笔画
    if (currentStroke.length > 1) {
      final path = Path();
      path.moveTo(currentStroke.first.dx, currentStroke.first.dy);
      for (int i = 1; i < currentStroke.length; i++) {
        path.lineTo(currentStroke[i].dx, currentStroke[i].dy);
      }
      canvas.drawPath(path, _paint);
    }

    // 步骤3: 如果开启了可视化，则绘制简化后的特征点
    if (showSimplifiedPoints) {
      // 为所有已完成的笔画绘制特征点
      for (final stroke in allStrokes) {
        if (stroke.length > 1) {
          final simplifiedPoints = RamerDouglasPeucker.simplify(stroke, rdpEpsilon);
          canvas.drawPoints(ui.PointMode.points, simplifiedPoints, _debugPaint);
        }
      }
      // 为当前正在绘制的笔画也实时显示特征点
      if (currentStroke.length > 1) {
        final simplifiedPoints = RamerDouglasPeucker.simplify(currentStroke, rdpEpsilon);
        canvas.drawPoints(ui.PointMode.points, simplifiedPoints, _debugPaint);
      }
    }
  }

  @override
  bool shouldRepaint(covariant _GestureCanvasPainter oldDelegate) {
    // [修改] 当笔画、总笔画数或可视化开关变化时，都需要重绘
    return oldDelegate.currentStroke != currentStroke ||
        oldDelegate.showSimplifiedPoints != showSimplifiedPoints ||
        oldDelegate.allStrokes.length != allStrokes.length;
  }
}

// 缓存绘制器保持不变
class _GestureCachePainter extends CustomPainter {
  final List<List<Offset>> allStrokes;
  final Paint _paint;

  _GestureCachePainter({required this.allStrokes})
      : _paint = Paint()
          ..color = Colors.black
          ..strokeCap = StrokeCap.round
          ..strokeWidth = 5.0
          ..style = PaintingStyle.stroke;

  @override
  void paint(Canvas canvas, Size size) {
    for (final stroke in allStrokes) {
      if (stroke.length > 1) {
        final path = Path();
        path.moveTo(stroke.first.dx, stroke.first.dy);
        for (int i = 1; i < stroke.length; i++) {
          path.lineTo(stroke[i].dx, stroke[i].dy);
        }
        canvas.drawPath(path, _paint);
      }
    }
  }

  @override
  bool shouldRepaint(covariant _GestureCachePainter oldDelegate) {
    return oldDelegate.allStrokes != allStrokes;
  }
}
