/** globals: alert,  escape, unescape, console, document, jQuery, window, $, cto, Image  */
/* jslint bitwise: true, browser: true, eqeqeq: true, immed: true, newcap: true, nomen: true, onevar: true, plusplus: true, regexp: true, undef: true */ 

/** COMENTARIOS */
cto.comentario = function (options) {
    var defaults, ops, chain, eventName, comentarioSuccess, comentarioError, bindClick;
    if( !$('.'+options.ctn ).length ) { return; }
    
    comentarioSuccess = function (data, status) {
        var mensaje = data.msg;
        this.mask.hide();
        if (data.success === true) {
            this.ctn.find('#comm').val('');
            this.ctn.find('#comm').blur();
            cto.alert(cto.defaults.mensajes.enviadoConExito, true);
        } else if (mensaje.match('[[LOGIN]]')) {
            cto.alert(cto.mensajeLogReg(mensaje));
        } else {
            if( data && data.msg ) { 
                cto.alert(data.msg);
            } else {
                cto.alert(cto.defaults.mensajes.errorEnvio);
            }
        }
    };
    
    comentarioError = function (data, status) {
        this.mask.hide();
        if( data && data.msg ) {
            cto.alert(data.msg);
        } else {
            cto.alert(cto.defaults.mensajes.errorEnvio);
        }
    };
    
    defaults = {
        handler : '.cto-com-voto',
        clsSending : 'cto-sending',
        fnSuccess : comentarioSuccess,
        fnError : comentarioError,
        str : 'Deja aquí tu comentario',
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    eventName = "click.comentario";
    ops.ctn = '.' + ops.ctn;
    chain = [ops.ctn, ops.handler].join(' ');
    
    $(ops.ctn + " textarea").clearOnFocus(ops.str);
    
    function comprobar () {
        
        var user = cto.getCookieCuatro();
        if (user === null) { // si es null no esta conectado
            $(ops.ctn).find('.cto-no-logueado').show();
            return false;
        } else {
            $(ops.ctn).find('.cto-no-logueado').hide();
            $(ops.ctn).find('.cto-logueado').show();
            return true;
        }
    }
    
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, $ctn, $item, mask;
        $ctn = $hn.closest(ops.ctn);
        $item = $hn.closest(ops.item);
        if ($ctn.hasClass(ops.clsSending)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        
        ajaxData = {
            modulo : 'PAR',
            t : 'cm',
            comentario : $ctn.find('#comm')[0].value,
            rid : $ctn.find('#rid')[0].value
        };
        if (!ajaxData || !ajaxData.modulo) { return false; }

        mask = cto.getLoadingMask($ctn, { id : ops.ctn });
        mask.show(); 

        $ctn.addClass(ops.clsSending);
        
        callbackScope = {
            ctn : $ctn,
            item : $item,
            hn : $hn,
            mask : mask,
            comentario : ops.comentario
        };
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsSending);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsSending);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    
    // solo ponemos evento si el usuario esta conectado
    if (comprobar()) {
        $(chain).unbind(eventName);
        $(chain).bind(eventName, bindClick);
    }
    
};

/** ENTREVISTAS */
cto.entrevista = function (options) {
    var defaults, ops, chain, eventName, entrevistaSuccess, entrevistaError, bindClick, comprobar, $textoDefecto;
    if( !$('.'+options.ctn ).length ) { return; }
    
    entrevistaSuccess = function (data, status) {
        if (data.success === true) {
            cto.alert('Pregunta enviada con éxito', true);
            // limpiamos la caja de texto
            $(ops.textArea).attr('value', $textoDefecto);
            this.mask.hide();
        } else {
            cto.alert(cto.defaults.mensajes.errorEnvio);
            this.mask.hide();
        }
    };
    
    entrevistaError = function (data, status) {
        cto.alert(cto.defaults.mensajes.errorEnvio);
    };
    
    defaults = {
        handler : '.cto-ent-preg',
        fnSuccess : entrevistaSuccess,
        fnError : entrevistaError,
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    eventName = "click.entrevista";
    ops.ctn = '.' + ops.ctn;
    ops.textArea = $(ops.ctn).find('#ent');
    chain = [ops.ctn, ops.handler].join(' ');
    
    comprobar = function () {
        
        var user = cto.getCookieCuatro();
        if (user === null) { // si es null no esta conectado
            $(ops.ctn).find('.cto-no-logueado').show();
            return false;
        } else {
            $(ops.ctn).find('.cto-no-logueado').hide();
            $(ops.ctn).find('.cto-logueado').show();
            $(ops.ctn).find('.usuario').find('img').attr('src', '/avatar/' + user.id + '/63/' + user.nick + '.jpg');
            $(ops.ctn).find('.usuario').find('a').attr('href','http://soy.cuatro.com/soycuatro-actividad.html?idusr=' + user.id );
            $(ops.ctn).find('.usuario').find('a').html(user.nick);
            return true;
        }
    };
    
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, $ctn, $item, mask;
        $ctn = $hn.closest(ops.ctn);
        $item = $hn.closest(ops.item);
        if ($ctn.hasClass(ops.clsLoading)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        if($.trim($(ops.textArea).attr('value')) === $textoDefecto){ 
            // ha hecho click con la caja de texto vacía
            return false;
        }
        mask = cto.getLoadingMask($ctn, {
                id : ops.ctn
        });
        mask.show();
        ajaxData = {
            modulo : 'PAR',
            t : 'et',
            entrevista : $ctn.find('#ent')[0].value,
            rid : $ctn.find('#rid')[0].value
        };
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        callbackScope = {
            ctn : $ctn,
            item : $item,
            hn : $hn,
            entrevista : ops.ctn,
            mask : mask
        };
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
            }
        });
        $.ajax(ajaxConfig);
    };
    
    // solo ponemos evento si el usuario esta conectado
    if (comprobar()) {
        $(chain).unbind(eventName);
        $(chain).bind(eventName, bindClick);
        $textoDefecto = $(ops.textArea).attr('value');
        $(ops.textArea).clearOnFocus($textoDefecto);
    }
    
};

