import _regeneratorRuntime from "@babel/runtime/regenerator";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

import React, { useEffect, useRef, memo, useCallback, useState } from 'react';
import PipeHolistic from '@mediapipe/holistic';
import { drawLandmarks, drawConnectors, lerp } from '@mediapipe/drawing_utils';
import { Camera } from '@mediapipe/camera_utils';
import Loading from "../Loading";
import { HolisticAngleCalculator, HolisticPoseValidator } from "../../services";

var Holistic = PipeHolistic.Holistic,
    mpHolistic = _objectWithoutPropertiesLoose(PipeHolistic, ["Holistic"]);

var holistic = null;

var connect = function connect(ctx, connectors) {
  var canvas = ctx.canvas;

  for (var _iterator = _createForOfIteratorHelperLoose(connectors), _step; !(_step = _iterator()).done;) {
    var connector = _step.value;
    var from = connector[0];
    var to = connector[1];

    if (from && to) {
      if (from.visibility && to.visibility && (from.visibility < 0.1 || to.visibility < 0.1)) {
        continue;
      }

      ctx.beginPath();
      ctx.moveTo(from.x * canvas.width, from.y * canvas.height);
      ctx.lineTo(to.x * canvas.width, to.y * canvas.height);
      ctx.stroke();
    }
  }
};

var removeElements = function removeElements(landmarks, elements) {
  for (var _iterator2 = _createForOfIteratorHelperLoose(elements), _step2; !(_step2 = _iterator2()).done;) {
    var element = _step2.value;
    delete landmarks[element];
  }
};

var removeLandmarks = function removeLandmarks(results) {
  if (results.poseLandmarks) {
    removeElements(results.poseLandmarks, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22]);
  }
};

