<?php

class Schema{
    private $con;
    private $database;
    private $ubicacion_archivos;
    private $file_size;
    private $clave_elemento;
    private $resize_img;
    public $e;


    public function __construct($con, $database = FALSE){
        $this->con = $con;
        if($database) {
            $this->database = $database;
        }
    }

    public function selectAll($table){
        $array = [];
        $sql = 'SELECT * FROM ' . $table;
        $res = $this->con->query($sql);
        while($row = $res->fetch_array()){
            $array[] = $row;
        }
        return $array;
    }

    public function executeQuery($sql, $types = null, $params = null){//Traer en una linea de codigo la petición de las bbdd
        try{
            $stmt = $this->con->prepare($sql);
            //foreach ($params as $aux){var_dump($aux);echo "<br>";}
            $stmt->bind_param($types, ...$params);
            if(!$stmt->execute()){
                echo 'No se ha podido ejecutar la consulta sql</br>'.$sql.'</br>';
                echo "</pre>"; var_dump($types);echo "</pre>";echo '</br></br>';
                echo "</pre>"; var_dump($params);echo "</pre>";echo '</br></br>';
                return false;
            }
            return $stmt->get_result();
        } catch (Throwable $ex) {
            echo 'Ha habido un error al ejecutar la peticion sql'. $ex->getMessage();
            return FALSE;
        }
    }

    private function count_biblioteca_etiquetas($clave) {
        $esq = -1;
        $sql = "UPDATE BIBLIOTECA_ELEMENTOS 
        SET NUMETI = (SELECT COUNT(CLAVE) AS NETI FROM BIBLIOTECA_ETIQUETAS WHERE CLAVE = ? AND ESQUEMA<>?)
        WHERE CLAVE = ?";
        $stmt = $this->con->prepare($sql);
        $stmt->bind_param('sis', $clave, $esq, $clave);
        $stmt->execute();
    }

    public function set_clave_elemento ($clave_elemento) {
        //ASIGNAR UN VALOR PARA CLAVE_ELEMENTO
        $this->clave_elemento = $clave_elemento;
        return $this;
    }

    public function get_clave_elemento () {
        //MOSTRAR VALOR PARA CLAVE ELEMENTO
        return $this->clave_elemento;
    }

    public function set_ubicacion_archivos($ubicacion_archivos) {
        //ASIGNAR UNA RUTA
        $this->ubicacion_archivos = $ubicacion_archivos;
        return $this;
    }

    public function get_ubicacion_archivos() {
        //MOSTRAR LA RUTA
        return $this->ubicacion_archivos;
    }

    public function set_file_size($file_size) {
        $this->file_size = $file_size;
        return $this;
    }
    
    public function get_file_size() {
        return $this->file_size;
    }

    public function set_resize_img($resize_img) {
        //TRUE PARA IMAGENES / FALSE PARA DOCUMENTOS
        $this->resize_img = $resize_img;
        return $this;
    }

    public function get_resize_img() {
        return $this->resize_img;
    }

    public function select_expediente_tipos_valores ($alias, $campo = 'CODIGO') {
        $sql = "SELECT * FROM EXPEDIENTES_TIPOS WHERE ALIAS = '$alias'";
        $res = $this->con->query($sql);
        $fila = $res->fetch_array();
        //$campo = $campo ? $campo : 'CODIGO';// Cambiando la cabecera es suficiente (antes false)
        return $fila[$campo];
    }

    public function select_esquema_estructura_valores ($alias, $esquema, $campo = 'CODIGO') {
        $sql = "SELECT * FROM ESQUEMAS_ESTRUCTURA WHERE ESQUEMA = $esquema AND ALIAS = '$alias'";
        $res = $this->con->query($sql);
        $fila = $res->fetch_array();
        //$campo = $campo ? $campo : 'CODIGO';
        return $fila[$campo];
    }

