/*
PyWiki2Xhtml Javascript Wikibar
Developed and designed by Thenon David
www.sveetch.biz

Wikibar API 2.0.0

This script is part of PyWiki2Xhtml. 
It requires jQuery library >= 1.2.6

Plugin qui rajoute la barre de boutons de raccourcis wiki
au dessus du textarea et pose la capture d'évènement de clic sur
ces boutons

La wikibar est placée avant l'objet ciblé, par défaut cet objet est considéré 
comme un textarea.

@target_element_id: Indique un id de textarea autre que l'id de l'objet ciblé
dans l'init de la class. A faire si l'id de base n'est pas celui d'un 
textarea. (Utile si on veut placer la wikibar avant que le textarea soit 
placé/modifié dans le DOM)
*/
jQuery.fn.Wikibar = function(target_element_id, options) {
    
    // Options par défauts
    var defaults = {
        'with_task_option': false,
        'with_wikiword_option': true,
        'with_flv_option': false,
        'with_access_keys': true,
        //'with_help_syntax': ["Aide sur la syntaxe wiki", '/wiki/syntax/help/'],
        'with_help_syntax': false,
        'syntax_schema': {
            'heading1': {
                'label':"Entête de niveau 1",
                'access_key':"1",
                'enclosure': ["!!! ", "\n"],
                'control_activation': false
            },
            'heading2': {
                'label':"Entête de niveau 2",
                'access_key':"2",
                'enclosure': ["!! ", "\n"],
                'control_activation': false
            },
            'heading3': {
                'label':"Entête de niveau 3",
                'access_key':"3",
                'enclosure': ["! ", "\n"],
                'control_activation': false
            },
            'strong': {
                'label':"Gras",
                'access_key':"b",
                'enclosure': ["__", "__"],
                'control_activation': false
            },
            'em': {
                'label':"Emphase",
                'access_key':"i",
                'enclosure': ["''", "''"],
                'control_activation': false
            },
            'code': {
                'label':"Code",
                'access_key':"c",
                'enclosure': ["@@", "@@"],
                'control_activation': false
            },
            'del': {
                'label':"Surligné",
                'access_key':"s",
                'enclosure': ["--", "--"],
                'control_activation': false
            },
            'add': {
                'label':"Souligné",
                'access_key':"u",
                'enclosure': ["++", "++"],
                'control_activation': false
            },
            'wikiword': {
                'label':"Mot wiki",
                'access_key':"w",
                'enclosure': ["¶¶¶", "¶¶¶"],
                'control_activation': 'with_wikiword_option'
            },
            'link': {
                'label':"Lien",
                'access_key':"a",
                'enclosure': ["[", "]", "Entrez une url", jQuery.fn.Wikibar.promptForUrl],
                'control_activation': false
            },
            'flv': {
                'label':"Insérer le code d'une vidéo Flash",
                'access_key':"m",
                'enclosure': ["«««", "»»»", "Entrez le code html fourni", jQuery.fn.Wikibar.promptForFlvCode],
                'control_activation': 'with_flv_option'
            },
            'task': {
                'label':"Lien direct vers une tâche de Checkit",
                'access_key':"x",
                'enclosure': ["[", "]", "Entrez l'identifiant d'une tâche", jQuery.fn.Wikibar.promptForTask],
                'control_activation': 'with_task_option'
            },
            'image': {
                'label':"Insérer une image",
                'access_key':"p",
                'enclosure': ["((", "))", "Entrez un lien vers une image", jQuery.fn.Wikibar.promptForImage],
                'control_activation': false
            }
        }
    };
    
    // Gestion des options envoyés
    var opts = jQuery.extend(defaults, options);
    
    // Il est pas vraiment prévu d'utiliser ce plugin avec plusieurs éléments 
    // d'un coup, mais on laisse le support vu que ça mange pas de pain
    return this.each(function(){
        // Si il n'est pas spécifié en argument, l'id du textarea ciblé devient 
        // celui de l'objet donné à l'instanciation
        if( !target_element_id ) {
            target_element_id = jQuery(this).attr('id');
        }
        // Lance la méthode principale
        Main(false, this, target_element_id);
    });

    /*
    * Lance tout le processus
    */
    function Main(e, elem, target_element_id) {
        var obj;
        var target_element_id;
        var undefined;
        obj = elem;
        target_element_id = target_element_id;
        
        // Crée le div principal de la wikibar et l'ajoute avant l'objet ciblé
        var toolbar_body_Html = jQuery('<div>').attr({
            'id': "ui_wikitoolbar",
            'class': "wikitoolbar"
        });
        
        // Ajoute tout les boutons qui sont activés
        $.each( opts.syntax_schema, function(key, val){
            if(val.control_activation == false || (val.control_activation != false && opts[val.control_activation])) {
                toolbar_body_Html.append( 
                    add_button(key, val.label, val.access_key, function() {
                        jQuery.fn.Wikibar.enclose(target_element_id, val.enclosure[0], val.enclosure[1], val.enclosure[2], val.enclosure[3]);
                    })
                );
            }
        });
        
        // Lien d'aide optionel
        if(opts.with_help_syntax) {
            var help_link = jQuery('<a>').attr({
                'title': opts.with_help_syntax[0],
                'href': opts.with_help_syntax[1],
                'id': "wikibarButton_help"
            }).text(opts.with_help_syntax[0]);
            if(opts.with_access_keys) help_link.attr({'accesskey': "h"});
            // Gestion du clic
            help_link.click(function(){
                try { window.open(opts.with_help_syntax[1], "Wikibar_help_syntax") } catch (e) { } return false
            });
            // Ajout au DOM de la toolbar
            toolbar_body_Html.append(help_link);
        }
        
        // Termine en ajoutant une cale à la fin du div et le rajoute au document
        jQuery(toolbar_body_Html).append('<div class="cale"></div>');
        jQuery(obj).before(toolbar_body_Html);
    };


    /*
    * Méthode d'ajout d'un bouton à la Wikibar
    */
    function add_button(id, label, key, fn) {
        var button = jQuery('<a>').attr({
            'title': label,
            'href': "#",
            'id': "wikibarButton_"+id
        });
        // Access key optionelle
        if(opts.with_access_keys) button.attr({'accesskey': key});
        // Gestion du clic
        button.click(function(){
            try { fn() } catch (e) { } return false
        });
        // Renvoi l'objet créé prêt à insérer
        return button;
    };
};