var VideoPoseEstimator = function VideoPoseEstimator(props) {
  var canvasRef = useRef(null);
  var videoRef = useRef(null); // const [holistic, setHolistic] = useState(null);
  // DEPRECATED - TESTING
  // useEffect(() => {
  //   const poseEstimator = new PoseEstimationController(
  //     canvasRef.current,
  //     videoRef.current,
  //     onInitHandler,
  //     props
  //   );
  //   poseEstimator.onInit();
  //   poseEstimator.holistic.updateProps(props);
  // }, [props.currentExercise, props.facingMode]);

  var __onResults = useCallback(function (results) {
    if (props.loading) {
      props.onLoading();
      return;
    }

    var canvasCtx = canvasRef.current.getContext('2d');
    var width = canvasRef.current.width;
    var height = canvasRef.current.height;
    canvasCtx.save();
    canvasCtx.clearRect(0, 0, width, height);

    if (results.segmentationMask) {
      canvasCtx.drawImage(results.segmentationMask, 0, 0, width, height); // Only overwrite existing pixels.

      if (activeEffect === 'mask' || activeEffect === 'both') {
        canvasCtx.globalCompositeOperation = 'source-in'; // This can be a color or a texture or whatever...

        canvasCtx.fillStyle = '#00FF007F';
        canvasCtx.fillRect(0, 0, width, height);
      } else {
        canvasCtx.globalCompositeOperation = 'source-out';
        canvasCtx.fillStyle = '#0000FF7F';
        canvasCtx.fillRect(0, 0, width, height);
      } // Only overwrite missing pixels.


      canvasCtx.globalCompositeOperation = 'destination-atop';
      canvasCtx.drawImage(results.image, 0, 0, width, height);
      canvasCtx.globalCompositeOperation = 'source-over';
    } else {
      canvasCtx.drawImage(results.image, 0, 0, width, height);
    } // Connect elbows to hands. Do this first so that the other graphics will draw
    // on top of these marks.


    canvasCtx.lineWidth = 5;

    if (results.poseLandmarks) {
      var _props$currentExercis;

      if (results.rightHandLandmarks) {
        canvasCtx.strokeStyle = 'white';
        connect(canvasCtx, [[results.poseLandmarks[mpHolistic.POSE_LANDMARKS.RIGHT_ELBOW], results.rightHandLandmarks[0]]]);
      }

      if (results.leftHandLandmarks) {
        canvasCtx.strokeStyle = 'white';
        connect(canvasCtx, [[results.poseLandmarks[mpHolistic.POSE_LANDMARKS.LEFT_ELBOW], results.leftHandLandmarks[0]]]);
      }

      if ((_props$currentExercis = props.currentExercise) === null || _props$currentExercis === void 0 ? void 0 : _props$currentExercis.key) {
        var _props$currentExercis2;

        var resultObject = HolisticPoseValidator.visiblePoints((_props$currentExercis2 = props.currentExercise) === null || _props$currentExercis2 === void 0 ? void 0 : _props$currentExercis2.key, results);
        props.onBodyPartNotVisible(resultObject.parts);
        props.onShowIncorrectSide(resultObject.incorrectSide);
        var angleValue = HolisticAngleCalculator.calculate(props.currentExercise.key, results);
        props.onExerciseValue(angleValue.toFixed(2));
      }

      if (results.poseLandmarks) {
        removeLandmarks(results);
      } // Pose...


      drawConnectors(canvasCtx, results.poseLandmarks, mpHolistic.POSE_CONNECTIONS, {
        color: 'white'
      });
      drawLandmarks(canvasCtx, Object.values(mpHolistic.POSE_LANDMARKS_LEFT).map(function (index) {
        return results.poseLandmarks[index];
      }), {
        visibilityMin: 0.65,
        color: 'white',
        fillColor: 'rgb(255,138,0)'
      });
      drawLandmarks(canvasCtx, Object.values(mpHolistic.POSE_LANDMARKS_RIGHT).map(function (index) {
        return results.poseLandmarks[index];
      }), {
        visibilityMin: 0.65,
        color: 'white',
        fillColor: 'rgb(0,217,231)'
      }); // Hands...

      drawConnectors(canvasCtx, results.rightHandLandmarks, mpHolistic.HAND_CONNECTIONS, {
        color: 'white'
      });
      drawLandmarks(canvasCtx, results.rightHandLandmarks, {
        color: 'white',
        fillColor: 'rgb(0,217,231)',
        lineWidth: 2,
        radius: function radius(data) {
          return lerp(data.from.z, -0.15, 0.1, 10, 1);
        }
      });
      drawConnectors(canvasCtx, results.leftHandLandmarks, mpHolistic.HAND_CONNECTIONS, {
        color: 'white'
      });
      drawLandmarks(canvasCtx, results.leftHandLandmarks, {
        color: 'white',
        fillColor: 'rgb(255,138,0)',
        lineWidth: 2,
        radius: function radius(data) {
          return lerp(data.from.z, -0.15, 0.1, 10, 1);
        }
      });
    }

    canvasCtx.restore();
  }, [props.currentExercise, props.loading]);

  useEffect(function () {
    holistic = new Holistic({
      locateFile: function locateFile(file) {
        return "https://cdn.jsdelivr.net/npm/@mediapipe/holistic/" + file;
      },
      prefix: false
    });
    holistic.setOptions({
      enableFaceGeometry: false,
      selfieMode: false,
      modelComplexity: 1,
      smoothLandmarks: true,
      enableSegmentation: false,
      smoothSegmentation: true,
      minDetectionConfidence: 0.5,
      minTrackingConfidence: 0.5
    });
    setupCamera();
  }, []);
  useEffect(function () {
    holistic.onResults(__onResults);
  }, [props.currentExercise, props.loading]);
  var setupCamera = useCallback(function () {
    if (holistic && typeof videoRef.current !== 'undefined' && videoRef.current !== null) {
      var camera = new Camera(videoRef.current, {
        facingMode: props.facingMode,
        onFrame: function () {
          var _onFrame = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
            return _regeneratorRuntime.wrap(function _callee$(_context) {
              while (1) {
                switch (_context.prev = _context.next) {
                  case 0:
                    _context.next = 2;
                    return holistic.send({
                      image: videoRef.current
                    });

                  case 2:
                  case "end":
                    return _context.stop();
                }
              }
            }, _callee);
          }));

          function onFrame() {
            return _onFrame.apply(this, arguments);
          }

          return onFrame;
        }(),
        width: 1280,
        height: 720
      });
      camera.start();
    }
  }, [props.facingMode]);
  useEffect(function () {
    setupCamera();
  }, [props.facingMode]);
  return /*#__PURE__*/React.createElement("div", {
    id: "video",
    className: "main-video"
  }, props.loading && /*#__PURE__*/React.createElement(Loading, null), /*#__PURE__*/React.createElement("video", {
    id: "videoNoShow",
    style: {
      display: 'none'
    },
    playsInline: true,
    ref: videoRef,
    on: function on() {
      return console.log('ENTREI');
    }
  }), /*#__PURE__*/React.createElement("canvas", {
    id: "canvas",
    ref: canvasRef,
    width: "1280px",
    height: "720px"
  }));
};

export default memo(VideoPoseEstimator);