    /*
    //$originalFile = archivo original / tmp_name
    //$new_size = el tamaño del archivo , dividirlo por 100 si no se utiliza en un expediente
    //$name = el nombre del archivo
    //$ubicacion_archivos = es la ubicacion donde se guarda el archivo, se puede cambiar con las funciones set_ubicacion_archivos / get_ubicacion_archivos, son metodos encadenados
     */
    public function resize_img ($originalFile, $new_size, $name, $ubicacion_archivos = 'uploads/') { 
        $info = getimagesize($originalFile);
        $mime = $info['mime'];  

        switch ($mime) {
            case 'image/jpeg':
                    $image_create_func = 'imagecreatefromjpeg';
                    $image_save_func = 'imagejpeg';
                    $new_image_ext = 'jpg';
                    break;
            case 'image/png':
                    $image_create_func = 'imagecreatefrompng';
                    $image_save_func = 'imagejpeg';
                    $new_image_ext = 'jpg';
                    break;
            case 'image/gif':
                    $image_create_func = 'imagecreatefromgif';
                    $image_save_func = 'imagejpeg';
                    $new_image_ext = 'jpg';
                    break;
            case 'image/webp':
                    $image_create_func = 'imagecreatefromwebp';
                    $image_save_func = 'imagejpeg';
                    $new_image_ext = 'jpg';
                    break;
            default: 
                    $image_create_func = 'imagecreatefromjpeg';
                    $image_save_func = 'imagejpeg';
                    $new_image_ext = 'jpg';
                    break;
        }

        $img = $image_create_func($originalFile);
        list($width, $height) = getimagesize($originalFile);

        //$new_size = 2000;
        $newHeight = ($height / $width) * $new_size;
        $tmp = imagecreatetruecolor($new_size, $newHeight);
        imagecopyresampled($tmp, $img, 0, 0, 0, 0, $new_size, $newHeight, $width, $height);

        $new_file_in_folder = $ubicacion_archivos . $name;
        if (!is_dir($ubicacion_archivos)){
            mkdir($ubicacion_archivos);
        }
        else
        if (file_exists($new_file_in_folder)) {
            unlink($new_file_in_folder);
        }
        $image_save_func($tmp, $new_file_in_folder);
    }

