/www/jssrc/blerg/Util.js
blerg = window.blerg || {};

blerg.Util = {};

// Dirty, terrible shim for rewritten links below
blerg.Util.qlink = function(ev) {
    try {
        location.href = ev.target.href;
    } catch(e) { }
    enyo.$.blerg.bubble('onNavigate');
    return false;
}

blerg.Util.formatLinkHooks = [
    BlergMedia
];

blerg.Util.formatMarkdownLinks = function(l) {
        m = l.match(/(\s[()\[\]{}]?|^)\[([^\]]+)\]\((https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/[^)"]*?)?|mailto:[^)"]*?)(\s([^)]*))?\)/);
        if (!m)
            return l;
        var whitespace = m[1];
        var data = {
            label: m[2],
            url: m[3],
            extra: m[5]
        };

        for (var i = 0; i < blerg.Util.formatLinkHooks.length; i++) {
            var newdata = blerg.Util.formatLinkHooks[i].process(data);
            if (newdata)
                data = newdata;
            else
                console.warn("Format Link Hook " + i + " returned null");
        }
        var s = whitespace + '<a href="' + data.url + '">' + data.label + '</a>' +
            (data.widget ? ' ' + data.widget : '');
        return l.slice(0, m.index) + s + blerg.Util.formatMarkdownLinks(l.slice(m.index + m[0].length));
}

blerg.Util.blergFormat = function(text) {
    var lines = text.split(/\r?\n/);
    if (lines[lines.length - 1] == '')
        lines.pop();

    var out = ['<p>'];
    var endpush = null;
    var listMode = false;
    var codeMode = false;
    var githubCodeMode = false;
    lines.forEach(function(l) {
        // Blank line
        if (l == '') {
            // Turn single linebreaks into paragraphs
            if (out[out.length - 1] == '<br>') {
                out[out.length - 1] = '<p>';
            }
            // End bullet list
            if (out[out.length - 1] == '</li>') {
                out.push('</ul>');
                out.push('<p>');
                listMode = false;
            }
            // End code mode
            if (codeMode) {
                out.push('</pre>');
                out.push('<p>');
                codeMode = false;
            }
            return;
        }

        // Sometimes I wish more languages had Perl's bistable .. operator.
        if (githubCodeMode) {
            if (l == '```') {
                out.push('</pre>');
                out.push('<p>');
                githubCodeMode = false;
            } else {
                // Sanitize HTML input
                l = l.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                out.push(l + "\n");
            }
            return;
        } else {
            if (l == '```') {
                out.push('<pre>');
                githubCodeMode = true;
                return;
            }
        }

        // Create a code block when lines begin with at least four spaces
        if (l.substr(0, 4) == '    ') {
            if (!codeMode) {
                out.push('<pre>');
                codeMode = true;
            }
            // Sanitize HTML input
            l = l.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
            out.push(l.substr(4) + "\n");
            return;
        } else {
            if (codeMode) {
                out.push('</pre>');
                codeMode = false;
            }
        }

        // Put quoted material into a special paragraph
        if (l[0] == '>') {
            var pi = out.lastIndexOf('<p>');
            if (pi != -1) {
                out[pi] = '<p class="quote">';
                l = l.replace(/^>\s*/, '');
            }
        }

        // Sanitize HTML input
        l = l.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

        // Turn HTTP URLs into links
        l = l.replace(/(\s[()\[\]{}]?|^)(https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/([^\s"]*[^.!,;?()\s])?)?)/g, '$1<a href="$2">$2</a>');

        // Turn markdown links into links
        l = blerg.Util.formatMarkdownLinks(l);

        // Turn *foo* into italics and **foo** into bold
        l = l.replace(/([^\w\\]|^)\*\*(\w[^*]*)\*\*(\W|$)/g, '$1<b>$2</b>$3');
        l = l.replace(/([^\w\\]|^)\*(\w[^*]*)\*(\W|$)/g, '$1<i>$2</i>$3');

        // Turn ~~foo~~ into strikethrough
        l = l.replace(/([^\w\\]|^)~~(\w[^~]*)~~(\W|$)/g, '$1<s>$2</s>$3');

        // Turn refs and tags into links
        l = l.replace(/(\s|^)#([A-Za-z0-9_-]+)/g, '$1<a href="#/tag/$2" class="ref" onclick="return blerg.Util.qlink(event)">#$2</a>');
        l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)(\/\d+)?/g, '$1<a href="#$2$3" class="ref" onclick="return blerg.Util.qlink(event)">@$2</a>');

        // Create lists when lines begin with *
        if (l[0] == '*') {
            if (!listMode) {
                var pi = out.lastIndexOf('<p>');
                out[pi] = '<ul>';
                listMode = true;
            }
            l = l.replace(/^\*\s*/, '');
            out.push('<li>');
            endpush = '</li>';
        }

        // Create headers when lines begin with = or #
        if (l[0] == '=' || l[0] == '#') {
            var m = l.match(/^([=#]+)/);
            var depth = m[1].length;
            if (depth <= 5) {
                l = l.replace(/^[=#]+\s*/, '').replace(/\s*[=#]+$/, '');
                out.push('<h' + depth + '>');
                endpush = '</h' + depth + '>';
            }
        }

        // Remove backslashes from escaped metachars
        l = l.replace(/\\([*\[\]@#~])/g, '$1');

        out.push(l);
        if (endpush) {
            out.push(endpush);
            endpush = null;
        } else {
            out.push('<br>');
        }
    });
    while (out[out.length - 1] == '<br>' || out[out.length - 1] == '<p>') {
        out.pop();
    }
    if (listMode) {
        out.push('</ul>');
    }
    if (codeMode || githubCodeMode) {
        out.push('</pre>');
    }

    return out.join('');
}