Tabulador = function(datos) {
    this.id = datos.id;
    this.muestraEn = datos.muestraEn;
    this.ui = datos.ui;
    this.inicializa();
    this.inicializaEventos(datos.eventos);
};
Tabulador.prototype = {
    muestraEn: null,
    ui: null,
    
    inicializa: function() {
        $(window).data('jqueryTabulador', true);
        if(!this.ui) {
            this.ui = this.nuevoUI();
            this.inicializaSolapas();
        }
        $(this.ui).data('objeto', this);
        if(this.muestraEn) {
            $(this.muestraEn).append(this.ui);
        }
    },
    
    inicia: function() {
        if(this.ui.tabs && this.ui.tabs('length') > 0) {
            var constructora = $(this.ui.find('.ui-tabs-panel')[0]).data('constructora');
            if(constructora) {
                constructora({ indice: 0, objeto: this });
            }
        }
    },
    
    nuevoUI: function() {
        var ui =
            $('<div></div>').attr({
                id: this.id,
                'class': 'ui-tabs'
            });
        ui.append('<ul class="ui-tabs-nav"></ul>');
        return ui;
    },
    
    nuevaSolapa: function(datos) {
        this.ui.tabs('add', '#' + datos.id, datos.titulo);
        var numero = this.ui.tabs('length') - 1;
        if(!datos.enIframe && datos.url) {
            this.ui.tabs('url', numero, datos.url);
        }
        if(datos.botonCerrar !== false) {
            this.botonCerrar(numero);
        }
        
        var panel = this.panelDe(datos.id);
        panel.append(this.htmlContenedorSolapa(datos));
        panel.data('constructora', datos.constructora);
        if(datos.enIframe) {
            this.eventoIframeCargado();
        }
    },
    
    eventoIframeCargado: function() {
        this.ui.find('.iframeSolapa').bind('load', { objeto: this }, function(evento) {
            evento.data.objeto.ui.find('.cargando').hide();
        });
    },
    
    botonCerrar: function(numero) {
        var solapa = this.uiSolapaNumero(numero);
        var boton = $('<a href="#" class="botonCerrar">X</a>');
        boton.bind('click', { numero: numero, objeto: this }, this.solapaCerrada);
        solapa.append(boton);
    },
    
    solapaCerrada: function(evento) {
        evento.data.objeto.quitaSolapa(evento.data.numero);
        return false;
    },
    
    quitaSolapa: function(numero) {
        this.ui.tabs('remove', numero);
    },
    
    uiSolapaNumero: function(numero) {
        return this.ui.find('ul.ui-tabs-nav > :eq(' + numero + ')');
    },
    
    existeSolapa: function(id) {
        return this.panelDe(id).length > 0;
    },
    
    seleccionaSolapa: function(id) {
        this.ui.tabs('select', '#' + id);
    },
    
    panelDe: function(id) {
        return this.ui.find('#' + id);
    },
    
    inicializaSolapas: function() {
        this.ui.tabs({
            select: function(evento, solapa) { // invoca la función constructora correspondiente a la solapa seleccionada
                //console.log('tab ' + solapa.index + 'seleccionado');
                var constructora = $(solapa.panel).data('constructora');
                if(constructora) {
                    constructora({ indice: solapa.index, objeto: $(evento.target).data('objeto') });
                }
            }
        });
    },
    
    htmlContenedorSolapa: function(datos) {
        var html = '<div class="ui-layout-center">' +
                    '<div class="contenedorSolapa contenido-' + datos.id + '"><div class="cargando">Cargando...</div>';
        if(datos.enIframe && datos.url) {
            html += '<iframe src="' + datos.url + '" class="iframeSolapa"></iframe>';
        }
        html +=     '</div>' +
               '</div>';
        return html;
    },
    
    inicializaEventos: function(eventos) {
        if(eventos) {
            var este = this;
            $.each(eventos, function(nombre, funcion) {
                $(este.ui).bind(nombre, { objeto: este }, funcion);
            });
        }
    },
    
    abreSiNoExiste: function(solapa) {
        if(!this.existeSolapa(solapa.id)) {
            this.nuevaSolapa(solapa);
        }
        this.seleccionaSolapa(solapa.id);
    },
    
    reemplazaYAbre: function(solapa) {
        if(this.existeSolapa(solapa.id)) {
            this.quitaSolapa(this.indiceDe(solapa.id));
        }
        this.nuevaSolapa(solapa);
        this.seleccionaSolapa(solapa.id);
    },
    
    indiceDe: function(id) {
        var indice = this.ui.children().index(this.ui.find('#' + id));
        return indice >= 0 ? indice - 1 : -1; // descuento el ul
    }
    
};