/** ENCUESTAS * */
cto.encuesta = function (options) {
    var defaults, ops, chain, eventName, encuestaSuccess, encuestaError, bindClick;
    if( !$('.'+options.ctn ).length ) { return; }
    
    encuestaSuccess = function (data, status) {
        var $this;
        if (data.success === true) {
            //Cojemos los datos actualizados y se los ponemos en el HTML
            $this = this;
            $.each(data.data, function(i,n){
                var percent, item, barra;

                percent = $this.ctn.find(defaults.handlerPercent + i);
                percent.html(n.porcentaje + '%');
                item = $this.ctn.find(defaults.handlerItem + i);
                item.html(n.votos + ' votos'); 
                barra = $this.ctn.find(defaults.handlerBarra + i);
                barra.attr('style', 'width:' + n.porcentaje + '%');
            });

            this.mask.hide();
            cto.alert(data.msg);
        } else if (data.msg.match('[[LOGIN]]')) {
            this.mask.hide();
            cto.alert(cto.mensajeLogReg(data.msg));
        } else {
            this.mask.hide();
            if( data && data.msg ) { 
                cto.alert(data.msg);
            } else {
                cto.alert(cto.defaults.mensajes.errorEnvio);
            }
        }
    };
    
    encuestaError = function (data, status) {
        this.mask.hide();
        cto.alert(data.msg);
    };
    
    defaults = {
        handler : '.cto-enc-voto',
        handlerPercent : '.cto-percent',
        handlerBarra : '.cto-barra',
        handlerItem : '.cto-item',
        fnSuccess : encuestaSuccess,
        fnError : encuestaError,
        strVotos : 'voto|votos',
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    eventName = "click.encuesta";
    ops.ctn = '.' + ops.ctn;
    chain = [ops.ctn, ops.handler].join(' ');
    
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, mask, $ctn, $item;
        $ctn = $hn.closest(ops.ctn);
        $item = $hn.closest(ops.item);
        if ($ctn.hasClass(ops.clsLoading)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        ajaxData = cto.query($hn.find('[href]:first').attr('href'));
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        mask = cto.getLoadingMask($ctn, {
            id : ops.ctn
        });
        mask.show();
        
        callbackScope = {
            ctn : $ctn,
            item : $item,
            hn : $hn,
            encuesta : ops.encuesta,
            mask : mask
        };
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    $(chain).unbind(eventName);
    $(chain).bind(eventName, bindClick);
};

/** CONCURSOS * */

cto.concurso = function (options) {
    var a, defaults, ops, chain, eventName, concursoSuccess, concursoError, opcionClick, botonClick, opcionMouseOver, capa, eventName2;
    if( !$('.'+options.ctn ).length ) { return; }
    
    concursoSuccess = function (res, status) {
        var opciones, $boton, capSelecciona, capAdvierte, mensaje;
        capSelecciona = this.ctn.find('.selecciona');
        capAdvierte = this.ctn.find('.advertencia');
        opciones = this.ctn.find(ops.handlerOpc);
        // Faltan datos de registro. Muestra la capa de datos adicionales
        if(res.data && res.data.rc === 0) {
            cto.crm.alertModificacion();
            this.mask.hide();
            return;
        }
        if (res.success) {
            opciones.each(function (i, val) {
                var clase = val.className, opcion, res;
                res = clase.indexOf('seleccionada');
                if (res === -1) {
                    opcion = $(val).closest('li');
                    opcion.remove();
                }
            });
            capSelecciona.html(ops.mensajeFase3selecciona);
            capAdvierte.html(ops.mensajeFase3advertencia);
            cto.alert(ops.mensajeFase3selecciona);
        } else {
            // ha fallado algo....o no estás conectado o no puede
            mensaje = res.msg;
            if (!res.success && mensaje.match('[[LOGIN]]')) {
                mensaje = cto.mensajeLogReg(mensaje);
            }
            cto.alert(mensaje);
            capSelecciona.html(mensaje);
            capAdvierte.hide();
        }
        $boton = this.ctn.find(ops.handlerVoto);
        $boton.unbind(eventName);
        opciones.unbind(eventName);
        $boton.hide();
        opciones.unbind(eventName2);
        opciones.css('cursor', 'default');
        this.mask.hide();
    };
    
    concursoError = function (data, status) {
        var capSelecciona, capAdvierte;
        capSelecciona = this.ctn.find('.selecciona');
        capSelecciona.html(data.msg);
        capAdvierte = this.ctn.find('.advertencia');
        capAdvierte.hide();
        cto.alert(data.msg);
        this.mask.hide();
    };
    
    defaults = {
        pregOpc : [],
        handlerOpc : '.cto-conc-opc-comun',
        handlerVoto : '.cto-conc-voto',
        claseOpcion : '.cto-conc-opc-',
        clsSelect : 'seleccionada',
        modulo : 'PAR',
        t : 'co',
        abcdario : ['a', 'b', 'c', 'd', 'e'],
        mensajeFase1advertencia : '',
        mensajeFase1selecciona : '',
        mensajeFase2advertencia : 'Si no estás seguro, puedes cambiar tu respuesta en este momento, si estás seguro pulsa confirmar',
        mensajeFase2selecciona : 'Has seleccionado la respuesta ',
        mensajeFase3selecciona : '¡Confirmado!. Suerte y gracias por participar',
        mensajeFase3advertencia : 'El ganador se anunciará próximamente ',
        completo : true,
        fnSuccess : concursoSuccess,
        fnError : concursoError,
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    if (!ops.ctn || !ops.id || !ops.num_preg) { return; }
    
    for (a = 0; a < ops.num_preg; a+=1) {
        ops.pregOpc[a] = null;
    }
    eventName = "click.concurso";
    eventName2 = "mouseover.concurso";
    ops.ctn = '.' + ops.ctn;
    $(ops.ctn).css('cursor', 'default');
    // recojo los mensaje por defecto de las capas de advertencia
    capa = $(ops.ctn).find('.selecciona');
    ops.mensajeFase1selecciona = capa[0].innerHTML;
    capa = $(ops.ctn).find('.advertencia');
    ops.mensajeFase1advertencia = capa[0].innerHTML;
    chain = [ops.ctn, ops.handlerOpc].join(' ');
    opcionMouseOver = function () {
        var opsCapa = $(this);
        opsCapa.css('cursor', 'pointer');
    };
    opcionClick = function () {
        var a, $hn = $(this), $opcion, cls, $pregunta, $combi, $ctn, $indice, $boton, chaini, capSelecciona, capAdvierte, $Tempopcion, temp, nomClase, nulles, mensTemp, ind;
        $ctn = $hn.closest(ops.ctn);
        $boton = $ctn.find(ops.handlerVoto);
        capSelecciona = $ctn.find('.selecciona');
        capAdvierte = $ctn.find('.advertencia');
        cls = $hn.attr('class').split(' ')[2];
        temp = cls.split('-');
        $combi = temp[temp.length - 1];
        $Tempopcion = $combi.split('', $combi);
        $opcion = $Tempopcion[1];
        $pregunta = $Tempopcion[0];
        $indice = $Tempopcion[0] - 1;
        if (ops.pregOpc[$indice] === null) {
            // no había ninguna selección hecha
            $hn.addClass(ops.clsSelect);
        } else if (ops.pregOpc[$indice] === $opcion) {
            // ha vuelto a pinchar en la misma opcion
            // si completo es true y dios quiere, hay que quitar el mensaje de
            // resultados y poner los default
            if (ops.completo) {
                capSelecciona.html(ops.mensajeFase1selecciona);
                capAdvierte.html(ops.mensajeFase1advertencia);
            }
            $hn.removeClass(ops.clsSelect);
            $opcion = null;
        } else {
            // ha pinchado en otra opción de la misma pregunta
            nomClase = ops.claseOpcion + $pregunta + ops.pregOpc[$indice];
            $(nomClase).removeClass(ops.clsSelect);
            $hn.addClass(ops.clsSelect);
        }
        ops.pregOpc[$indice] = $opcion;
        nulles = false;
        for (a = 0; a < ops.num_preg; a+=1) {
            if (ops.pregOpc[a] === null) {
                nulles = true;
            }
        }
        ops.completo = (nulles) ? false : true;
        
        chaini = [ops.ctn, ops.handlerVoto].join(' ');
        if (ops.completo) {
            // ha contestado todas las preguntas!! habilitamos el botón y
            // sacamos los mensajes correspondientes
            $(chaini).unbind(eventName);
            $(chaini).bind(eventName, botonClick);
            mensTemp = ops.mensajeFase2selecciona;
            // TODO: optimizar for
            for (ind in ops.pregOpc) {
                if ( typeof ops.pregOpc[ind] !== 'undefined' ) { 
                    mensTemp += ops.abcdario[ops.pregOpc[ind]] + ', ';
                }
            }
            // quitamos la ultima coma
            mensTemp = mensTemp.substr(0, mensTemp.length - 2);
            capSelecciona.html(mensTemp);
            capAdvierte.html(ops.mensajeFase2advertencia);
            $boton.show();
        } else {
            $(chaini).unbind(eventName);
            $boton.hide();
        }
    };
    botonClick = function () {
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, mask, $ctn, Temp, ind;
        $ctn = $hn.closest(ops.ctn);
        // @TODO: Esto se puede hacer con un .join()
        Temp = '';
        for (ind in ops.pregOpc) {
            if ( typeof ops.pregOpc[ind] !== 'undefined' ) { 
                Temp += (parseInt(ops.pregOpc[ind], 10) + 1) + ',';
            }
        }
        // quitamos la ultima coma
        Temp = Temp.substr(0, Temp.length - 1);
        ajaxData = {
            id : ops.id,
            num_preg : ops.num_preg,
            respuestas : Temp,
            modulo : ops.modulo,
            t : ops.t,
            type : ops.type
        };
        if (!ajaxData || !ajaxData.modulo) { return false; }
        mask = cto.getLoadingMask($ctn, {
            id : ops.ctn
        });
        mask.show();
        
        callbackScope = {
            ctn : $ctn,
            hn : $hn,
            concurso : ops.concurso,
            mask : mask
        };
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
            }
        });
        
        $.ajax(ajaxConfig);
        // Devuelve false para interrumpir el evento click
        return false;
    };
    
    $(chain).unbind(eventName);
    $(chain).bind(eventName, opcionClick);
    $(chain).bind(eventName2, opcionMouseOver);
};

