<?php
/*
  Class SuperWidget
 */

class SuperWidget {

    const CLASS_NAME = 'Widget';

    //Cuatro parámetros fijos:
    //	Tipo: php|js
    //	Nombre: Nombre del widget a cargar. Se corresponda con la función principal del widget
    //	Función a ejecutar: Función del widget que se va a ejecutar
    //	Ejecutar al iniciar: Si todo ha ido bien, con este parámetro indicaremo ssi queremos ejecutar, al crearse el objeto, el script del widget
    //El resto de los parámetros se incluirá  en un array
    private $tipo = 'php'; //El tipo sólo se puede modificar utilizando una función. Es necesario porque hay que hacer recálculos
    public $nombre = '';
    public $funcion = '';
    public $parametros = array();
    private $tipos_permitidos = array('php', 'modal', 'dropDown', 'dropRight', 'dropLeft', 'dropUp', 'fixedDropDown', 'fixedDropUp', 'fixedDropRight', 'fixedDropLeft'); //Tipos permitidos
    public $id = '';
    public $html_previo = '';
    public $html_posterior = '';
    private $recording = false;
    private $opciones = NULL;
    private $opcionesWidget = NULL;
    public $error = ''; //Último error que se haya producido al crear el widget

    public function __construct() {
        //Modificado por Pedro el 28/Junio/2017 para que la función no tenga porqué recibir nada
        //Posteriormente recalculamos sus parámetros.
        $array_parametros = func_get_args();
        //var_dump($array_parametros);
        $widgetVacio = true;
        if (count($array_parametros) != 0) {
            if ($array_parametros[0] != NULL) {
                $widgetVacio = false;
            }
        }

        if ($widgetVacio) {
            //Tenemos un widget vacío
        } else {
            /*echo("<pre>");
            var_dump($array_parametros);
            echo("</pre>");*/
            $array_parametros = $array_parametros[0];
            //Es posible que lo que recibamos sea un string, en cuyo caso es sólo el nombre del widget
            if (gettype($array_parametros) == 'string') {
                $this->nombre = $array_parametros;
                $this->funcion = '';
                $this->tipo = 'php';
                $this->ejecutar = true;
                $this->opciones = NULL;
            } else {
                //Recogemos el array recibido y metemos los valores en las variables locales necesarias
                $array_valores = array('nombre' => '', 'funcion' => '', 'tipo' => 'php', 'ejecutar' => true, 'opciones' => NULL);
                //var_dump($array_parametros);
                foreach ($array_parametros as $clave => $valor) {
                    $array_valores[$clave] = $valor;
                }
                $this->nombre = $array_valores['nombre'];
                $this->funcion = $array_valores['funcion'];
                $this->tipo = $array_valores['tipo'];
                $this->tipo = str_replace("'", "", $this->tipo);
                $this->tipo = str_replace('"', "", $this->tipo);
                $this->ejecutar = $array_valores['ejecutar'];
                $this->opciones = $array_valores['opciones'];
            }
        }
        //Sólo continuamos si el tipo es correcto
        if (!in_array($this->tipo, $this->tipos_permitidos)) {
            $this->tipo = "php";
        }

        if ($this->nombre != "") {
            //Por seguridad, al tipo le vamos a quitar las comillas simples que pueda tener
            $this->nombre = "widget_" . $this->nombre;
            //Tenemos el tipo y el nombre. vamos a ver si se han recibido más parámetros
            $num_params = func_num_args();
            //Si el número de parámetros es mayor que 4 (los que se auto-rellenan) entonces significa que nos han pasado más parámetros
            //echo("<pre>Comienzo\n");
            //var_dump($this->parametros);
            if ($num_params > 1) {
                unset($this->parametros);
                $this->parametros = array_slice(func_get_args(), 1);
            }
            //var_dump($this->parametros);
            //if ($this->funcion != ""){
            //La función va al principio del array
            array_unshift($this->parametros, $this->funcion);
            //}
            //var_dump($this->parametros);
            //echo("Fin\n</pre>");
            //Entre los parámetros del widget, es posible que haya alguno del tipo "opcionesWidget". Si lo hay, lo metemos en la variable indicada
            foreach ($this->parametros as $clave => $valor) {
                if (is_a($valor, 'OpcionesWidget')) {
                    $this->opcionesWidget = $valor;
                    break;
                }
            }

            //Por último, si el cliente quiere ejecutar el widget directamente, lo hacemos:
            if ($this->ejecutar) {
                $this->mostrar();
            }
        } else {
            $this->error = 'Debe especificar el nombre del widget a ejecutar';
        }
    }

