enum QrCameraBootstrapStatus {
  ready,
  detectorUnsupported,
  permissionError,
  cameraError,
}

class QrCameraBootstrapResult {
  const QrCameraBootstrapResult(this.status, {this.errorDetail = ''});

  final QrCameraBootstrapStatus status;
  final String errorDetail;

  bool get isReady => status == QrCameraBootstrapStatus.ready;
}

typedef QrOpenCameraAndPlay = Future<void> Function();
typedef QrStopCamera = Future<void> Function();

bool isQrPermissionError(Object error) {
  final raw = error.toString();
  return raw.contains('NotAllowedError') ||
      raw.contains('PermissionDeniedError') ||
      raw.contains('SecurityError');
}

Future<QrCameraBootstrapResult> bootstrapQrCamera({
  required bool hasBarcodeDetector,
  required QrOpenCameraAndPlay openCameraAndPlay,
  required QrStopCamera stopCamera,
}) async {
  try {
    await openCameraAndPlay();
    if (!hasBarcodeDetector) {
      await stopCamera();
      return const QrCameraBootstrapResult(
        QrCameraBootstrapStatus.detectorUnsupported,
        errorDetail: 'BarcodeDetector is not supported in this browser.',
      );
    }
    return const QrCameraBootstrapResult(QrCameraBootstrapStatus.ready);
  } catch (e) {
    if (isQrPermissionError(e)) {
      return QrCameraBootstrapResult(
        QrCameraBootstrapStatus.permissionError,
        errorDetail: e.toString(),
      );
    }
    return QrCameraBootstrapResult(
      QrCameraBootstrapStatus.cameraError,
      errorDetail: e.toString(),
    );
  }
}
