Mapeate.Base = function(mapeate, entradas){

    const self = this, 
          base_cache = {x : 0, y : 0}, 
          posicion_de_raton = {x : 0, y : 0};
    let iniciado = false, 
        base_hilo, 
        construido = false;

    const constructor = () => {

        mapeate.print("info", "mapeate_base_construyendose");

        mapeate.print("ok", "mapeate_base_construido");
    
    };

    this.iniciar = callback => {

        const terminar = estado => typeof callback == "function" && callback(estado);

        if(iniciado){
            terminar(false);
            return false;
        };
        iniciado = true;

        self.construir(() => {
            mapeate.print("ok", "base_construida");
            terminar(true);
        });

        return true;
    };

    const base_hilo_metodo = () => {

        if(mapeate.si_mismo && (base_cache.x != mapeate.si_mismo.offsetWidth || base_cache.y != mapeate.si_mismo.offsetHeight) && mapeate.si_mismo.getAttribute){

            const minimo = Number(mapeate.si_mismo.getAttribute("data-celdas-minimo"));
            let tamano;

            base_cache.x = mapeate.si_mismo.offsetWidth;
            base_cache.y = mapeate.si_mismo.offsetHeight;

            tamano = base_cache[base_cache.x < base_cache.y ? "x" : "y"] / Number(mapeate.si_mismo.getAttribute("data-celdas"));

            mapeate.si_mismo.style.fontSize = (tamano < minimo ? tamano = minimo : tamano) + "px";
            mapeate.si_mismo.setAttribute("data-menu-principal-completo", base_cache.x / tamano > 50);

        };

    };

    this.construir = callback => {

        const terminar = estado => typeof callback == "function" && callback(estado);

        if(construido){
            terminar(false);
            return false;
        };
        construido = true;
        
        mapeate.vistas.establecer(mapeate.configuracion("posicion_html"), "base", {
            clases : "", 
            link_local : "#", 
            logo : mapeate.configuracion("logo"), 
            hash : mapeate.coger_hash(), 
            menu_principal : mapeate.vistas.crear_elementos_de_menu("elemento_menu_principal", mapeate.configuracion("menu_principal")), 
            menu_links : mapeate.vistas.crear_elementos_de_menu("elemento_menu_links", mapeate.configuracion("menu_links")), 
            lista_mapas : mapeate.mapas.selector.crear_lista(), 
            parametros_raiz : {
                aplicacion : mapeate.configuracion("aplicacion"), 
                link : mapeate.configuracion("link"), 
                git : mapeate.configuracion("git"), 
                organizacion : mapeate.configuracion("organizacion"), 
                celdas : mapeate.configuracion("celdas"), 
                celdas_minimo : mapeate.configuracion("tamano_minimo_celda"), 
                onmousemove : mapeate.nombre_objeto + ".base.capturar_cursor(this, event);"
            }
        }, () => {

            mapeate.establecer_si_mismo(document.querySelector("#" + mapeate.hash_self));

            base_hilo = mapeate.anadir_hilo_de_proceso(base_hilo_metodo);

            terminar(true);

        });

        return true;
    };

    this.coger_posicion_del_cursor = evento => {

        const box = mapeate.si_mismo.getBoundingClientRect();
        
        return [evento.clientX - box.x, evento.clientY - box.y];
    };

    this.capturar_cursor = (elemento, evento) => [posicion_de_raton.x, posicion_de_raton.y] = self.coger_posicion_del_cursor(evento);

    this.coger_posicion_del_raton = () => ({...posicion_de_raton});

    this.abrir_dialogo = (mensaje, datos, acciones) => {
        
        const dialogo = mapeate.si_mismo.querySelector(".dialogo");
        let botones = ``;
        
        dialogo.setAttribute("data-visible", true);
        with(dialogo.querySelector("legend")){
            setAttribute("data-i18n", mensaje);
            innerText = mapeate.i18n(mensaje);
        };
        dialogo.querySelector("section").innerHTML = datos && typeof datos == "string" ? datos : (
            `<p data-i18n="` + mensaje + `_texto"` + (
                typeof datos == "object" ? ` data-1i8n-variables="`  + atob(JSON.stringify(datos)
            ) + `"` : ``) + `>` + mapeate.i18n(mensaje + "_texto", datos) + `</p>`
        );

        if(acciones){
            dialogo.setAttribute("data-solo-mensaje", false);
            acciones.forEach((accion, i) => {

                const texto = mapeate.i18n(accion.i18n), 
                      hash = mapeate.hash();

                botones += (`<button type="button" data-i18n="` + accion.i18n + `" data-i18n-without="true" title="` + texto + `" data-precarga="` + hash + `">
                    <span data-icon="` + (accion.icono || accion.i18n) + `"></span>
                    <span data-i18n="` + accion.i18n + `">` + texto + `</span>
                </button>`);

                ((accion, i) => mapeate.precargar("[data-precarga=" + hash + "]", boton => {
                    console.log(boton);
                    boton.removeAttribute("data-precarga");
                    boton.onclick = accion.accion;
                    !i && boton.focus();
                }))(accion, i);

            });
        }else 
            dialogo.setAttribute("data-solo-mensaje", true);

        dialogo.querySelector(".grupo").innerHTML = botones;

    };

    this.ocultar_dialogo = (elemento, evento) => {
        if(elemento && elemento.parentNode && (elemento = elemento.parentNode).classList.contains("dialogo"))
            elemento.getAttribute("data-solo-mensaje") == "true" && 
            elemento.getAttribute("data-visible") == "true" && 
            elemento.setAttribute("data-visible", false);
        else 
            with(mapeate.si_mismo.querySelector(".dialogo"))
                getAttribute("data-visible") == "true" && setAttribute("data-visible", false);
    };
 
    constructor();

};