/*
* Enferme une séléction entre un @prefix et @suffix, en dernier argument cette 
* méthode peut recevoir une fonction supplémentaire qui se chargera du formatage
*/
jQuery.fn.Wikibar.enclose = function(target_id, prefix, suffix, label, extFn) {
    var textarea = jQuery("#"+target_id)[0];
    textarea.focus();
    
    // Récupère la séléction en cours si y'en a une et ses paramètres de position
    var start, end, sel, scrollPos, subst, undefined;
    if (typeof(document["selection"]) != "undefined") {
        sel = document.selection.createRange().text;
    } else if (textarea["setSelectionRange"] != undefined) {
        start = textarea.selectionStart;
        end = textarea.selectionEnd;
        scrollPos = textarea.scrollTop;
        sel = textarea.value.substring(start, end);
    }
    // Rajoute un espace en fin pour éviter qu'il se fasse bouffer
    if (sel.match(/ $/)) {
        sel = sel.substring(0, sel.length - 1);
        suffix = suffix + " ";
    }
    
    // Si la balise a une fonction dédicacée pour le formatage, on l'utilise, 
    // sinon on utilise "l'enclosure" de la balise
    if(extFn){
        subst = extFn(sel, label, prefix, suffix);
    } else {
        subst = prefix + sel + suffix;
    }
    if (document["selection"] != undefined) {
        var range = document.selection.createRange().text = subst;
        textarea.caretPos -= suffix.length;
    } else if (textarea["setSelectionRange"] != undefined) {
        textarea.value = textarea.value.substring(0, start) + subst +
                        textarea.value.substring(end);
        if (sel) {
            textarea.setSelectionRange(start + subst.length, start + subst.length);
        } else {
            textarea.setSelectionRange(start + prefix.length, start + prefix.length);
        }
        textarea.scrollTop = scrollPos;
    }
};

/*
* Affiche un prompt pour renseigner les options d'un lien standard
*/
jQuery.fn.Wikibar.promptForUrl = function(s, label, prefix, suffix) {
    var url = prompt(label, 'http://');
    if (url) {
        return prefix + s +'|'+ url + suffix;
    }
    return s;
};

/*
* Affiche un prompt pour renseigner les options d'un lien vers une tâche
*/
jQuery.fn.Wikibar.promptForTask = function(s, label, prefix, suffix) {
    var id = prompt(label, '');
    if (id) {
        if (!s) {
            s = '#'+id;
        }
        return prefix + s +'|task://'+ id + suffix;
    }
    return s;
};

/*
* Affiche un prompt pour renseigner les options d'une image
*/
jQuery.fn.Wikibar.promptForImage = function(s, label, prefix, suffix) {
    var url = prompt(label, 'http://');
    if (url) {
        return prefix + url +'|'+ s + suffix;
    }
    return s;
};

/*
* Affiche un prompt pour renseigner les options d'une vidéo Flash
* Prévu pour parser un code <embed/> donné par dailymotion/youtube/yahoo/..
*/
jQuery.fn.Wikibar.promptForFlvCode = function(s, label, prefix, suffix) {
    var code = prompt(label, '');
    // Si on a bien un morceau de code
    if (code) {
        // Recherche d'un @src
        var url = "";
        var url_res = code.match(/src="[^"]*"/);
        var url_res2 = code.match(/src='[^']*'/);
        // On a une url
        if (url_res || url_res2) {
            if(url_res) {
                url = url_res[0].match(/src="(.*)"/)[1];
            } else {
                url = url_res2[0].match(/src='(.*)'/)[1];
            }
            // Recherche d'un @flashvars
            var flvars_res = code.match(/flashvars="[^"]*"/i);
            var flvars_res2 = code.match(/flashvars='[^']*'/i);
            if(flvars_res) {
                url = url +'|'+ flvars_res[0].match(/flashvars="(.*)"/i)[1];
            } else if(flvars_res2) {
                url = url +'|'+ flvars_res2[0].match(/flashvars='(.*)'/i)[1];
            }
            // Renvoi l'url et le flashvars optionnel
            return s + prefix + url + suffix;
        }
    }
    return s;
};