/** VALORACION/VOTACION */
cto.valoracion = function (options) {
    var defaults, ops, chain, eventName, valoracionSuccess, valoracionError, bindClick, bindHover;
    if( !$('.'+options.ctn ).length ) { return; }
    
    valoracionSuccess = function (data, status) {
        var mensaje, votos, tagVotos;
        this.mask.hide();
        if (data && !data.success) {
            mensaje = data.msg;
            if (mensaje.match('[[LOGIN]]')) {
                mensaje = cto.mensajeLogReg(mensaje);
            }
            cto.alert(mensaje, true);
            return false;
        }
        //Controlamos que los votos de la pagina se refresquen en tiempo real
        tagVotos = this.item.find(ops.handlerVotos);

        if(tagVotos.html() !== null && tagVotos.find(ops.tagIncludedVotos).length ) {
            votos = parseInt(this.item.find(ops.handlerVotosSpan).html(), 10);
            if(ops.strVotosSpanC != '' && data.data.t == 'vc') {
               tagVotos.html(cto.plural(votos +1 , ops.strVotosSpanC));
            }else{
               tagVotos.html(cto.plural(votos +1 , ops.strVotosSpan));
            }
        }else if(tagVotos.html() !== null){
            votos = parseInt(tagVotos.html().split(' ')[0], 10);
            if(ops.strVotosC != '' && data.data.t == 'vc') {
               tagVotos.html(cto.plural(votos +1 , ops.strVotosC));
            }else{
               tagVotos.html(cto.plural(votos +1 , ops.strVotos));
            }
        }

        if (this.votacion) {
            this.hn.prevAll().addClass(ops.clsSelected);
        }
        
        this.hn.addClass(ops.clsSelected);
        cto.alert(data.msg, true);
        return false;
    };
    
    valoracionError = function (data, status) {
        this.mask.hide();
        if (data && data.msg) {
            cto.alert(data.msg, true);
        } else {
            cto.alert(cto.defaults.mensajes.errorEnvio);
        }
        return false;
    };
    defaults = {
        item : '.cto-val-item',
        handler : '.cto-val-handler',
        clsSelected : 'cto-val-votado',
        clsHover : 'cto-val-hover',
        handlerVotos : '.cto-val-votos',
        handlerVotosSpan : '.cto-val-span',
        tagIncludedVotos : 'span',
        clsLoading : 'cto-val-loading',
        strVotos : '%s voto|%s votos',
        strVotosC : '',
        strVotosSpan : '<span>%s</span> voto|<span>%s</span> votos',
        strVotosSpanC : '',
        uselivequery : true,
        useHover : false,
        votacion : true,
        fnSuccess : valoracionSuccess,
        fnError : valoracionError,
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    
    ops = $.extend( {}, defaults, options || {});
    
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    ops.ctn = '.' + ops.ctn;
    chain = [ops.ctn, ops.item, ops.handler].join(' ');
    
    if (!ops.votacion && ops.useHover) {
        eventName = 'mouseleave mouseenter';
        if (ops.uselivequery) {
            $(chain).live(eventName, bindHover);
        } else {
            $(chain).unbind(eventName);
            $(chain).bind(eventName, bindHover);
        }
        
    }
    
    eventName = 'click';
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, href, $ctn, $item, mask;
        
        if ($hn.siblings().hasClass(ops.clsSelected) || $hn.hasClass(ops.clsSelected)) { return false; }
        
        $ctn = $hn.closest(ops.ctn);
        $item = $hn.closest(ops.item);
        if ($ctn.hasClass(ops.clsLoading)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        
        href = $hn.find('[href]:first').attr('href');
        if (!href) {
            href = $hn.attr('href');
        }
        ajaxData = cto.query(href);
        
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        mask = cto.getLoadingMask($item, { id: ops.ctn+'-'+cto.id() });
        mask.show();
        callbackScope = {
            ctn : $ctn,
            item : $item,
            hn : $hn,
            mask : mask,
            votacion : ops.votacion
        };
        $ctn.addClass(ops.clsLoading);
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    
    bindHover = function (target, ev) {
        var $hn = $(this);
        if ($hn.siblings().hasClass(ops.clsSelected)) { return; }
        
        $hn.toggleClass(ops.clsHover);
        $hn.prevAll().toggleClass(ops.clsHover);
    };
    
    if (ops.uselivequery) {
        $(chain).live(eventName, bindClick);
    } else {
        $(chain).unbind(eventName);
        $(chain).bind(eventName, bindClick);
    }
    
};

var Fotogaleria_loadImageSuccess = function (data, status) {
        var $d, $this, img;
        this.dataCtn.html('');
        $d = $(data);
        img = $d.find('img');
        $this = this;
        
        //Recogemos el contenedor y la mascara de carga para 
        //controlar estos dentro del evento load de la imagen
        img.bind('load', function(e) {
            $this.dataCtn.html($d);
            img.show();
            $this.mask.hide();
         });
};

/** PAGINACION */

cto.paginacion = function (options) {
    var defaults, ops, chain, eventName, paginacionSuccess, paginacionError, bindClick;
    if( !$('.'+options.ctn ).length ) { return; }
    
    /** Callbacks por defecto */
    paginacionSuccess = function (data, status) {
        this.dataCtn.html('');
        this.dataCtn.html(data);
        this.mask.hide();
    };
    
    paginacionError = function (data, status) {
        this.mask.hide();
    };
    
    defaults = {
        data : '.cto-pg-data',
        pgCtn : '.cto-pg-hn-ctn',
        pgHandler : '.cto-pg-hn',
        clsSelected : 'cto-pg-selected',
        clsLoading : 'cto-pg-loading',
        fnSuccess : paginacionSuccess,
        fnError : paginacionError,
        ajaxConfig : {
            type : 'GET',
            dataType : 'text/html'
        }
    };
    eventName = 'click'; 
    
    ops = $.extend( {}, defaults, options || {});
    
    // si faltan datos, no asocia eventos
    if (!ops.ctn || !ops.nombre) { return; }
    
    ops.ctn = '.' + ops.ctn;
    
    chain = [ops.ctn, ops.pgCtn, ops.pgHandler].join(' ');
    
    bindClick = function (ev) {
        if( ev.button !==  0 ) { return; } // no es click izquierdo
        ev.preventDefault();
        var $hn = $(this), callbackScope, ajaxConfig, ajaxData, mask, href, modulo, $ctn, $data, $pgCtn;
        if ($hn.hasClass(ops.clsSelected)) { return false; }
        
        $ctn = $hn.closest(ops.ctn);
        $pgCtn = $hn.closest(ops.pgCtn);
        $data = $ctn.find(ops.data);
        
        if ($ctn.hasClass(ops.clsLoading)) { return false; }
        
        href = $hn.find('[href]:first').attr('href');
        if (!href) {
            href = $hn.attr('href');
        }
        
        ajaxData = cto.query(href);
        
        modulo = ajaxData.modulo && !ops.nombre ? ajaxData.modulo : ajaxData[ops.nombre + '_paginador_modulo'] ? ops.nombre + '_paginador_modulo' : ops.nombre + '_modulo';
        
        if (!ajaxData.modulo) {
            ajaxData.modulo = ajaxData[modulo];
            delete ajaxData[modulo];
        }
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        mask = cto.getLoadingMask($ctn, {
            id : ops.ctn
        });
        mask.show();
        
        callbackScope = {
            ctn : $ctn,
            dataCtn : $data,
            pgHn : $hn,
            pgCtn : $pgCtn,
            mask : mask
        };
        
        $ctn.addClass(ops.clsLoading);
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : ajaxData,
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    
    $(chain).live(eventName, bindClick);
};

/** paginacion buscador **/ 
cto.paginacion_buscador = function (options) {
    var defaults, ops, chain, eventName, paginacionSuccess, paginacionError, bindClick;
    if( !$('.'+options.ctn ).length ) { return; }
    
    defaults = {
        data : '.cto-pg-data',
        pgCtn : '.cto-pg-hn-ctn',
        pgHandler : '.cto-pg-hn',
        clsSelected : 'selected',
        clsLoading : 'cto-pg-loading',
        fnSuccess : paginacionSuccess,
        fnError : paginacionError,
        ajaxConfig : {
            type : 'GET',
            dataType : 'text/html'
        }
    };
    eventName = 'click';
    
    ops = $.extend( {}, defaults, options || {});
    
    // si faltan datos, no asocia eventos
    if (!ops.ctn ) { return; }
    
    ops.ctn = '.' + ops.ctn;
    
    chain = [ops.ctn, ops.pgCtn, ops.pgHandler].join(' ');
    
    bindClick = function (ev) {
        if( ev.button !==  0 ) { return; } // no es click izquierdo
        ev.preventDefault();
        var $hn = $(this),  ajaxData, href, $ctn,isTienda;
        if ($hn.hasClass(ops.clsSelected)) { return false; }
        
        $ctn = $hn.closest(ops.ctn);
        
        if ($ctn.hasClass(ops.clsLoading)) { return false; }
        
        href = $hn.find('[href]:first').attr('href');
        if (!href) {
            href = $hn.attr('href');
        }
        
        ajaxData = cto.query(href);
        isTienda = $hn.closest('.tienda').length;
        if( isTienda ) {
            cto.buscador.pagina_tienda =  ajaxData.lbt_paginador_page;
        } else {
            cto.buscador.pagina =  ajaxData.lb_paginador_page;
        }
        cto.buscador.paginar();
        return ;
        
    };
    
    $(chain).live(eventName, bindClick);
};

/** ABRIR/CERRAR */

cto.togglePanel = function (options) {
    var $hn, defaults, ops, bindClick, chain;
    if( !$('.'+options.ctn ).length ) { return; }
    defaults = {
        panel : '.cto-col-panel',
        handler : '.cto-col-handler',
        clsHidden : 'cto-col-hidden'
    };
    
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), $ctn, $panel;
        $ctn = $hn.closest(ops.ctn); // + ':first');
        $panel = $ctn.find(ops.panel + ':first');
        $hn.toggleClass(ops.clsHidden);
        $panel.slideToggle();
        $hn.blur();
    };
    
    ops = $.extend( {}, defaults, options);
    ops.ctn = '.' + ops.ctn;
    chain = ops.ctn + ' ' + ops.handler;
    $hn = $(chain);
    $hn.each(function (i, e) {
        var $e = $(e), $panel;
        $panel = $e.closest(ops.ctn).find(ops.panel + ':first');
        if ($panel.is(':visible')) {
            $e.removeClass(ops.clsHidden);
        }
        if ($panel.is(':hidden')) {
            $e.addClass(ops.clsHidden);
        }
    });
    $hn.bind('click.togglePanel', bindClick);
};

cto.tooltip = function (options) {
    var defaults, chain, ops;
    if( !$('.'+options.ctn ).length ) { return; }
    defaults = {
        ctnInfo : '.cto-ttp-info',
        item : '.programa'
    };
    
    ops = $.extend( {}, defaults, options || {});
    
    chain = '.' + ops.ctn + ' ' + ops.item;
    $(chain).tooltip( {
        id : 'cto-tooltip',
        bodyHandler : function () {
            return $(this).closest('tr').find('.cto-ttp-info').html();
        },
        showURL : false,
        track : true
    });
};


cto.countdown = function (options) {
    var defaults, ops, now = new Date();
    if( !$('.'+options.ctn ).length ) { return; }
    defaults = {
        faltan : '<p>Faltan</p>',
        faltanDias : '<p>Faltan %D%n %l%D y</p>',
        layout : ['<div class="cifras"><p>%H%nn<strong>%l%H</strong></p></div>',
                  '<div class="cifras"><p>%M%nn<strong>%l%M</strong></p></div>',
                  '<div class="cifras"><p>%S%nn<strong>%l%S</strong></p></div>'].join(''),
        format : 'dHMS'
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    if (Math.abs(now.getTime() - ops.until.getTime()) > 86400000) {
        ops.layout = ops.faltanDias + ops.layout;
    } else {
        ops.layout = ops.faltan + ops.layout;
    }
    ops.ctn = '.' + ops.ctn;
    $(ops.ctn).countdown( {
        layout : ops.layout,
        until : ops.until,
        format : ops.format
    });
};

cto.filtroListado = function (options) {
    var defaults, ops, chain, eventName, formAction, filtroSuccess, filtroError, bindChange;
    if( !$('.'+options.ctn ).length ) { return; }
    
    filtroSuccess = function (data, status) {
        this.dataCtn.html('');
        this.dataCtn.html(data);
        this.mask.hide();
    };
    
    filtroError = function (data, status) {
        this.mask.hide();
    };
    
    defaults = {
        flt : '.cto-flt',
        data : '.cto-pg-data',
        clsLoading : 'cto-pg-loading',
        fnSuccess : filtroSuccess,
        fnError : filtroError
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    ops.ctn = '.' + ops.ctn;
    
    eventName = 'change.filtro';
    
    chain = [ops.ctn, ops.flt].join(' ');
    
    bindChange = function () {
        var $hn = $(this), filterValue, $ctn, $data, ajaxData, modulo, mask, ajaxConfig, callbackScope,  url_string, optionName;
        filterValue = $hn.val();
        optionName = $hn.attr('name');
        $ctn = $hn.closest(ops.ctn);
        $data = $ctn.find(ops.data);
        formAction = $(ops.ctn + ' form').attr('action');
        ajaxData = cto.query(formAction);
        
        if (ajaxData[optionName] === filterValue) {
            return false;
        } else {
            ajaxData[optionName] = filterValue;
        }
        
        ajaxData[ops.nombre + '_paginador_page'] = 1;
        
        modulo = ajaxData.modulo && !ops.nombre ? ajaxData.modulo : ajaxData[ops.nombre + '_paginador_modulo'] ? ops.nombre + '_paginador_modulo' : ops.nombre + '_modulo';
        
        if (!ajaxData.modulo) {
            ajaxData.modulo = ajaxData[modulo];
            delete ajaxData[modulo];
        }
        
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        url_string = $.param(ajaxData);
        url_string = decodeURIComponent(url_string);
        
        $(ops.ctn + ' form').attr("action", "?" + url_string);
        
        mask = cto.getLoadingMask($ctn, {
            id : ops.ctn
        });
        mask.show();
        
        callbackScope = {
            ctn : $ctn,
            dataCtn : $data,
            mask : mask
        };
        
        $ctn.addClass(ops.clsLoading);
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : ajaxData,
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
                $ctn.removeClass(ops.clsLoading);
            }
        });
        
        $.ajax(ajaxConfig);
        // Devuelve false para interrumpir el evento click
        return false;
        
    };
    
    $(chain).bind(eventName, bindChange);
    
};

