<?php

/**
 *
 * @About:      API Interface
 * @File:       index.php
 * @Date:       $Date:$ Agosot0 -2022
 * @Version:    $Rev:$ 1.0
 * @Developer:  Federico Guzman || Modificado por Fernando Humanes para PHP 8.1
 **/

/* Los headers permiten acceso desde otro dominio (CORS) a nuestro REST API o desde un cliente remoto via HTTP
 * Removiendo las lineas header() limitamos el acceso a nuestro RESTfull API a el mismo dominio
 * Nótese los métodos permitidos en Access-Control-Allow-Methods. Esto nos permite limitar los métodos de consulta a nuestro RESTfull API
 * Mas información: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
 **/

header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Requested-With");
header('Content-Type: text/html; charset=utf-8');
header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');

session_cache_limiter(false);

include_once '../include/Config.php';

require_once("../../include/dbcommon.php"); // DataBase PHPRunner
global $conn; // Connection data base of PHPRunner

// Debug
$debugCode = false;
custom_error(1,"URL ejecutada: ".$_SERVER["REQUEST_URI"]); // To debug

// use App\Models\Db;  // Utilizamos la conexión de PHPRunner
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Selective\BasePath\BasePathMiddleware;
use Slim\Factory\AppFactory;

require_once __DIR__ . '/../libs/autoload.php';

$app = AppFactory::create();
$app->addBodyParsingMiddleware();

$app->addRoutingMiddleware();
// $app->add(new BasePathMiddleware($app)); // No usar si se ejecuta en subdirectorio
$app->addErrorMiddleware(true, true, true);


$app->setBasePath(SCRIPTS_DIR);


// --------------------------------------------------------------------------------------

/* Usando POST para Crear la autenticación de los usuarios */