    /*
    //$clave, ubicacion y resize_img se llamaran desde fuera con los metodos set, la clave se debe guardar en una variable para hacer ulteriormente el insert en biblioteca_etiquetas;
    //$tmp = documento temporal
    //$name = el nombre del archivo
    //$size = tamaño del archivo
    //$clave_expediente = la clave del expediente existente/creado
    //$acceso = el acceso del expediente
    //$ubicacion = el la ubicacion del exediente + ubicacion año
    //$posicion = cuando se suben imágenes principales tienen que tener un orden, donde 1 es la foto principal y en caso contrario 0 no se requiere mostrar un orden
     */
    public function upload_doc ($tmp, $name, $size, $clave_expediente, $acceso, $ubicacion, $usuarioSession, $codigo_vehiculo, $posicion = 0) {
        //$posicion = $posicion ? $posicion : 0;
        $parte = 1;
        $version = 0;
        $tipo = 'D';
        $ambito = 'PUB';
        $ordenador = gethostname().'(WEB)';
        $clave = $this->clave_elemento;
        $entrada = date( "YmdHis" ) . sprintf( "%04d", rand( 0, 9999 ) );
        $id_unico = date( "YmdHis" ) . sprintf( "%04d", rand( 0, 9999 ) );
        $part = pathinfo($name);
        $extension = strtoupper($part['extension']) == 'JPG' ? 'JPG' : strtoupper($part['extension']);
        /* $extension = "JPG"; */
        $nombre_sin_extension = basename($name,".$extension");

        $sqlParamTable = "SELECT VALOR FROM PARAMETROS WHERE CODIGO = ?";
        $resParamTable = $this->executeQuery($sqlParamTable, 's', ['TAM_TABLABLOB']);
        $filaParamTable = $resParamTable->fetch_array();
        $paramGb = $filaParamTable['VALOR'];

        /* $ubicacion_archivos = $ubicacion_archivos ? $ubicacion_archivos : 'uploads/'; */
        $ubicacion_archivos = $this->ubicacion_archivos;
        
        $max_width = 2000;
        
        // Comprueba si el ancho de la imagen es superior a lo permitido
        if($this->resize_img && getimagesize($tmp)[0] > $max_width) {
            $this->resize_img($tmp, $max_width, $nombre_sin_extension, $ubicacion_archivos);
            $size = filesize($ubicacion_archivos . $nombre_sin_extension);
        } else {
        // Si es inferior, no redimensiona y sube la imagen sin modificar
            if (!is_dir($ubicacion_archivos)){
                mkdir($ubicacion_archivos);
            }
            copy($tmp, $ubicacion_archivos . $nombre_sin_extension);
        }
        $item = $ubicacion_archivos . $nombre_sin_extension;
        $ruta = fopen($item,"r");
        $doc_binario = fread($ruta,filesize($item));
        fclose($ruta);

        $sqlTable = "SELECT TABLE_NAME,ROUND(DATA_LENGTH/(1024*1024*1024),1) AS GB
                    FROM INFORMATION_SCHEMA.TABLES
                    WHERE TABLE_SCHEMA = ?
                    AND TABLE_NAME LIKE 'FICHEROS_2%'
                    AND (ROUND(DATA_LENGTH/(1024*1024*1024),1) + ROUND(?/(1024*1024*1024),1)) < (ROUND(?,1))
                    ORDER BY DATA_LENGTH LIMIT 1";
        $stmt = $this->con->prepare($sqlTable);
        $stmt->bind_param('sii',$this->database,$size,$paramGb);
        $stmt->execute();
        $resTable = $stmt->get_result();
        if($resTable->num_rows){
            $filaTable = $resTable->fetch_array();
            $table_name = $filaTable['TABLE_NAME'];
            $explode = explode("_",$table_name);
            $sufijo = $explode[1];
        }else{
            $sufijo = substr($id_unico,0, 14);
            $sqlCreateTable = "CREATE TABLE `FICHEROS_$sufijo` (
                `CLAVE` VARCHAR(18) NOT NULL DEFAULT '',
                `PARTE` INT(11) NOT NULL DEFAULT '0',
                `VERSION` VARCHAR(8) NOT NULL DEFAULT '',
                `FICHERO` LONGBLOB NULL,
                `TAMANO` DOUBLE(15,0) NULL DEFAULT '0',
                `ENTRADA` VARCHAR(18) NULL DEFAULT '',
                `COMPRIMIDO` INT(11) NULL DEFAULT '0',
                `TAMANOREAL` DOUBLE(15,0) NULL DEFAULT '0',
                `ENCRIPTADO` INT(11) NULL DEFAULT '0',
                `FECHA` DATETIME NULL DEFAULT NULL,
                `USUARIO` VARCHAR(50) NULL DEFAULT NULL,
                PRIMARY KEY (`CLAVE`, `PARTE`, `VERSION`),
                INDEX `TAMANO` (`TAMANO`),
                INDEX `ENTRADA` (`ENTRADA`)
            )
            COLLATE='latin1_swedish_ci'
            ENGINE=MyISAM
            ;";
            $resCreateTable = $this->con->query($sqlCreateTable);
            $table_name = "FICHEROS_$sufijo";
        }

        if ( $size > 16777216 ) {
            $array = str_split($doc_binario, 16777216);
            foreach ($array as $key => $value) {
                $sql = "INSERT INTO $table_name(CLAVE,PARTE,VERSION,FICHERO,TAMANO,ENTRADA,TAMANOREAL) 
                    VALUES(?,?,?,?,?,?,?)";
                $stmt = $this->con->prepare($sql);
                $stmt->bind_param('siisisi',$clave,$parte,$version,$value,$size,$entrada,$size);
                $stmt->execute();
                $parte++;
            }
        }else{
            $sql = "INSERT INTO $table_name(CLAVE,PARTE,VERSION,FICHERO,TAMANO,ENTRADA,TAMANOREAL) 
                    VALUES(?,?,?,?,?,?,?)";
            $stmt = $this->con->prepare($sql);
            $stmt->bind_param('siisisi',$clave,$parte,$version,$doc_binario,$size,$entrada,$size);
            $stmt->execute();
        }