// Tooltip fotogalerías
cto.tooltip_fotogalerias = function (options) {
    $.extend($.fn.Tooltip.defaults, {
        track : true,
        delay : 0,
        showURL : false,
        showBody : false
    });
    $('.mini-53 li a').Tooltip();
    $('.mini-56 li a').Tooltip();
    $('.mini-56b li a').Tooltip();
    $('.mini-63 li a').Tooltip();
    $('.mini-106 li a').Tooltip();
    $('.mini-114 li a').Tooltip();
    $('.mini-114b li a').Tooltip();
    $('.idolos li a').Tooltip();
    $('.fans li a').Tooltip();
    $('.amigos li a').Tooltip();
};



/** INDICE FOTOGALERIA */
cto.fotogIndice = function (options) {
    var $ctn, defaults, ops, $btnMostrar, $btnOcultar;
    if( !$('.'+options.ctn ).length ) { return; }
    defaults = {
        btnMostrar : '.cto-mostrar',
        btnOcultar : '.cto-ocultar',
        clsIndice : 'cto-pg-data-indice',
        pgCtn : '.cto-pg-hn-ctn'
    };
    ops = $.extend( {}, defaults, options);
    ops.ctn = '.' + ops.ctn;
    
    $ctn = $(ops.ctn);
    $btnMostrar = $ctn.find(ops.btnMostrar);
    $btnOcultar = $ctn.find(ops.btnOcultar);
    
    $btnMostrar.live('click.indice', function (e) {
        $ctn.find(ops.pgCtn).hide();
        $(ops.btnMostrar).hide();
        $(ops.btnOcultar).show();
        e.preventDefault();
        $ctn.find('.indice').height($('.cont-imagen').height());
        $ctn.find('.cont-imagen').show();
        $ctn.find('.indice').show();
    });
    
    $btnOcultar.live('click.indice', function (e) {
        $(ops.btnMostrar).show();
        $(ops.btnOcultar).hide();
        //$ctn.find('.' + ops.clsIndice).html('');
        $ctn.find('.' + ops.clsIndice).hide();
        $ctn.find(ops.pgCtn).show();
        e.preventDefault();
        $ctn.find('.indice').hide();
    });
};

