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

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 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 _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

import React, { memo, useEffect, useRef, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import '@mediapipe/pose';
import { Camera } from '@mediapipe/camera_utils';
import * as poseDetection from '@tensorflow-models/pose-detection';
import * as knnClassifier from '@tensorflow-models/knn-classifier';
import * as tf from '@tensorflow/tfjs-core';
import '@tensorflow/tfjs-backend-cpu';
import InstructionalVideo from "./InstructionalVideo";
import EndScreen from "./EndScreen";
import RedirectScreen from "./RedirectScreen";
import TemplateTimer from "../components/TemplateTimer";
import TemplateCountDownReps from "../components/TemplateCountDownReps";
import TemplateCountDownSets from "../components/TemplateCountDownSets";
import Calibration from "../components/TransitionCalibration";
import TransitionCountDown from "../components/TransitionCountDown";
import BetaStartScreen from "./BetaStartScreen";
import { resetAll, setNumberOfReps, setNumberOfSets, saveUserProgress } from "../store/performance/main";
import { down, up, keypoints, numbersToRecord, enterThreshold, exitThreshold } from "./data";
var _initialPoseConfidence = {
  down: 0,
  up: 0
};

var _poseConfidence = _extends({}, _initialPoseConfidence);

var _last = null;
var _numberOfReps = 0;
var _calibration = false; // const _limit = 0.9;

var _legsLimit = 0.5;

var Main = function Main(props) {
  var dispatch = useDispatch();

  var _useSelector = useSelector(function (state) {
    return state.performance.main;
  }),
      exerciseProgress = _useSelector.exerciseProgress,
      complete = _useSelector.complete,
      currentExercise = _useSelector.currentExercise,
      identifier = _useSelector.identifier,
      user = _useSelector.user,
      aspectArea = _useSelector.aspectArea;

  var videoRef = useRef(null);
  var timerRef = useRef(null);

  var _useState = useState(knnClassifier.create()),
      classifier = _useState[0];

  var _useState2 = useState(false),
      calibration = _useState2[0],
      setCalibration = _useState2[1];

  var _useState3 = useState(false),
      showCountDown = _useState3[0],
      setShowCountDown = _useState3[1];

  var _useState4 = useState(false),
      showRedirectScreen = _useState4[0],
      setShowRedirectScreen = _useState4[1];

  var _useState5 = useState(true),
      showBetaScreen = _useState5[0],
      setShowBetaScreen = _useState5[1];

  var poseEstimator = /*#__PURE__*/function () {
    var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
      var detector, camera;
      return _regeneratorRuntime.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.prev = 0;
              _context2.next = 3;
              return poseDetection.createDetector(poseDetection.SupportedModels.BlazePose, {
                runtime: 'mediapipe',
                modelType: 'heavy',
                solutionPath: 'https://cdn.jsdelivr.net/npm/@mediapipe/pose',
                width: 1280,
                height: 720
              });

            case 3:
              detector = _context2.sent;
              camera = new Camera(videoRef.current, {
                onFrame: function () {
                  var _onFrame = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
                    var poses, poseList, _iterator, _step, keypoint, ans;

                    return _regeneratorRuntime.wrap(function _callee$(_context) {
                      while (1) {
                        switch (_context.prev = _context.next) {
                          case 0:
                            _context.next = 2;
                            return detector.estimatePoses(videoRef.current);

                          case 2:
                            poses = _context.sent;

                            if (!(poses.length > 0 && !showCountDown)) {
                              _context.next = 14;
                              break;
                            }

                            poseList = [];

                            for (_iterator = _createForOfIteratorHelperLoose(poses[0].keypoints); !(_step = _iterator()).done;) {
                              keypoint = _step.value;

                              if (keypoints[keypoint.name] === 23 || keypoints[keypoint.name] === 24 || keypoints[keypoint.name] === 25 || keypoints[keypoint.name] === 26 || keypoints[keypoint.name] === 27 || keypoints[keypoint.name] === 28 || keypoints[keypoint.name] === 31 || keypoints[keypoint.name] === 32) {
                                _calibration = keypoint.score > 0.2;
                                poseList.push(keypoint.x, keypoint.y);
                              }
                            } // VERIFICAR PERFORMANCE


                            setCalibration(_calibration);

                            if (!_calibration) {
                              _context.next = 14;
                              break;
                            }

                            _context.next = 10;
                            return classifier.predictClass(tf.tensor1d(poseList), 2);

                          case 10:
                            ans = _context.sent;
                            if (ans.confidences.down > 0.5) console.log('DOWN', _numberOfReps);
                            if (ans.confidences.up > 0.5) console.log('UP', _numberOfReps);

                            if (ans.confidences.down > 0.5 || ans.confidences.up > 0.5) {
                              if (_poseConfidence[ans.label] < enterThreshold || _poseConfidence[ans.label] < exitThreshold) {
                                _poseConfidence[ans.label] += ans.confidences[ans.label];
                              }

                              if (_poseConfidence.down >= exitThreshold && _poseConfidence.up >= enterThreshold) {
                                _numberOfReps += 1;
                                _poseConfidence = _extends({}, _initialPoseConfidence);
                                dispatch(setNumberOfReps(_numberOfReps));
                              }

                              if (_poseConfidence.down <= exitThreshold && _poseConfidence.up <= enterThreshold && _last !== ans.label) {
                                _poseConfidence = _extends({}, _initialPoseConfidence);
                              }

                              _last = ans.label;
                            }

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

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

                  return onFrame;
                }(),
                width: 1280,
                height: 720
              });
              _context2.next = 7;
              return camera.start();

            case 7:
              setShowCountDown(true);
              _context2.next = 13;
              break;

            case 10:
              _context2.prev = 10;
              _context2.t0 = _context2["catch"](0);
              console.log('🚀 ~ file: App.js ~ line 35 ~ poseEstimator ~ error', _context2.t0);

            case 13:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, null, [[0, 10]]);
    }));

    return function poseEstimator() {
      return _ref.apply(this, arguments);
    };
  }();

  var knnTensor = function knnTensor() {
    down.forEach(function (data) {
      var keypointsSelected = [];

      for (var _i = 0, _Object$entries = Object.entries(keypoints); _i < _Object$entries.length; _i++) {
        var _Object$entries$_i = _Object$entries[_i],
            index = _Object$entries$_i[1];

        if (index === keypoints['left_hip'] || index === keypoints['right_hip'] || index === keypoints['left_knee'] || index === keypoints['right_knee'] || index === keypoints['left_ankle'] || index === keypoints['right_ankle'] || index === keypoints['left_foot_index'] || index === keypoints['right_foot_index']) {
          var keypoint = numbersToRecord[index];
          keypointsSelected.push(data[keypoint.x], data[keypoint.y]);
        }
      }

      classifier.addExample(tf.tensor1d(keypointsSelected), 'down');
    });
    up.forEach(function (data) {
      var keypointsSelected = [];

      for (var _i2 = 0, _Object$entries2 = Object.entries(keypoints); _i2 < _Object$entries2.length; _i2++) {
        var _Object$entries2$_i = _Object$entries2[_i2],
            index = _Object$entries2$_i[1];

        if (index === keypoints['left_hip'] || index === keypoints['right_hip'] || index === keypoints['left_knee'] || index === keypoints['right_knee'] || index === keypoints['left_ankle'] || index === keypoints['right_ankle'] || index === keypoints['left_foot_index'] || index === keypoints['right_foot_index']) {
          var keypoint = numbersToRecord[index];
          keypointsSelected.push(data[keypoint.x], data[keypoint.y]);
        }
      }

      classifier.addExample(tf.tensor1d(keypointsSelected), 'up');
    });
  };

  useEffect(function () {
    if (exerciseProgress.current >= (currentExercise === null || currentExercise === void 0 ? void 0 : currentExercise.repetitions) && exerciseProgress.sets <= (currentExercise === null || currentExercise === void 0 ? void 0 : currentExercise.setsPerSessions)) {
      _numberOfReps = 0;
      dispatch(setNumberOfSets());
      setShowCountDown(true);
    }
  }, [exerciseProgress]);
  useEffect(function () {
    if (complete && currentExercise) {
      var _timerRef$current, _timerRef$current$sta;

      dispatch(saveUserProgress({
        identifier: identifier,
        user: user,
        exercise: currentExercise === null || currentExercise === void 0 ? void 0 : currentExercise._id,
        time: (_timerRef$current = timerRef.current) === null || _timerRef$current === void 0 ? void 0 : (_timerRef$current$sta = _timerRef$current.state) === null || _timerRef$current$sta === void 0 ? void 0 : _timerRef$current$sta.time
      })); // dispatch(resetAll());
    } else {
      poseEstimator(knnTensor());
    }
  }, [complete]); // useEffect(() => {
  //   // poseEstimator(knnTensor());
  // }, []);

  return /*#__PURE__*/React.createElement(React.Fragment, null, showBetaScreen && /*#__PURE__*/React.createElement(BetaStartScreen, {
    aspectArea: aspectArea,
    setShowBetaScreen: setShowBetaScreen
  }), complete && /*#__PURE__*/React.createElement(EndScreen, {
    setShowRedirectScreen: setShowRedirectScreen
  }), showRedirectScreen && /*#__PURE__*/React.createElement(RedirectScreen, {
    setShowRedirectScreen: setShowRedirectScreen,
    setShowBetaScreen: setShowBetaScreen
  }), !complete && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(InstructionalVideo, null), /*#__PURE__*/React.createElement(TemplateCountDownReps, {
    countProgress: exerciseProgress
  }), /*#__PURE__*/React.createElement(TemplateCountDownSets, {
    countProgress: exerciseProgress
  }), showCountDown && /*#__PURE__*/React.createElement(TransitionCountDown, {
    callback: function callback() {
      return setShowCountDown(false);
    }
  }), !calibration && /*#__PURE__*/React.createElement(Calibration, {
    currentExercise: currentExercise
  }), /*#__PURE__*/React.createElement("video", {
    ref: videoRef,
    width: '100%',
    height: '100%'
  })), /*#__PURE__*/React.createElement(TemplateTimer, {
    ref: timerRef,
    active: !complete
  }));
};

export default memo(Main);