<?php
    ##########################################################################
    ##########################################################################
    //VERIFICA SEGURIDAD: Perfil de Administrador requerido antes de continuar
    global $PCOSESS_LoginUsuario,$MULTILANG_ErrorTitAuth,$MULTILANG_WSErr06;
    if (!PCO_EsAdministrador(@$PCOSESS_LoginUsuario))
        {
            PCO_Mensaje("{$MULTILANG_ErrorTitAuth}", "{$MULTILANG_WSErr06}", '', 'fa fa-exclamation-triangle fa-3x texto-rojo texto-blink', 'alert alert-warning alert-dismissible');
            PCO_Auditar("$PCOSESS_LoginUsuario Intenta acceso no autorizado Frm:-46","SECLog:event");
            die();
        }
    ##########################################################################
    ##########################################################################
    
    global $FaceAPI_CodigoEnrolamientoCamara,$FaceAPI_CodigoEnrolamientoControles,$PCOVAR_ScriptPre_FaceAPI,$MULTILANG_Cerrar,$MULTILANG_Error,$TablasCore;

    //Determina si se debe incluir scripts de reconocimiento facial
    $PCO_RegistroParametrosAplicacion=PCO_EjecutarSQL("SELECT * FROM {$TablasCore}parametros WHERE 1=1 LIMIT 0,1 ")->fetch();
    if ($PCO_RegistroParametrosAplicacion["facialrec_habilitar"]!="S")
        {
            PCO_Mensaje("{$MULTILANG_Error}", "Subsistema de reconocimiento facial no se encuentra activado.<br><br>Vaya a Configuraci&oacute;n->Parametros de aplicaci&oacute;n->Reconocimiento facial y act&iacute;velo en caso que sea necesario antes de intentar usarlo.", '', 'fa fa-exclamation-triangle fa-3x texto-rojo texto-blink', 'alert alert-danger');
            echo " <a class='btn btn-danger' href='#' onclick='window.close();'>{$MULTILANG_Cerrar}</a>";
            die();
        }

    //Variables de Personalizacion del JS Face-API y maquetacion
    $ID_CampoAlmacenamientoEnForm="vectores_faciales";  //Campo existente en form sobre el que se almacenan los vectores
    $ID_CampoLlaveUnicaEnForm="login";  //Campo existente en form que contiene el valor de llave unica para asociar los vectores
    $ID_CampoPrecisionEnForm="precision";  //Campo existente en form
    
    //Variables de configuracion en parametros del framework
    $ResolucionAncho=$PCO_RegistroParametrosAplicacion["facialrec_anchocam"];
    $ResolucionAlto=$PCO_RegistroParametrosAplicacion["facialrec_altocam"];
    $TiempoMuestreo=$PCO_RegistroParametrosAplicacion["facialrec_tiempomuestreo"]*1000;
    $PrecisionMinima=$PCO_RegistroParametrosAplicacion["facialrec_precision"];


    //Carga todos los datos de biometria desde la BD simulando el fetch.php
    $DatosHuellasBiometria="";
    $data=PCO_EjecutarSQL("SELECT vectores_faciales FROM core_usuario")->fetchAll(PDO::FETCH_OBJ);
    $array=array();
    if($data)
        {
            foreach($data as $dat)
                {
                    if (trim($dat->vectores_faciales)!="")
            	        array_push($array,$dat->vectores_faciales);
                }
            $array = implode(", ", $array);
            $DatosHuellasBiometria.= '['.$array.']';
        }
    else
        {
            $DatosHuellasBiometria.= '[]';
        }


    $FaceAPI_CodigoEnrolamientoCamara='
        <div style="text-align: left;">
            <video id="vidDisplay" style="height: '.$ResolucionAlto.'px; width: '.$ResolucionAncho.'px;" onloadedmetadata="onPlay(this)" autoplay="true"></video>
            <canvas id="overlay" style="position: absolute; top: 0; left: 0;" width = "'.$ResolucionAncho.'" height = "'.$ResolucionAlto.'"/>
        </div>';

    $PCOVAR_ScriptPre_FaceAPI="
          //----------------------------GLOBAL VARIABLE FOR FACE MATCHER------------------------------------
          var faceMatcher = undefined
          //----------------------------------------------------------------------------------------------
        
          Promise.all([
            faceapi.nets.faceRecognitionNet.loadFromUri('inc/face-detect/models'),
            faceapi.nets.faceLandmark68Net.loadFromUri('inc/face-detect/models'),
            faceapi.nets.ssdMobilenetv1.loadFromUri('inc/face-detect/models'),
            faceapi.nets.tinyFaceDetector.loadFromUri('inc/face-detect/models')
          ]).then(start)


            var json_str='';
            async function start()
            {
                data='{$DatosHuellasBiometria}';
                if(data.length > 2)
                    {
                        json_str = '{\"parent\":' + data  + '}'
                        content = JSON.parse(json_str)
                        for (var x = 0; x < Object.keys(content.parent).length; x++)
                            {
                                for (var y = 0; y < Object.keys(content.parent[x]._descriptors).length; y++)
                                    {
                                        var results = Object.values(content.parent[x]._descriptors[y])
                                        content.parent[x]._descriptors[y] = new Float32Array(results)
                                    }
                            }
                        faceMatcher = await createFaceMatcher(content);
                    }
                run();
            }

          // Create Face Matcher
          async function createFaceMatcher(data) {
            const labeledFaceDescriptors = await Promise.all(data.parent.map(className => {
              const descriptors = [];
              for (var i = 0; i < className._descriptors.length; i++) {
                descriptors.push(className._descriptors[i]);
              }
              return new faceapi.LabeledFaceDescriptors(className._label, descriptors);
            }))
            return new faceapi.FaceMatcher(labeledFaceDescriptors,0.6);
          }
        
        
          async function onPlay() {
              //RETIRADO ELIMINACION JQUERY 
            //   const videoEl = $('#vidDisplay').get(0)
            //   if(videoEl.paused || videoEl.ended )
            //     return setTimeout(() => onPlay())
        
                $('#overlay').show()
                const canvas = $('#overlay').get(0)
                
                  if(faceMatcher != undefined){
                    //--------------------------FACE RECOGNIZE------------------
                    const input = document.getElementById('vidDisplay')
                    const displaySize = { width: {$ResolucionAncho}, height: {$ResolucionAlto} }
                    faceapi.matchDimensions(canvas, displaySize)
                    const detections = await faceapi.detectAllFaces(input).withFaceLandmarks().withFaceDescriptors()
                    const resizedDetections = faceapi.resizeResults(detections, displaySize)
                    const results = resizedDetections.map(d => faceMatcher.findBestMatch(d.descriptor))
                    results.forEach((result, i) => {
                        const box = resizedDetections[i].detection.box
                        const drawBox = new faceapi.draw.DrawBox(box, { label: result.toString() })
                        drawBox.draw(canvas)
                        var str = result.toString()
                        rating = parseFloat(str.substring(str.indexOf('(') + 1,str.indexOf(')')))
                        str = str.substring(0, str.indexOf('('))
                        str = str.substring(0, str.length - 1)
                        if(str != 'unknown'){
                          if(rating < {$PrecisionMinima}){
                                    $('#{$ID_CampoLlaveUnicaEnForm}').val(str);
                                    $('#{$ID_CampoPrecisionEnForm}').val(rating);
                                    match = true;
                            }  
                        }
                    })
                    //---------------------------------------------------------------------  
                  }
                  
                //Establece el tiempo entre cada captura en milisegundos
              setTimeout(() => onPlay(),{$TiempoMuestreo})
            }
        
          async function run() {
              const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
              const videoEl = $('#vidDisplay').get(0)
              videoEl.srcObject = stream
          }

        ";