    public function mostrar() {
        include('comunes/globals.php');
        $retorno = NULL;
        //echo("Mostramos Widget");
        //No hacemos nada si la función no tiene el nombre del widget a ejecutar y el código html está vacío
        if (!( ($this->nombre == '') && ($this->html_previo == '') && ($this->html_posterior == '') )) {
            //Según el tipo, hacemos una cosa u otra
            $codigo_inicio = '';
            $codigo_fin = '';
            $visibilidad_capa = ( $noInicializarWidgets ) ? '' : 'visibility:hidden;';
            $id = $this->nombre . '_' . incrementa_contador(true);
            switch ($this->tipo) {
                case 'modal':
                    $codigo_inicio = '<div class="webStoreWindow" style="' . $noInicializarWidgets . '" id="' . $id . '"><div class="contenidoWebstoreWindow">';
                    $codigo_fin = "</div></div>";
                    break;
                case 'dropDown':
                case 'fixedDropDown':
                    $codigo_inicio = '<div class="webStoreDropDown" style="' . $noInicializarWidgets . '" id="' . $id . '">';
                    $codigo_fin = "</div>";
                    break;
                case 'dropRight':
                case 'fixedDropRight':
                    $codigo_inicio = '<div class="webStoreDropRight" style="' . $noInicializarWidgets . '" id="' . $id . '">';
                    $codigo_fin = "</div>";
                    break;
                case 'dropLeft':
                case 'fixedDropLeft':
                    $codigo_inicio = '<div class="webStoreDropLeft" style="' . $noInicializarWidgets . '" id="' . $id . '">';
                    $codigo_fin = "</div>";
                    break;
                case 'dropUp':
                case 'fixedDropUp':
                    $codigo_inicio = '<div class="webStoreDropUp" style="' . $noInicializarWidgets . '" id="' . $id . '">';
                    $codigo_fin = "</div>";
                    break;
            }
            echo($codigo_inicio);

            //Si tenemos código html lo ejecutamos primero
            if ($this->html_previo != '') {
                echo($this->html_previo);
            }

            if ($this->nombre != '') {
                //echo("llamada a la función " . $this->nombre . " con los parámetros: ");
                //Ahora ejecutamos la función definida siempre y cuando esté definida
                if (function_exists($this->nombre)) {
                    /* echo("llamada a la función " . $this->nombre . " con los parámetros: ");
                      var_dump($this->parametros);
                      echo("<br />");
                     */
                    call_user_func_array($this->nombre, $this->parametros);
                }
            } else {
                $this->error = 'la función ' . $this->nombre . ' no existe<br />\n';
            }

            //Si tenemos html posterior, lo mostramos
            if ($this->html_posterior != '') {
                echo($this->html_posterior);
            }

            echo($codigo_fin);
            $this->id = $retorno = $id;

            //Después de haber mostrado el elemento, vamos a añadirle el script que nos lo mete en los componentes
            if ($this->tipo != 'php') {
                $opciones = $this->opciones;
				/*echo("<pre>");
				echo("Hemos recibido esto: \n");
				var_dump($opciones);
				echo("</pre>");*/
                //Hay que preparar las opciones
                if ($opciones == NULL) {
                    //Con el tipo vamos a definir unas opciones 'pre-definidas'
                    $opciones = new ObOptions();
                    $opciones->centerH = 'false';
                    $opciones->centerV = 'false';
                    $opciones->transBackground = 'false';
                    $opciones->closeButton = 'false';
                    $opciones->inSpeed = "'slow'";
                    $opciones->zindex = 10;
                    switch ($this->tipo) {
                        case 'modal':
                            $opciones->fixedPosition = 'true';
                            $opciones->centerH = 'true';
                            $opciones->centerV = 'true';
                            $opciones->closeButton = 'true';
                            $opciones->transBackground = 'true';
                            $opciones->zindex = 150;
                            break;
                        case 'dropDown':
                            $opciones->positionY = "'parent_b'";
                            $opciones->positionX = "'parent_l'";
                            $opciones->pivot = "'lt'";
                            break;
                        case "dropRight":
                            $opciones->positionX = "'parent_l'";
                            $opciones->positionY = "'parent_t'";
                            $opciones->pivot = "'lt'";
                            break;
                        case "dropLeft":
                            $opciones->positionX = "'parent_r'";
                            $opciones->positionY = "'parent_t'";
                            $opciones->pivot = "'rt'";
                            break;
                        case "dropUp":
                            $opciones->positionX = "'parent_l'";
                            $opciones->positionY = "'parent_b'";
                            $opciones->pivot = "'lb'";
                            break;
                    }
                } else {
					//Vamos a convertir opciones a un objeto ObOptions para maximizar la compatibilidad
					$opciones = new ObOptions($opciones);
					//$opciones = $this->opciones;
					/*echo("<pre>");
					var_dump($opciones);
					echo("</pre>");*/
                    //echo("Hemos recibido opciones<br />\n");
                }
                //Si no hay tipo, entonces cogemos el del widget
                if ($opciones->type == NULL) {
                    //El tipo siempre será el mismo que el definido aquí para evitar problemas
                    $opciones->type = "'" . $this->tipo . "'";
                }
				//Pedro 03/Abril/2019 ==> Ya no hay "muestraOpciones", el propio widget hará esto:
                //$cadena_opciones = $opciones->muestra_opciones('componente_' . $retorno);
				//$cadena_opciones = 'var componente_' . $retorno . ' = ' . json_encode($opciones) . ';';
				$cadena_opciones = 'var componente_' . $retorno . ' = ' . obOptions::sToJs($opciones) . ';';
				
                //Quitamos el símbolo del dolar a las opciones
                $cadena_opciones = str_replace('$', '', $cadena_opciones);
                $script_id = 'script_' . incrementa_contador(true);
                ?>
                <script type="text/javascript" id="<?= $script_id; ?>">
				document.addEventListener('WSLE', function(event) {
                    ;(function () {
                <?= $cadena_opciones . "\n"; ?>
                        var elementObjetive = getLastHtmlObject('<?= $script_id; ?>');
						var supercalifragilistico = 0;
                        var index = componentList.add(elementObjetive, <?= "componente_" . $retorno; ?>);
                    }());
				});
                </script>
                <?php
            }
        }
        return($retorno);
    }

