import 'dart:io';

import 'package:camera/camera.dart';
import 'package:get/get.dart';
import 'package:myhr_facescan/luxand_controller.dart';
import 'package:myhr_facescan/models/face_position.dart';
import 'package:myhr_facescan/models/template.dart';
import 'package:myhr_facescan/utils/camera.dart';
import 'package:myhr_facescan/utils/image.dart';
import 'package:myhr_facescan/utils/throttler.dart';

class EnrollController extends GetxController {
  EnrollController({
    required String licenseKey,
    required void Function(List<TemplateModel>) onFinish,
    required int templateCount,
    required int imageStreamMilliSecond,
  })  : _imageStreamMilliSecond = imageStreamMilliSecond,
        _templateCount = templateCount,
        _onFinish = onFinish,
        _licenseKey = licenseKey {
    _throttler = Throttler(milliSeconds: _imageStreamMilliSecond);
    _luxand = Get.put(LuxandController(licenseKey: _licenseKey));
  }

  CameraController? camController;
  double previewScale = 0;
  late Throttler _throttler;
  // StreamSubscription<int> _timer = null;

  final String _licenseKey;
  final void Function(List<TemplateModel>) _onFinish;
  final int _templateCount;
  final int _imageStreamMilliSecond;

  var isFoundFace = false.obs;
  var facePosition = FacePosition(x: 0, y: 0, width: 0).obs;
  var isCameraReady = false.obs;
  var templates = <TemplateModel>[].obs;

  var _gettingCurrentImage = false;
  late LuxandController _luxand;

  @override
  void onInit() async {
    super.onInit();

    await _luxand.initialize();
    await initCamera();

    camController!.initialize().then((_) {
      isCameraReady.value = true;
      previewScale = getCameraPreviewScale(camController!.value.aspectRatio);

      // Only open and close camera in iOS for low-tier device
      if (Platform.isIOS) {
        // _timer = Stream.periodic(const Duration(milliseconds: 500), (v) => v)
        //     .listen((count) async {
        //   _throttler.run(() async {
        //     controller.startImageStream((image) async {});

        //     Future.delayed(const Duration(milliseconds: 50), () async {
        //       await controller.stopImageStream();
        //     });
        //   });
        // });
      } else {
        camController!.startImageStream(_handleCameraAndroid);
      }
    });
  }

  initCamera() async {
    camController = await getCameraController();
  }

  @override
  void onClose() async {
    super.onClose();
    await _clearResource();
  }

  _clearResource() async {
    isCameraReady.value = false;
    await camController?.stopImageStream();
    await camController?.dispose();

    await _luxand.freeResource();
  }

  _handleCameraAndroid(CameraImage image) async {
    _throttler.run(() async {
      if (_gettingCurrentImage) {
        var template = await _luxand.getFaceTemplate(image);
        var jpgImage = await convertYUV420toImageColor(image);

        if (template.isEmpty) {
          _gettingCurrentImage = false;
          return;
        }

        templates.add(TemplateModel(
            face: template[1], eye: template[0], image: jpgImage!));

        if (templates.length >= _templateCount) {
          _onFinish(templates);
          await _clearResource();
        }

        _gettingCurrentImage = false;
      } else {
        var data = await _luxand.detectFace(image);

        if (data == null) {
          isFoundFace.value = false;
          return;
        }

        isFoundFace.value = true;
        facePosition.value = data;
      }
    });
  }

  getCurrentImage() async {
    if (isFoundFace.value) {
      _gettingCurrentImage = true;
    }
  }
}