/** CALENDARIOS */
cto.calendario = function (options) {
    var defaults, ops, chain, eventName, calendarioError, calendarioSuccess, bindClick;
    if( !$('.'+options.ctn ).length ) { return; }
    
    calendarioSuccess = function (data, status) {
        this.dataCtn.html('');
        this.dataCtn.html(data);
        this.mask.hide();
    };
    
    calendarioError = function (data, status) {
        cto.alert(cto.defaults.mensajes.errorEnvio);
    };
    
    defaults = {
        data : '.cto-cal-data',
        item : '.cto-cal-item',
        pgCtn : '.cto-cal-hn-ctn',
        handler : '.cto-cal-handler',
        fnSuccess : calendarioSuccess,
        fnError : calendarioError,
        ajaxConfig : {
            dataType : 'text/html',
            type : 'GET'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    eventName = "click";
    ops.ctn = '.' + ops.ctn;
    chain = [ops.ctn, ops.handler].join(' ');
    
    bindClick = function (ev) {
        ev.preventDefault();
        var $hn = $(this), ajaxConfig, ajaxData, callbackScope, $ctn, $pgCtn, $item, $data, href, mask, ajaxAux;
        $ctn = $hn.closest(ops.ctn);
        $pgCtn = $hn.closest(ops.pgCtn);
        $item = $hn.closest(ops.item);
        $data = $(ops.data);
        if ($ctn.hasClass(ops.clsLoading)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        
        href = $hn.find('[href]:first').attr('href');
        if (!href) {
            href = $hn.attr('href');
        }
        
        ajaxAux = cto.query(href);
        
        ajaxData = {
            modulo : 'CAL',
            v : ajaxAux.v,
            step : ajaxAux.step
        };
        
        if (ajaxAux.cid !== null) {
            ajaxData.cid = ajaxAux.cid;
        }
        
        if (ajaxAux.pid !== null) {
            ajaxData.pid = ajaxAux.pid;
        }
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        mask = cto.getLoadingMask($ctn, {
            id : ops.ctn
        });
        mask.show();
        
        callbackScope = {
            ctn : $ctn,
            pgCtn : $pgCtn,
            item : $item,
            pgHn : $hn,
            dataCtn : $data,
            mask : mask
        };
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    
    $(chain).live(eventName, bindClick);
    
};


/** SUSCRIPCION - START */
cto.suscripcion = function (options) {
    var defaults, ops, chain, eventName, suscripcionSuccess, suscripcionError, bindClick, suscripcionNoLogged;
    if( !$('.'+options.ctn ).length ) { return; }
    
    suscripcionSuccess = function (data, status) {
        if (data.success === true) {
            cto.alert(data.message);
        } else {
            cto.alert( cto.defaults.mensajes.errorEnvio);
        }
    };
    
    suscripcionError = function (data, status) {
        cto.alert( cto.defaults.mensajes.errorEnvio);
    };
    
    suscripcionNoLogged = function () {
        cto.alert(cto.defaults.mensajes.errorConectadoSuscripcion);
        return false;
    };
    
    defaults = {
        handler : '.cto-par-sus-handler',
        fnSuccess : suscripcionSuccess,
        fnError : suscripcionError,
        ajaxConfig : {
            dataType : 'json',
            type : 'POST'
        }
    };
    ops = $.extend( {}, defaults, options || {});
    // si faltan datos, no asocia eventos
    if (!ops.ctn) { return; }
    
    eventName = "click";
    ops.ctn = '.' + ops.ctn;
    chain = [ops.ctn, ops.handler].join(' ');
    
    function comprobar () {
        
        var user = cto.getCookieCuatro();
        if (user === null) { // si es null no esta conectado
            $(ops.ctn).find('.cto-no-logueado').show();
            return false;
        } else {
            $(ops.ctn).find('.cto-no-logueado').hide();
            $(ops.ctn).find('.cto-logueado').show();
            return true;
        }
    }
    bindClick = function (ev) {
        ev.preventDefault();
        var hn = $(this), ajaxConfig, ajaxData, callbackScope, ctn, item, valores;
        ctn = hn.closest(ops.ctn);
        if (ctn.hasClass(ops.clsLoading)) {
            // ha hecho click antes de que acabe de cargar.
            return false;
        }
        item = ctn.find(ops.handler);
        valores = item.attr('href');
        ajaxData = cto.query(valores);
        ajaxData.format = 'JSON';
        
        if (!ajaxData || !ajaxData.modulo) { return false; }
        
        ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
            data : $.param(ajaxData),
            success : function () {
                ops.fnSuccess.apply(callbackScope, arguments);
            },
            error : function () {
                ops.fnError.apply(callbackScope, arguments);
            }
        });
        
        $.ajax(ajaxConfig);
    };
    
    // solo ponemos evento si el usuario esta conectado
    if (comprobar()) {
        $(chain).live(eventName, bindClick);
    } else {
        $(chain).bind(eventName, suscripcionNoLogged);
    }
    
};

/** SUSCRIPCION - END */

/** CTO-SELECT-CONTENT */
cto.selectContent = function () {
    var isFlash9;
    // Solo intentamos copiar si estamos en flash9. flash10 esta deshabilitado por seguridad
    isFlash9= function() {
        var r;
        try { 
            if(window.navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){ 
                r = new RegExp("^,?(.+),?$");
                return (window.navigator.plugins["Shockwave Flash 2.0"] || window.navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(r)[1].split(',')[0] === "9"; 
            } 
        } catch(e) {
            return false;
        }
        return false;
    };
    if( !$.browser.msie && !isFlash9() ) {
        $(".cto-select-content-btn a").text('Marcar');
    }
    $(".cto-select-content-btn a").bind("click", function (e) {
        var contenedor, valor;
        contenedor = $(e.target).closest('.cto-select-content-wrap').find('.cto-select-content-target');
        contenedor.focus();
        contenedor.select();
        valor = contenedor.val();
        if( $.browser.msie || isFlash9() ) {
            $.copy(valor);
        }
        return false;
    });
    $(".cto-select-content-btn").css({visibility: 'visible'});
};
/** CTO-SELECT-CONTENT */

cto.trackRecurso = function(options) {
    var ops, defaults, oPixel;
    defaults = {
        srcPixel: cto.defaults.trackPixel.src
    };
    ops = $.extend( {}, defaults, options || {});
    ops.params = ops.params || {};

    ops.params.rd = cto.random();
    if( ops.rid  ) {
        ops.params.rid = ops.rid;
    } else if ( ops.xref ) {
        ops.params.xref = ops.xref;
    } else {
        return;
    }
    ops.params.r  = encodeURIComponent(document.location);
    ops.params.re = encodeURIComponent(document.referrer);

    /* Agregamos url y referer */
    oPixel = new Image();
    oPixel.src = ops.srcPixel +'?'+ $.param(ops.params);
    return;
};

/** ENTREVISTAS CON WEBCAM **/
cto.loadWebCam = function(options) {
   var ops, defaults, src, webCamSalida; 
   defaults = {
      idEnt: '',
      urlEnt: 'entrevistas_webcam.html',
      server: 'cuatro2.pre.prisacom.int',
      ctn: 'cto-ent-wc',
      ctnWebCam: '.cto-ctn-webcam',
      btnWebCam: '.cto-btn-webcam',
      flagSalida: 'false'
   };
   
   ops = $.extend( {}, defaults, options || {});
   $(ops.btnWebCam).click(function () {
       src = ops.server + "/" + ops.urlEnt;
       if(ops.flagSalida === 'false') {
           $(ops.ctnWebCam).html('');
           $(ops.ctnWebCam).html(webCamSalida({src: src, idEnt: ops.idEnt}));
       }else{
           webCamSalida({src: src, idEnt: ops.idEnt, flagSalida: ops.flagSalida});
       }
       return false;
   });

   /** Aqui se controla que la salida de la webcam vaya en el hueco de la imagen del entrevistado o en un PopUp **/
   /** Esto es controlado por un flag flagSalida **/
   webCamSalida = function (options) {
       var iframe, params, popupConf;
       defaults = {
           scrolling: 'no',
           frameborder: 'no',
           width: '320',
           height: '240',
           alt: 'webcam',
           src: '',
           tagName: 'IFRAME',
           flagSalida: 'false'
       };
       if(options.idEnt) { 
           ops.id = options.idEnt;
           params = '?id=' + ops.id;
       }
       ops = $.extend( {}, defaults, options || {});
       if(ops.flagSalida === 'false') {
           iframe = $(document.createElement(ops.tagName));
           iframe.attr('src', 'http://' + ops.src + params);
           iframe.attr('scrolling', ops.scrolling);
           iframe.attr('frameborder', ops.frameborder);
           iframe.attr('width', ops.width);
           iframe.attr('height', ops.height);
           iframe.attr('alt', ops.alt);
           return iframe;
       }else{
           popupConf = "scrollbars=" + ops.scrolling + ",width=" + ops.width + ",height=" + ops.height;
           window.open('http://' + ops.src + params, ops.alt, popupConf);     
           return false;
       }
   };
};


cto.favoritos = function(options) {
    var defaults, ops ;
    defaults = {
        clsFav: 'cto-add-fav'
    };
    ops = $.extend( {}, defaults, options || {});
    $('.'+ops.clsFav).bookmarkThis();

};

cto.homepage = function(options) {
    var defaults, ops, fnAlert, args ;
    defaults = {
        clsHome: 'cto-add-ini',
        url : window.location.href
    };
    ops = $.extend( {}, defaults, options || {});
    args = [cto.defaults.add2FavHTML, true];
    fnAlert = cto.alert;

    $('.'+ops.clsHome).setHomePage({ url : ops.url, fn: fnAlert, args: args});
};

/***** Paginacion estatica ***/

cto.staticPaging = function(ops) {
    var defaults = {}, all;
    defaults = {
        eventName: 'click.staticPaging',
        storeKey: 'staticPaging',
        pgn: 'cto-pgn-',
        clsContainer:'cto-pg-static',
        clsNoAction: 'cto-no-action',
        clsHidden: 'cto-oculto',
        clsActive: 'cto-active',
        clsNavLinks: 'cto-pg-nav',
        clsNavHn: 'cto-hn',
        clsNext: 'cto-hn-next',
        clsPrev: 'cto-hn-prev',
        clsFirst:'cto-hn-first',
        clsLast: 'cto-hn-last',
        clsInfo: 'cto-pg-info',
        clsInfoTpl: 'cto-pg-info-tpl',
        clsItem: 'cto-pg-item',
        clsNavItem: 'cto-pg-nav-item',
        infoTpl: '{pagina} de {total}'
    };
    ops = jQuery.extend({}, defaults, ops );
    all = $('.'+ops.clsContainer);
    if( !all.length ) { return false; }
    all.each( function(i, e) {
        var ctn,ctnClasses, prev, next, first, last, pages, showLink, start, info, info_tpl,links, move,infolinks, infopagina, circular, clickNext, clickPrev;
        ctn = $(this);
        showLink = 5;
        start = 1;
        circular = false;
        clickNext = false;
        clickPrev = false;
        ctnClasses = ctn.attr('class').split(' ');
        jQuery.each(ctnClasses, function(i, e) {
            var x = e.match(/cto-pg-show-links-([0-9]+)/),
                cNext =  e.match(/cto-pg-click-next/ ),
                cPrev =  e.match(/cto-pg-click-prev/ ),
                cir =  e.match(/cto-pg-circular/),
                st = e.match(/cto-pg-start-([0-9]+)/);
                
            if( x ) {
                showLink = parseInt(x[1], 10);
            } else if ( cNext ) {
                clickNext = true;
            } else if (cPrev ) {
                clickPrev = true;
            } else if ( cir ) {
                circular = true;
            } else if ( st) {
                start = parseInt(st[1], 10);
            } 

        });
        ctn.find('.'+ops.clsItem+':not(:eq('+(start-1)+'))').addClass(ops.clsHidden);
        ctn.find('.'+ops.clsItem+':eq('+(start-1)+')').removeClass(ops.clsHidden);
        
        pages = ctn.find('.'+ops.clsItem);

        pages.each(function(i,el) {
            var $el = $(el);
            $el.addClass(ops.pgn+(i+1));
        });

        if( clickNext ) {
            pages.addClass(ops.clsNext);
        } else if( clickPrev ) {
            pages.addClass(ops.clsPrev);
        } 

        prev = ctn.find('.'+ops.clsPrev);
        next = ctn.find('.'+ops.clsNext);
        first= ctn.find('.'+ops.clsFirst);
        last = ctn.find('.'+ops.clsLast);

        info = ctn.find('.'+ops.clsInfo);
        info_tpl = ctn.find('.'+ops.clsInfoTpl);
        
        links = ctn.find('.'+ops.clsNavLinks);
        
        move = function(dir) {
            var page = ctn.data(ops.storeKey);
            if( ( dir === 1 &&  page === pages.length  ) || ( dir === -1 && page === 1) )  {
                if( circular ) {
                    if( dir === 1 ) {page = 0;}
                    else if( dir === -1 ) { page = pages.length +1; }
                } else {
                    return; 
                }
            }
            page += dir;
            ctn.find('.'+ops.clsNavHn).children().removeClass(ops.clsNoAction);
            if( page === pages.length ) {
                next.addClass(ops.clsNoAction);
                last.addClass(ops.clsNoAction);
            }
            if( page === 1 ) {
                prev.addClass(ops.clsNoAction);
                first.addClass(ops.clsNoAction);
            }
            ctn.data(ops.storeKey, page);
            pages.filter( ':not(.'+ops.pgn+ page+')').addClass(ops.clsHidden).removeClass(ops.clsActive);
            pages.filter( '.'+ops.pgn+ page).removeClass(ops.clsHidden).addClass(ops.clsActive);
            infopagina(page, pages.length);
            infolinks(page, pages.length, showLink);
        };

        infopagina = function(p, t) {
            var tpl, msg;
            if( !info.length ) { return; }
            tpl = ops.infoTpl;
            if( info_tpl.length ) {
                tpl = info_tpl.html();
            }
            msg = tpl.replace( /\{pagina\}/, p ).replace( /\{total\}/,  t);
            info.html( $('<div/>').html( msg ) );
        };
        infolinks = function(p, t, n) {
            var x, i, a, ul;
            if( !links.length ) { return; }
            if( p < n ) {
                i = 1;
                x = n+1;
            } else if( p> (t-n) ){
                i= t-n+1;
                x = t+1;
            } else {
                i = p - Math.floor(n/2);
                x = i+n;
            }
            ul = $('<ul/>');
            for(;i<x; i+=1) {
                a = $('<a/>').text(i);
                if ( i !== p ) {
                    a.addClass(ops.clsNavItem);
                } else {
                    a.addClass(ops.clsActive).addClass(ops.clsNoAction);
                }
                ul.append( $('<li/>').html(a ) );
            }
            
            links.html( ul );
            links.find('.'+ops.clsNavItem).bind(ops.eventName, function(e) {
                var p = parseInt($(this).text(), 10); 
                e.preventDefault();
                if( $(this).hasClass(ops.clsNoAction) ) { return; }
                ctn.data(ops.storeKey, p);
                move( 0);
            });
        };

        infopagina(start, pages.length);
        infolinks(start, pages.length, showLink);
        prev.addClass(ops.clsNoAction);
        first.addClass(ops.clsNoAction);
        ctn.data(ops.storeKey, start);
        move(0);
        
        // TODO: agregar transiciones entre paginas
        //var h = ctn.find('.cto-pg-ctn').height(); 
        //pages.addClass('cto-pos-abs');
        //ctn.find('.cto-pg-ctn').height(h); 

        next.unbind(ops.eventName);
        next.bind(ops.eventName, function(e) {
            move(1);
            e.preventDefault();
        });
        
        prev.unbind(ops.eventName);
        prev.bind(ops.eventName, function(e) {
            move(-1);
            e.preventDefault();
        });
        
        first.unbind(ops.eventName);
        first.bind(ops.eventName, function(e) {
            ctn.data(ops.storeKey, 1); 
            move(0);
            e.preventDefault();
        });
        
        last.unbind(ops.eventName);
        last.bind(ops.eventName, function(e) {
            ctn.data(ops.storeKey, pages.length); 
            move(0);
            e.preventDefault();
        });
    });
};


/** TRIVIAL - START */

cto.trivial = function(options){
    var defaults, ops, ctn, pagClass, btnNext, enumOptions, enumQuestions,getQuestionPoints, showResult, counter, nextQuestion, lastQuestion, hideElementsNext;
    if( !$('.'+options.ctn ).length ) { return; }

    defaults = {
        eventName:'click.trivial',
        clsPick: 'cto-tri-sel',
        clsQuestion: 'cto-tri-preg',
        clsOption: 'cto-tri-opt',
        clsBtnNext:'cto-hn-next',
        acumulados: 0,
        pregOK: 0,
        pregNOK: 0,
        optionCounter: {0: 0, 1:0, 2:0, 3:0, 4:0, 5:0},
        setCounter: 1

    };
    ops = jQuery.extend({}, defaults, options||{});
    if (!ops.ctn) { return; }

    ctn = $('.'+ops.ctn);

    // Paginacion estatica    
    pagClass = ops.ctn + '-pag-static';
    ctn.addClass(pagClass);   
    cto.staticPaging({clsContainer: pagClass});

    ctn.find('.'+ops.clsQuestion).removeAttr('style');
    
    btnNext = ctn.find('.'+ops.clsBtnNext);
    btnNext.hide();

    enumOptions  = function (i,e) {
        var x;
        e = $(e);
        x = e.attr('className').match(/cto-opt-([0-9]+)/); 
        if( x ) {
           e.data('trivial.option', parseInt(x[1], 10)-1);
        }
    };

    enumQuestions = function (i, e) {
        var x; 
        e = $(e);
        x =  e.attr('className').match(/cto-prg-([0-9]+)/);
        if( x ) {
            e.data('trivial.question', parseInt(x[1], 10));
        }
        e.find('.'+ops.clsOption).each(enumOptions);
        
    };

    ctn.find('.'+ops.clsQuestion).each(enumQuestions);

    getQuestionPoints = function(questionNum, optionNum) {
        if( ops.puntos && ops.puntos[questionNum] &&  ops.puntos[questionNum][optionNum] >= 0 ) {
                return ops.puntos[questionNum][optionNum] ;
        } else {
            return 0;
        }
    };
    hideElementsNext = function(element, lastQuestion) {
        element.hide();
        if (lastQuestion) {
            showResult();        
        }
    };

    nextQuestion = function(questionNum, trigger) {
        trigger = trigger || false;
        if( questionNum <= ops.total ) {
            if( trigger ) {
                btnNext.trigger('click');
                btnNext.hide();
            } else {
                //muestra el boton y lo oculta en el siguiente click
                btnNext.show();
                //btnNext.one(ops.eventName, function() {$(this).hide();});
                lastQuestion = (questionNum == ops.total)? 1:0;
                btnNext.one(ops.eventName, function() { hideElementsNext(btnNext, lastQuestion); });
            }
        } else {
            btnNext.hide();
            showResult();
        }
    };

    showResult = function() {
        var j, optionMax, optionRes;

       switch( ops.tipo ) {
           case 'Q':
              ctn.find('.result .'+ops.ctn+'-ok' + ' p span').parent().html('Respuestas correctas: ' + ops.pregOK + '<span></span>');
              ctn.find('.result .'+ops.ctn+'-nok' + ' p span').parent().html('Respuestas incorrectas: ' + ops.pregNOK + '<span></span>');
              var percOK = parseInt((ops.pregOK * 100/ ops.total), 10);
              var percNOK = 100-percOK;
              ctn.find('.'+ops.ctn+'-pok').html(percOK+'%');
              ctn.find('.'+ops.ctn+'-pnok').html(percNOK+'%');
              ctn.find('.'+ops.ctn+'-bok').css('width', percOK+'%');
              ctn.find('.'+ops.ctn+'-bnok').css('width', percNOK+'%');
              
              for (j=0; j < ops.msg.length; j++) {
                   if (ops.msg[j][0] <= ops.pregOK && ( ops.pregOK <= parseInt(ops.msg[j][1], 10) || j+1 == ops.msg.length ) ) {
                       ctn.find('.'+ops.ctn+'-res-msg').html(ops.msg[j][2]);
                       break;
                   }
              }    
              break;
              
           case 'T':
              optionMax = 0;
              optionRes = 0;
              for (j=0; j<5; j++) {
                   if (ops.optionCounter[j] > optionMax) {
                       optionMax = ops.optionCounter[j];
                       optionRes = j;
                   }
              }
              ctn.find('.'+ops.ctn+'-res-msg').html(ops.msg[optionRes][2]);
              ctn.find('.'+ops.ctn+'-res-text').html(ops.msg[optionRes][3]);
              ctn.find('.'+ops.ctn+'-res-img').attr('src', ops.msg[optionRes][4]);
              break;

              
           case 'M':
              optionRes = 0;
              for (j=0; j < ops.msg.length; j++) {
                   if (ops.msg[j][0] <= ops.acumulados && ( ops.acumulados <= parseInt(ops.msg[j][1], 10) || j+1 == ops.msg.length ) ) {
                       optionRes = j;
                       break;
                   }
              }
              ctn.find('.'+ops.ctn+'-res-msg').html(ops.msg[optionRes][2]);
              ctn.find('.'+ops.ctn+'-res-text').html(ops.msg[optionRes][3]);
              ctn.find('.'+ops.ctn+'-res-img').attr('src', ops.msg[optionRes][4]);
            
              break;
        }
    
        // Para el contador
        counter();
        
        //ocultamos todas las preguntas
        ctn.find('.'+ops.clsQuestion).hide();    
        ctn.find('.'+ops.ctn + '-resp').show();  
    };


    counter = function() {
        if (ops.setCounter) {
            ops.setCounter = 0; //descomentar para contar solo una vez por carga
            
            var ajaxData, ajaxConfig;
            ajaxData = ops.counter;
            ajaxData.format = 'JSON';
    
            if (!ajaxData || !ajaxData.modulo) { return false; }
            
            ajaxConfig = $.extend( {}, cto.defaults.ajaxConfig, ops.ajaxConfig, {
                data : $.param(ajaxData),
                success : function () {},
                error : function () {}
            });
            
            $.ajax(ajaxConfig);
         }
    };




    function showRights(question, questionNum, optionSelected) {
        // buscar en ops.puntos las que tengan 0 son incorrectas y las que tengan 1 correctas
        question.find('.'+ops.clsOption).each(function(i,e){
            var $e = $(e), optionNum = $e.data('trivial.option'), right, texto;
            
            if (optionSelected != optionNum) {
                $e.addClass('no-sel');
                $e.find('.btn').hide();
                return;
            }
            right = ( ops.puntos && ops.puntos[questionNum] &&  ops.puntos[questionNum][optionNum] >= 1 ) ? true: false;

            if (right) {
                $e.find('.rojo').addClass('verde');
                //$e.find('.rojo').removeClass('rojo');
            }
            texto = (right)? 'Correcta' : 'Incorrecta';
             
            //lo mostramos
            $e.find('.'+ ops.clsPick).html(texto);

        });

    }


    function updateStats() {
        ctn.find('.'+ops.ctn+'-ok' + ' span').parent().html('<span>' + ops.pregOK + '</span>');
        ctn.find('.'+ops.ctn+'-nok' + ' span').parent().html('<span>' + ops.pregNOK + '</span>');
    }


    function showSelected(question, questionNum, optionSelected) {
        // buscar en ops.puntos las que tengan 0 son incorrectas y las que tengan 1 correctas
        question.find('.'+ops.clsOption).each(function(i,e){
            var $e = $(e), optionNum = $e.data('trivial.option');

            if (optionSelected != optionNum) {
                $e.addClass('no-sel');
                $e.find('.btn').hide();
                return;
            }

            $e.find('.rojo').addClass('verde');
            $e.find('.'+ ops.clsPick).html('Seleccionada');
        });
    }

    // captura el click
    function onClickOption(e) {
        var $this = $(this), 
            question = $this.closest('.'+ops.clsQuestion), 
            questionNum = question.data('trivial.question'),
            option = $this.closest('.'+ops.clsOption),
            optionNum = option.data('trivial.option'), 
            puntos = 0,
            asignacion;
            switch( ops.tipo ) {
                case 'Q':
                        puntos = parseInt(getQuestionPoints(questionNum, optionNum), 10);
                        ops.acumulados += puntos;
                        if (puntos) {
                            ops.pregOK++;
                        } else {
                            ops.pregNOK++;
                        }
                        // actualizar contador correctas/incorrectas
                        updateStats();
                        
                        //habilitamos el boton siguiente
                        nextQuestion(questionNum);
                        // marcar correctas/incorrectas
                        showRights(question, questionNum, optionNum);
                        
                    break;
                case 'T':
                        asignacion = parseInt(getQuestionPoints(questionNum, optionNum), 10); 
                        ops.optionCounter[asignacion-1]++;                        
                        //habilitamos el boton siguiente
                        nextQuestion(questionNum);
                        // marcar seleccionada
                        showSelected(question, questionNum, optionNum);                        
                    break;
                case 'M':
                        puntos = parseInt(getQuestionPoints(questionNum, optionNum), 10);
                        ops.acumulados += puntos;
                        //habilitamos el boton siguiente
                        nextQuestion(questionNum);
                        // marcar correctas/incorrectas
                        showSelected(question, questionNum, optionNum);
                 
                    break;

            }

            // comprobar si es la ultima pregunta mostrar el resultado

    }

    // captura el click
    function onClickRestart(e) {
        ops.acumulados = 0;
        ops.pregOK = 0;
        ops.pregNOK = 0;
        ops.optionCounter = {0: 0, 1:0, 2:0, 3:0, 4:0, 5:0};
        ops.setCounter = 1;

        // Inicializamos pantalla de resultados
        ctn.find('.'+ops.ctn+'-ok' + ' span').parent().html('<span>0</span>');
        ctn.find('.'+ops.ctn+'-nok' + ' span').parent().html('<span>0</span>');
               
        ctn.find('.'+ops.ctn+'-pok').html('0%');
        ctn.find('.'+ops.ctn+'-pnok').html('0%');
        
        ctn.find('.'+ops.ctn+'-bok').css('width', '50%');
        ctn.find('.'+ops.ctn+'-bnok').css('width', '50%');
        ctn.find('.'+ops.ctn+'-res-msg').html('Éste es tu resultado');
        ctn.find('.'+ops.ctn+'-res-text').html('');
        ctn.find('.'+ops.ctn+'-res-img').attr('src', '');
        
        ctn.find('.'+ops.clsOption+' .verde').addClass('rojo');
        ctn.find('.'+ops.clsOption+' .verde').removeClass('verde');
        ctn.find('.no-sel').removeClass('no-sel');
        
        //ctn.find('.'+ops.clsOption+' .btn').removeClass('cto-oculto');
        ctn.find('.'+ops.clsOption+' .btn').show();
        
        ctn.find('.'+ ops.clsPick).html('Seleccionar');        
        //ctn.find('.'+ ops.clsPick).show();
        
        //Ocultamos resultado
        ctn.find('.'+ops.ctn + '-resp').hide();
        
        // Eliminamos estilos
        ctn.find('.'+ops.clsQuestion).removeAttr('style');
                
        // Preparamos paginacion
        cto.staticPaging({clsContainer: pagClass});
    }
    
    ctn.find('.'+ops.clsPick).bind(ops.eventName, onClickOption );
    ctn.find('.'+ops.ctn+'-restart').bind(ops.eventName, onClickRestart);


};

/** TRIVIAL - END */

cto.drawAudioPlayer = function(config) {
    var defaults = {
        autoplay: 0,
        titulo: '',
        skin: 'cuatro' 
    }, 
    conf  = $.extend({}, defaults, config);
    window.setPlayer(conf); 
};

/** TOGGLECLASSES */
cto.toggleClasses = function (options) {
    var defaults, ops,bindClick,hnd;
    if( !$('.'+options.ctn ).length ) { return; }
    
    defaults = {
        clsHndSfx: '-handler',
        clsLnkSfx: '-lnk-',
        clsPanelSfx: '-panel',
        clsMsgSfx: '-msg',
        initStatus: 'a',
        clsToggleA: 'cto-tgc-cls-a',
        clsToggleB: 'cto-tgc-cls-b',
        msgToggleA: 'class a',
        msgToggleB: 'class b'
    };
    
    
    // aseguramos que los elementos tienen las clases iniciales
    function checkInitStatus(i, e) {
        var selectorPanel, selectorMsg;

        e = $(e);
        
        selectorPanel = '.' + e.data('tgc.lnk') + '.' + ops.ctn + ops.clsPanelSfx;
        selectorMsg = '.' + e.data('tgc.lnk') + '.' + ops.ctn + ops.clsMsgSfx;
        
        // ocultamos o mostramos todos los elementos relacionados
        if (ops.initStatus == 'a') {
            $(selectorPanel).addClass(ops.clsToggleA).removeClass(ops.clsToggleB);
            $(selectorMsg).html(ops.msgToggleA);
            e.data('tgc.status', 'a');
        } else {
            $(selectorPanel).addClass(ops.clsToggleB).removeClass(ops.clsToggleA);
            $(selectorMsg).html(ops.msgToggleB);            
            e.data('tgc.status', 'b');          
        }   
    }
    
    // obtenemos la clase que relaciona los elementos asociados a un handler
    function getLinkClass(i, e) {
        var mask, matches;
        e = $(e); 
        mask = new RegExp('(' + ops.ctn + ops.clsLnkSfx + '[0-9]+)');
        matches = e.attr('className').match(mask);
        if(matches ) {
            e.data('tgc.lnk', matches[1]);
        }
    }

    // cambiamos las clases y mostramos el mensaje
    bindClick = function (ev) {
        var selectorPanel, selectorMsg;
        
        hnd = $(this);

        selectorPanel = '.' + hnd.data('tgc.lnk') + '.' + ops.ctn + ops.clsPanelSfx;
        selectorMsg = '.' + hnd.data('tgc.lnk') + '.' + ops.ctn + ops.clsMsgSfx;
        
        // ocultamos o mostramos todos los elementos relacionados
        if (hnd.data('tgc.status') == 'a') {
            $(selectorPanel).addClass(ops.clsToggleB).removeClass(ops.clsToggleA);
            $(selectorMsg).html(ops.msgToggleB);            
            hnd.data('tgc.status', 'b');
        } else {
            $(selectorPanel).addClass(ops.clsToggleA).removeClass(ops.clsToggleB);
            $(selectorMsg).html(ops.msgToggleA);
            hnd.data('tgc.status', 'a');            
        }   
    };

    ops = jQuery.extend({}, defaults, options||{});
    if (!ops.ctn) { return; }   
    hnd = $('.' + ops.ctn + ops.clsHndSfx);
    hnd.each(getLinkClass);
    hnd.each(checkInitStatus);
    hnd.bind('click.toggleClasses', bindClick);
};