    public function addTexto($texto, $posicion = false) {
        //Si la posición es false, es codigo anterior, si no es posterior
        if ($posicion) {
            $this->html_posterior .= $texto;
        } else {
            $this->html_previo .= $texto;
        }
    }

    public function record($posicion = "false") {
        //Si la posición es false, es codigo anterior, si no es posterior
        //Si estamos grabando, dejamos de grabar recogiendo lo grabado y añadiéndolo a html
        if ($this->recording) {
            if ($posicion) {
                $this->html_posterior .= ob_get_contents();
            } else {
                $this->html_previo .= ob_get_contents();
            }
            ob_end_clean();
            $this->recording = false;
        } else {
            ob_start();
            $this->recording = true;
        }

        return($this->recording);
    }

    public function cambia_tipo($tipo) {
        if (!in_array($tipo, $this->tipos_permitidos)) {
            $tipo = 'php';
        }
        $this->tipo = $tipo;
    }

    //Métodos mágicos de este objeto
    public function __get($variable) {
        $retorno = NULL;
        if (isset($this->$variable)) {
            $retorno = $this->$variable;
        }
        return($retorno);
    }

    public function __set($variable, $valor) {
        if (!isset($this->$variable)) {
            $this->$variable = NULL;
        }
        $this->$variable = $valor;
    }

    public function __isset($variable) {
        $retorno = false;
        if (isset($this->$variable)) {
            $retorno = true;
        }
        return($retorno);
    }

    //De momento el invoke no sirve en nuestra versión de php
    public function __invoke() {
        $this->mostrar();
    }

}
?>