content: import 'dart:async';
  import 'dart:math';
  import 'package:fl_clash/common/color.dart';
  import 'package:fl_clash/state.dart';
  import 'package:fl_clash/widgets/activate_box.dart';
  import 'package:flutter/material.dart';
  import 'package:mobile_scanner/mobile_scanner.dart';
  
  class ScanPage extends StatefulWidget {
    const ScanPage({super.key});
  
    @override
    State<ScanPage> createState() => _ScanPageState();
  }
  
  class _ScanPageState extends State<ScanPage> with WidgetsBindingObserver {
    MobileScannerController controller = MobileScannerController(
      detectionSpeed: DetectionSpeed.noDuplicates,
      formats: const [BarcodeFormat.qrCode],
    );
  
    StreamSubscription<Object?>? _subscription;
  
    @override
    void initState() {
      super.initState();
      WidgetsBinding.instance.addObserver(this);
      _subscription = controller.barcodes.listen(_handleBarcode);
      unawaited(controller.start());
    }
  
    _handleBarcode(BarcodeCapture barcodeCapture) {
      final barcode = barcodeCapture.barcodes.first;
      if (barcode.type == BarcodeType.url) {
        Navigator.pop<String>(
          context,
          barcode.rawValue,
        );
      } else {
        Navigator.pop(context);
      }
    }
  
    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
      super.didChangeAppLifecycleState(state);
      switch (state) {
        case AppLifecycleState.detached:
        case AppLifecycleState.hidden:
        case AppLifecycleState.paused:
          return;
        case AppLifecycleState.resumed:
          _subscription = controller.barcodes.listen(_handleBarcode);
  
          unawaited(controller.start());
        case AppLifecycleState.inactive:
          unawaited(_subscription?.cancel());
          _subscription = null;
          unawaited(controller.stop());
      }
    }
  
    @override
    Widget build(BuildContext context) {
      double sideLength = min(400, MediaQuery.of(context).size.width * 0.67);
      final scanWindow = Rect.fromCenter(
        center: MediaQuery.sizeOf(context).center(Offset.zero),
        width: sideLength,
        height: sideLength,
      );
      return Scaffold(
        body: Stack(
          children: [
            Center(
              child: MobileScanner(
                controller: controller,
                scanWindow: scanWindow,
              ),
            ),
            CustomPaint(
              painter: ScannerOverlay(scanWindow: scanWindow),
            ),
            AppBar(
              backgroundColor: Colors.transparent,
              automaticallyImplyLeading: false,
              leading: IconButton(
                style: const ButtonStyle(
                  iconSize: WidgetStatePropertyAll(32),
                  foregroundColor: WidgetStatePropertyAll(Colors.white),
                ),
                onPressed: () {
                  Navigator.of(context).pop();
                },
                icon: const Icon(Icons.close),
              ),
              actions: [
                ValueListenableBuilder<MobileScannerState>(
                  valueListenable: controller,
                  builder: (context, state, _) {
                    var icon = const Icon(Icons.flash_off);
                    var backgroundColor = Colors.black12;
                    switch (state.torchState) {
                      case TorchState.off:
                        icon = const Icon(Icons.flash_off);
                        backgroundColor = Colors.black12;
                      case TorchState.on:
                        icon = const Icon(Icons.flash_on);
                        backgroundColor = Colors.orange;
                      case TorchState.unavailable:
                        icon = const Icon(Icons.flash_off);
                        backgroundColor = Colors.transparent;
                      case TorchState.auto:
                        icon = const Icon(Icons.flash_auto);
                        backgroundColor = Colors.orange;
                    }
                    return Container(
                      margin: const EdgeInsets.symmetric(horizontal: 8),
                      child: ActivateBox(
                        active: state.torchState != TorchState.unavailable,
                        child: IconButton(
                          color: Colors.white,
                          icon: icon,
                          style: ButtonStyle(
                            foregroundColor:
                                const WidgetStatePropertyAll(Colors.white),
                            backgroundColor:
                                WidgetStatePropertyAll(backgroundColor),
                          ),
                          onPressed: () => controller.toggleTorch(),
                        ),
                      ),
                    );
                  },
                )
              ],
            ),
            Container(
              margin: const EdgeInsets.only(bottom: 32),
              alignment: Alignment.bottomCenter,
              child: IconButton(
                color: Colors.white,
                style: const ButtonStyle(
                  foregroundColor: WidgetStatePropertyAll(Colors.white),
                  backgroundColor: WidgetStatePropertyAll(Colors.grey),
                ),
                padding: const EdgeInsets.all(16),
                iconSize: 32.0,
                onPressed: globalState.appController.addProfileFormQrCode,
                icon: const Icon(Icons.photo_camera_back),
              ),
            ),
          ],
        ),
      );
    }
  
    @override
    Future<void> dispose() async {
      WidgetsBinding.instance.removeObserver(this);
      unawaited(_subscription?.cancel());
      _subscription = null;
      await controller.dispose();
      super.dispose();
    }
  }
  
  class ScannerOverlay extends CustomPainter {
    const ScannerOverlay({
      required this.scanWindow,
      this.borderRadius = 12.0,
    });
  
    final Rect scanWindow;
    final double borderRadius;
  
    @override
    void paint(Canvas canvas, Size size) {
      final backgroundPath = Path()..addRect(Rect.largest);
  
      final cutoutPath = Path()
        ..addRRect(
          RRect.fromRectAndCorners(
            scanWindow,
            topLeft: Radius.circular(borderRadius),
            topRight: Radius.circular(borderRadius),
            bottomLeft: Radius.circular(borderRadius),
            bottomRight: Radius.circular(borderRadius),
          ),
        );
  
      final backgroundPaint = Paint()
        ..color = Colors.black.opacity50
        ..style = PaintingStyle.fill
        ..blendMode = BlendMode.dstOut;
  
      final backgroundWithCutout = Path.combine(
        PathOperation.difference,
        backgroundPath,
        cutoutPath,
      );
  
      final borderPaint = Paint()
        ..color = Colors.white
        ..style = PaintingStyle.stroke
        ..strokeWidth = 4.0;
  
      final borderRect = RRect.fromRectAndCorners(
        scanWindow,
        topLeft: Radius.circular(borderRadius),
        topRight: Radius.circular(borderRadius),
        bottomLeft: Radius.circular(borderRadius),
        bottomRight: Radius.circular(borderRadius),
      );
  
      canvas.drawPath(backgroundWithCutout, backgroundPaint);
      canvas.drawRRect(borderRect, borderPaint);
    }
  
    @override
    bool shouldRepaint(ScannerOverlay oldDelegate) {
      return scanWindow != oldDelegate.scanWindow ||
          borderRadius != oldDelegate.borderRadius;
    }
  }
  