        $padreDOC = $clave_expediente;
        $nombre_con_extension = $nombre_sin_extension . "." . $extension;
        $sqlBE = "INSERT INTO BIBLIOTECA_ELEMENTOS(CLAVE,NOMBRE,EXTENSION,PADRE,ACCESO,UBICACION,TIPO,FECHA,TAMANO,AMBITO,CREADOR,ORDENADOR,MODIFICACION,PARTES,ENTRADA,SUFIJO,POS) VALUES('$clave','$nombre_con_extension','$extension','$padreDOC','$acceso','$ubicacion','$tipo',NOW(),$size,'$ambito','$usuarioSession','$ordenador',NOW(),$parte,'$entrada',$sufijo,$posicion)";
        $this->con->query($sqlBE);
        unlink($item);
    }

    public function select_esquema_con_alias($alias) {
        $res = $this->con->query("SELECT CODIGO FROM ESQUEMAS WHERE ALIAS = '$alias'");
        $row = $res->fetch_array();
        return $row['CODIGO'];
    }

    public function select_esquema_o_esquema_estructura ($codigo_esquema = FALSE) {
        $sqlEsq = "SELECT CODIGO FROM ESQUEMAS WHERE ALIAS = 'DOC_VEHICULO'";
        $resEsq = $this->con->query($sqlEsq);
        $filaEsq = $resEsq->fetch_array();
        $sqlEsq2 = "SELECT CODIGO FROM ESQUEMAS_ESTRUCTURA WHERE ESQUEMA = " . $filaEsq['CODIGO'] . " AND ALIAS = 'VEHICULO'";
        $resEsq2 = $this->con->query($sqlEsq2);
        $filaEsq2 = $resEsq2->fetch_array();
        return $codigo_esquema ? $filaEsq['CODIGO'] : $filaEsq2['CODIGO'];
    } 

    public function asignar_etiquetas_nuevo_expediente ($codigo_bib_etiq, $codigo_vehiculo, $mostrar, $tag_for_img = FALSE, $pubicable_par = FALSE) {
        //$codigo_bib_etiq = get_id_unico();
        //$pubicable = es si se quiere hacer publicable o no 1 si 2 no
        global $si_lg;
        global $no_lg;

        $pubicable = $pubicable_par ? 1 : 2;
        $descripcion_codigo = date( "YmdHis" ) . sprintf( "%04d", rand( 0, 9999 ) );

        $clave = $this->clave_elemento;
        $esquema = $this->select_esquema_o_esquema_estructura(TRUE); 
        $grupoe = 1;
        $sqlGr1 = "INSERT INTO BIBLIOTECA_ETIQUETAS(CODIGO,CLAVE,DESCRIPCION,GRUPOE,ESQUEMA,FECHA) 
        VALUES(" . $codigo_bib_etiq . ", '$clave'," . $descripcion_codigo . ", $grupoe, $esquema, NOW())";
        $this->con->query($sqlGr1);

        $grupoEE = $this->select_esquema_estructura_valores('FECHA', $esquema);
        $ordenEE = $this->select_esquema_estructura_valores('FECHA', $esquema, 'ORDEN') - 1;
        $descripcion = date('d/m/Y');
        $vfecha = date('Y-m-d');
        $sqlGr2 = "INSERT INTO BIBLIOTECA_ETIQUETAS(CODIGO,CLAVE,DESCRIPCION,GRUPOE,ESQUEMA,FECHA,ORDEN,VFECHA,PADRE)
                    VALUES(" . get_id_unico() .", '$clave', '$descripcion', $grupoEE, $esquema,NOW(),$ordenEE,'$vfecha','$codigo_bib_etiq')";
        $this->con->query($sqlGr2);

        if($tag_for_img) {
            $grupoEE = $this->select_esquema_estructura_valores('TIPO',$esquema);
            $ordenEE = $this->select_esquema_estructura_valores('TIPO',$esquema, 'ORDEN') - 1;
            $tipoEE = $this->select_esquema_estructura_valores('TIPO',$esquema, 'TIPO');
            $listaEE = $this->select_esquema_estructura_valores('TIPO',$esquema, 'LISTA');
            $descripcion = 'FOTO';
            $sqlTipoLC = "SELECT CODIGO FROM ETIQUETAS WHERE GRUPO = $listaEE AND DESCRIPCION = 'FOTO'";
            $resTipoLC = $this->con->query($sqlTipoLC);
            $filaTipoLC = $resTipoLC->fetch_array(); 
            $sqlGr3 = "INSERT INTO BIBLIOTECA_ETIQUETAS(CODIGO,CLAVE,DESCRIPCION,GRUPO,ETIQUETA,GRUPOE,ESQUEMA,FECHA,ORDEN,PADRE)
            VALUES(" . get_id_unico() . ", '$clave', '$descripcion',  $listaEE, " . $filaTipoLC['CODIGO'] . ", $grupoEE, $esquema, NOW(), $ordenEE,'$codigo_bib_etiq')";
            $this->con->query($sqlGr3);
        }

        $grupoEE =  $this->select_esquema_estructura_valores('VEHICULO',$esquema);
        $ordenEE =  $this->select_esquema_estructura_valores('VEHICULO',$esquema, 'ORDEN') - 1;
        $tipoEE =  $this->select_esquema_estructura_valores('VEHICULO',$esquema, 'TIPO');
        $listaEE =  $this->select_esquema_estructura_valores('VEHICULO',$esquema, 'LISTA');
        $sqlGr4 = "INSERT INTO BIBLIOTECA_ETIQUETAS(CODIGO,CLAVE,DESCRIPCION,GRUPOE,ESQUEMA,FECHA,ORDEN,PADRE,ETIQUETA)
        VALUES(" . get_id_unico() . ", '$clave','$mostrar', $grupoEE, $esquema, NOW(), $ordenEE,'$codigo_bib_etiq', $codigo_vehiculo)";
        $this->con->query($sqlGr4);

        $descripcion = $pubicable === 1 ? $si_lg : $no_lg;
        $esquema = $this->select_esquema_o_esquema_estructura(true);
        $grupoEE =  $this->select_esquema_estructura_valores('PUBLICABLE', $esquema);
        $ordenEE =  $this->select_esquema_estructura_valores('PUBLICABLE', $esquema, 'ORDEN') - 1;
        $tipoEE =  $this->select_esquema_estructura_valores('PUBLICABLE', $esquema, 'TIPO');
        $listaEE =  $this->select_esquema_estructura_valores('PUBLICABLE', $esquema, 'LISTA');
        $now = date('Y-m-d H:i:s');

        $sql = "INSERT INTO BIBLIOTECA_ETIQUETAS(CODIGO,CLAVE,DESCRIPCION,GRUPO,ETIQUETA,GRUPOE,ESQUEMA,FECHA,ORDEN,PADRE)
        VALUE(?,?,?,?,?,?,?,?,?,?)";
        $this->executeQuery($sql, 'sssisiisis', [get_id_unico(), $clave, $descripcion, $listaEE, $pubicable, $grupoEE, $esquema, $now, $ordenEE, $codigo_bib_etiq]);

        $this->count_biblioteca_etiquetas($clave);
    }

    public function create_file ($tmp_file, $values, $sufijo, $clave, $version = FALSE) {
        //$tmp_file = archivo temporal
        //$values = son las partes que se reciben de fuera
        //$sufijo = el codigo que de la tabla
        if(file_exists($tmp_file)){
            unlink($tmp_file);
        }
        $version = $version ? $version : 0;
        $create_img = fopen($tmp_file,'a');
        for($i = 1; $i <= $values; $i++){
            $sqlPartes = "SELECT FICHERO
                        FROM FICHEROS_$sufijo 
                        WHERE CLAVE = " . $clave . " 
                        AND PARTE = $i
                        AND VERSION = '$version'";
            $resPartes = $this->con->query($sqlPartes);
            if($resPartes->num_rows) {
                $filaPartes = $resPartes->fetch_array();        
                $img = fwrite($create_img,$filaPartes['FICHERO']);
            } else {
                $sql = "SELECT FICHERO
                        FROM FICHEROS_$sufijo 
                        WHERE CLAVE = " . $clave . " 
                        AND PARTE = $i
                        AND VERSION = '0'";
                $res = $this->con->query($sql);
                $row = $res->fetch_array();      
                $img = fwrite($create_img,$row['FICHERO']);
            }
        }
        fclose($create_img);
        return TRUE; 
    }

}