import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'camera_permission.dart';
import 'camera_position.dart';
import 'query_camera_device.dart';
import 'user_info.dart';
import 'video_frame_processed_event.dart';
import 'vital_sign_camera_config.dart';
import 'preview_layer_gravity.dart';

import 'camera_device.dart';
import 'vital_sign_camera_platform_interface.dart';
import 'vital_sign_camera_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// Get the available camera devices supported by the hardware.
Future<List<CameraDevice>> availableCameraDevices() {
  return VitalSignCameraPlatform.instance.availableCameraDevices();
}

/// Request the permission to access the camera.
Future<CameraPermissionStatus> requestCameraPermission() {
  return VitalSignCameraPlatform.instance.requestCameraPermission();
}

/// Get the current status of the camera permission.
Future<CameraPermissionStatus> getCameraPermissionStatus() {
  return VitalSignCameraPlatform.instance.getCameraPermissionStatus();
}

typedef VitalSignCameraCreatedCallback = void Function(
    VitalSignCameraController controller);

typedef OnVideoFrameProcessed = void Function(VideoFrameProcessedEvent event);

/// The main component to perform vital sign scanning of a user.
class VitalSignCamera extends StatefulWidget {
  /// The callback function to obtain an instance of [VitalSignCameraController],
  /// which is used to start a scan.
  final VitalSignCameraCreatedCallback? onCreated;

  /// To state wheather the component should be active or not.
  final bool isActive;

  /// The camera deivice obtained by the method [availableCameraDevices].
  final Future<CameraDevice?>? device;

  /// The information of the user doing the scan.
  final UserInfo userInfo;

  /// The gravity of the camera preview layer.
  final PreviewLayerGravity? previewLayerGravity;

  /// The configuration of the component.
  final VitalSignCameraConfig config;

  /// The callback function for obtaining the information of a video frame and
  /// the result of the scan such as the vital signs.
  /// This callback function is called at the rate up to 30Hz, the actual
  /// rate depends on the the hardware capability.
  final OnVideoFrameProcessed? onVideoFrameProcessed;

  const VitalSignCamera(
      {super.key,
      this.onCreated,
      required this.isActive,
      this.device,
      required this.userInfo,
      required this.config,
      this.previewLayerGravity,
      this.onVideoFrameProcessed});

  @override
  State<VitalSignCamera> createState() => _VitalSignCameraState();
}

class _VitalSignCameraState extends State<VitalSignCamera> {
  late Future<CameraDevice?> cameraDevice;
  late MethodChannel channel;
  @override
  void initState() {
    super.initState();
    if (widget.device == null) {
      cameraDevice = getFrontCamera();
    } else {
      cameraDevice = widget.device!;
    }
  }

  @override
  void didUpdateWidget(VitalSignCamera oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.config != oldWidget.config ||
        widget.userInfo != oldWidget.userInfo ||
        widget.isActive != oldWidget.isActive) {
      channel.invokeMethod("configure", {
        'isActive': widget.isActive,
        'userInfo': widget.userInfo.map,
        'config': widget.config.map,
        'previewLayterGravity': widget.previewLayerGravity?.toInt(),
      });
    }
  }

  Future<CameraDevice?> getFrontCamera() async {
    var status = await getCameraPermissionStatus();
    if (CameraPermissionStatus.authorized != status) {
      status = await requestCameraPermission();
    }
    if (CameraPermissionStatus.authorized != status) {
      return null;
    }
    return queryCameraDevice(CameraPosition.front);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<CameraDevice?>(
        future: cameraDevice,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Container();
          }
          if (!snapshot.hasData) {
            return const Center(
                child: Text(
              "Camera permission denied.",
              textAlign: TextAlign.center,
            ));
          }

          final creationParams = {
            'isActive': widget.isActive,
            'id': snapshot.data?.id,
            'userInfo': widget.userInfo.map,
            'config': widget.config.map,
            'previewLayerGravity': widget.previewLayerGravity?.toInt(),
          };

          switch (defaultTargetPlatform) {
            case TargetPlatform.android:
              return PlatformViewLink(
                viewType: 'ai.panoptic/flutter_vital_sign_camera',
                surfaceFactory: (context, controller) {
                  return AndroidViewSurface(
                    controller: controller as AndroidViewController,
                    gestureRecognizers: const <Factory<
                        OneSequenceGestureRecognizer>>{},
                    hitTestBehavior: PlatformViewHitTestBehavior.opaque,
                  );
                },
                onCreatePlatformView: (params) {
                  return PlatformViewsService.initExpensiveAndroidView(
                    id: params.id,
                    viewType: 'ai.panoptic/flutter_vital_sign_camera',
                    layoutDirection: TextDirection.ltr,
                    creationParams: creationParams,
                    creationParamsCodec: const StandardMessageCodec(),
                    onFocus: () {
                      params.onFocusChanged(true);
                    },
                  )
                    ..addOnPlatformViewCreatedListener(
                      (id) {
                        params.onPlatformViewCreated(id);
                        _onPlatformViewCreated(id);
                      },
                    )
                    ..create();
                },
              );
            case TargetPlatform.iOS:
              return UiKitView(
                viewType: 'ai.panoptic/flutter_vital_sign_camera',
                onPlatformViewCreated: _onPlatformViewCreated,
                creationParams: creationParams,
                creationParamsCodec: const StandardMessageCodec(),
              );
            default:
              return Text(
                  '$defaultTargetPlatform is not yet supported by the web_view plugin');
          }
        });
  }

  // Callback method when platform view is created
  void _onPlatformViewCreated(int id) {
    final controller = VitalSignCameraController._(id);
    widget.onCreated?.call(controller);

    channel =
        MethodChannel('ai.panoptic/channel/flutter_vital_sign_camera_$id');

    if (widget.onVideoFrameProcessed != null) {
      controller.videoFrameProcessedChannel
          .receiveBroadcastStream()
          .listen((event) {
        if (!widget.isActive) {
          return;
        }
        widget.onVideoFrameProcessed!(VideoFrameProcessedEvent.fromMap(event));
      });
    }
  }
}

// VitalSignCamera Controller class
class VitalSignCameraController {
  VitalSignCameraController._(int id)
      : _channel =
            MethodChannel('ai.panoptic/channel/flutter_vital_sign_camera_$id'),
        videoFrameProcessedChannel = EventChannel(
            'ai.panoptic/channel/flutter_vital_sign_camera_processed_frame_event_$id');

  final MethodChannel _channel;
  final EventChannel videoFrameProcessedChannel;

  Future<void> startScanning() async {
    return _channel.invokeMethod('startScanning');
  }

  Future<void> stopScanning() async {
    return _channel.invokeMethod('stopScanning');
  }
}