$app->post('/login', function(Request $request, Response $response) {
    global $errorMessages;
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';
    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // check for required params
    $param = $request->getParsedBody();
    $verify = verifyRequiredParams(array('login', 'password'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    $data = $request->getParsedBody();

    $responseBody = array();
    $param = array();
    //capturamos los parametros recibidos y los almacenamos como un nuevo array
    $param['login']  = $data['login'];
    $param['password'] = $data['password'];
    
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();

    /* Podemos crear un metodo que almacene el nuevo auto, por ejemplo: */
    $login = $db->createSession($param, $request, $response);

    if ( is_array($login) ) {
        $responseBody["error"] = false;
        $responseBody["message_num"] = '001';
        $responseBody["message"] = $errorMessages['001'];
        $responseBody["token"] = $login['uuid'];
        $response->getBody()->write(json_encode($responseBody));

        session_write_close();  // Save Session

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);
    } else {
        $responseBody["error"] = true;
        $responseBody["message_num"] = '002';
        $responseBody["message"] = $errorMessages['002'];
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
});

// --------------------------------------------------------------------------------------

/* Usando POST para consultar Directorios */

$app->post('/dir', function(Request $request, Response $response) {
    global $errorMessages;
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // check for required params
    $param = $request->getParsedBody();
    $verify = verifyRequiredParams(array('path'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();

    $responseBody = array();

    $verify = $db->pathDirectory($param, $request, $response); // Control del path enviado
    
    if ($verify['error']) { // Si ha habido error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }

    /* Analizar directorio y obtener directorios y ficheros */
    $arr_row = $db->listDirectory($verify,$request, $response);


    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    $responseBody["message"] = $arr_row; 
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);

});
// --------------------------------------------------------------------------------------

/* Usando POST para Añadir  Documentos del directorio posicionado */

$app->post('/documentAdd', function(Request $request, Response $response) {

    global $errorMessages;
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // check for required params
    $param = $request->getParsedBody();

    $verify = verifyRequiredParams(array('code', 'name', 'locked'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }

    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();

    $USER_PRIV = $db->restoreUser($request, $response);  // Restauramos los campos del USER and data of Directory

    // Recuperar directorio y ficheros del último directorio
    $selectDirectory = $USER_PRIV['selectedDirectory'];

    $error = $db->accessDocumentWrite($param,$request, $response );   // Control acceso la directorio para escribir

    $responseBody = array();
    if ( $error <> '000') { // Si no es '000'' es que es error.
        $responseBody["error"] = true;
        $responseBody["message_num"] = $error;
        $responseBody["message"] =str_replace("{1}",$selectDirectory,$errorMessages[$error]);
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
    $error = $db->addDocument($param, $request, $response);  // Add row of Document

    $code = $param['code'];
    if ( !is_array($error)) { // Si no es '000'' es que es error.
        $responseBody["error"] = true;
        $responseBody["message_num"] = $error;
        $responseBody["message"] =str_replace("{1}",$code,$errorMessages[$error]);
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
    $lastID = $error['lastID'];    // last document INSERT
    // All OK
    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    $responseBody["message"] =  array("documentCreated" => $lastID);
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);

  
});
// --------------------------------------------------------------------------------------

/* Usando POST para view,update y delete ..... Documentos del directorio posicionado */

$app->put('/document/{action}/{id_document}', function(Request $request, Response $response, array $args) {

    global $errorMessages;
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // check for required params
    $param = array();
    $param['action'] = $args['action'];
    $param['id_document'] = $args['id_document'];

    $verify = verifyRequiredParams(array('action','id_document'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verificación de los valores de los parámetros || attributes
    if( !in_array($param['action'],array('view','update','delete')) || !is_numeric($param['id_document']))  { // Si la acción es correcta y el id es un número
        $responseBody["error"] = true;
        $responseBody["message_num"] = '013';
        $responseBody["message"] = $errorMessages['013'];
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
  
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();

    $data = $db->accessDocument($param,$request, $response );   // Control acceso la directorio y documento

    $id_document = $param['id_document'];     // CODE of File
    $responseBody = array();
    if ( !is_array($data)) { // Si no es array es que es error y si es array son los datos del documento
        $responseBody["error"] = true;
        $responseBody["message_num"] = $data;
        $responseBody["message"] = str_replace("{1}",$id_document,$errorMessages[$data]);
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
    
// --------------------------------------------------- VIEW -------------------------------------------------------
    if ( $param['action'] == 'view' ) { // VIEW}
        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] = $data; 
        $response->getBody()->write(json_encode($responseBody));

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);
    } 
// -------------------------------------------------- DELETE ---------------------------------------------------------
    if ( $param['action'] == 'delete' ) { // DELETE

        $db->deleteDocument($param); 

        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] =  str_replace("{1}",$id_document,$errorMessages['014']);
        $response->getBody()->write(json_encode($responseBody));

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);
    }
// -------------------------------------------------- UPDATE -----------------------------------------------------------
    if ( $param['action'] == 'update' ) { // UPDATE
        // check for required params
        $param2 = $request->getParsedBody();
        $verify = verifyRequiredParams(array('code', 'name', 'locked'), $param2, $request, $response);
        if (is_array($verify)) { // Si es una array, es que hay error
            $response->getBody()->write(json_encode($verify));
            return $response
                ->withHeader('content-type', 'application/json')
                ->withStatus(400);
        }
        $param2['id_document'] =  $id_document;
        $error = $db->updateDocument($param2, $request, $response);  // Update row of Document

        if ($error <> '000') { // ha habido error en la actualziación
            $responseBody["error"] = true;
            $responseBody["message_num"] = $error;
            $responseBody["message"] = str_replace("{1}",$param['code'],$errorMessages[$error]);
            $response->getBody()->write(json_encode($responseBody));
            return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);    
        }
   
        // All OK
        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] =  str_replace("{1}",$id_document,$errorMessages['017']);
        $response->getBody()->write(json_encode($responseBody));

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);

    }
});
// --------------------------------------------------------------------------------------
/* Usando POST para list, add, view, update y delete ..... ficheros de un Documento del directorio posicionado */

$app->put('/document/{id_document}/file/{action}', function(Request $request, Response $response, array $args) {

    global $errorMessages;
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // check for required params
    $param = array();
    $param['action'] = $args['action'];
    $param['id_document'] = $args['id_document'];

    $verify = verifyRequiredParams(array('action','id_document'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verificación de los valores de los parámetros || attributes
    if( !in_array($param['action'],array('list','add','view','update','delete')) || !is_numeric($param['id_document']))  { // Si la acción es correcta y el id es un número
        $responseBody["error"] = true;
        $responseBody["message_num"] = '013';
        $responseBody["message"] = $errorMessages['013'];
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
  
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();

    $data = $db->accessDocument($param,$request, $response );   // Control acceso la directorio y documento

    $id_document = $param['id_document'];     // CODE of File
    $responseBody = array();
    if ( !is_array($data)) { // Si no es array es que es error y si es array son los datos del documento
        $responseBody["error"] = true;
        $responseBody["message_num"] = $data;
        $responseBody["message"] = str_replace("{1}",$id_document,$errorMessages[$data]);
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
        // check for required params
        $param = $request->getParsedBody();

// --------------------------------------------------- LIST -------------------------------------------------------
if ( $args['action'] == 'list' ) { 
    $data = $db->listFile($param, $request, $response, $args );

    $id_document = $args['id_document'];
    if (!is_array($data)) { // Error 
        $responseBody["error"] = true;
        $responseBody["message_num"] = $data;
        $responseBody["message"] = str_replace("{1}",$id_document,$errorMessages[$data]);;
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    $responseBody["message"] = $data; 
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);
} 

// --------------------------------------------------- ADD -------------------------------------------------------
if ( $args['action'] == 'add' ) { 
    $verify = verifyRequiredParams(array('usrName','type','base64File'), $param, $request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    $data = $db->addFile($param, $request, $response, $args );
    $id_document = $args['id_document'];
    $usrName = $param['usrName'];

    if (!is_array($data)) { // Error 
        $responseBody["error"] = true;
        $responseBody["message_num"] = $data;
        $responseBody["message"] = str_replace("{2}",$usrName,str_replace("{1}",$id_document,$errorMessages[$data]));
        $response->getBody()->write(json_encode($responseBody));
        return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(400);
    }
    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    $responseBody["message"] = $data; 
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);
}  

// --------------------------------------------------- VIEW -------------------------------------------------------
    if ( $args['action'] == 'view' ) { 
        $verify = verifyRequiredParams(array('usrName'), $param, $request, $response);
        if (is_array($verify)) { // Si es una array, es que hay error
            $response->getBody()->write(json_encode($verify));
            return $response
                ->withHeader('content-type', 'application/json')
                ->withStatus(400);
        }
        $data = $db->viewFile($param, $request, $response, $args );
        $id_document = $args['id_document'];
        $usrName = $param['usrName'];

        if (!is_array($data)) { // Error 
            $responseBody["error"] = true;
            $responseBody["message_num"] = $data;
            $responseBody["message"] = str_replace("{2}",$usrName,str_replace("{1}",$id_document,$errorMessages[$data]));
            $response->getBody()->write(json_encode($responseBody));
            return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
        }
        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] = $data; 
        $response->getBody()->write(json_encode($responseBody));
    
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);
    }  
// -------------------------------------------------- DELETE ---------------------------------------------------------
    if ( $args['action'] == 'delete' ) { // DELETE

        $db->deleteDocument($param); 

        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] =  str_replace("{1}",$id_document,$errorMessages['014']);
        $response->getBody()->write(json_encode($responseBody));

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);
    }
// -------------------------------------------------- UPDATE -----------------------------------------------------------
    if ( $args['action'] == 'update' ) { // UPDATE
        // check for required params
        $param2 = $request->getParsedBody();
        $verify = verifyRequiredParams(array('code', 'name', 'locked'), $param2, $request, $response);
        if (is_array($verify)) { // Si es una array, es que hay error
            $response->getBody()->write(json_encode($verify));
            return $response
                ->withHeader('content-type', 'application/json')
                ->withStatus(400);
        }
        $param2['id_document'] =  $id_document;
        $error = $db->updateDocument($param2, $request, $response);  // Update row of Document

        if ($error <> '000') { // ha habido error en la actualziación
            $responseBody["error"] = true;
            $responseBody["message_num"] = $error;
            $responseBody["message"] = str_replace("{1}",$param['code'],$errorMessages[$error]);
            $response->getBody()->write(json_encode($responseBody));
            return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);    
        }
   
        // All OK
        $responseBody["error"] = false;
        $responseBody["message_num"] = '000';
        $responseBody["message"] =  str_replace("{1}",$id_document,$errorMessages['017']);
        $response->getBody()->write(json_encode($responseBody));

        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(200);

    }
});

// --------------------------------------------------------------------------------------
/* Usando POST para las variablers de session */

$app->post('/session', function(Request $request, Response $response) {
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();
    $USER_PRIV = $db->restoreUser($request, $response);

    $responseBody = array();

    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    // $responseBody["_SESSION"] =  $_SESSION; 
    $responseBody["USER_PRIV"] =  $USER_PRIV; 
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);
// --------------------------------------------------------------------------------------
});
// --------------------------------------------------------------------------------------
/* Usando GET para obtener la información del usuario conectado */

$app->get('/user', function(Request $request, Response $response) {
    /* Include functions required for the execution of the actions */
    include_once '../include/Function.php';   

    // Verify Token Authenticate Security
    $verify = authenticate($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    // Verify Token of Access
    $verify = controlSession($request, $response);
    if (is_array($verify)) { // Si es una array, es que hay error
        $response->getBody()->write(json_encode($verify));
        return $response
            ->withHeader('content-type', 'application/json')
            ->withStatus(400);
    }
    /* Podemos inicializar la conexion a la base de datos si queremos hacer uso de esta para procesar los parametros con DB */
    require_once '../include/DbEdas.php';
    $db = new DbEdas();
    $USER_PRIV = $db->restoreUser($request, $response);

    $responseBody = array();

    $responseBody["error"] = false;
    $responseBody["message_num"] = '000';
    $responseBody["message"] =  $USER_PRIV['dataUser']; 
    $response->getBody()->write(json_encode($responseBody));

    return $response
        ->withHeader('content-type', 'application/json')
        ->withStatus(200);
// --------------------------------------------------------------------------------------
});

/* corremos la aplicación */
$app->run();

/*********************** USEFULL FUNCTIONS **************************************/

