// RedBubble BubbleMail preview.
// Version 0.1
// 2008-06-03
// Copyright (c) 2008, Dave Pearson <http://www.davep.org/>
// Released under the GPL
// http://www.gnu.org/copyleft/gpl.html
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.  To install it, you need
// Greasemonkey: http://www.greasespot.net/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "RedBubble BubbleMail Preview", and click Uninstall.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          RedBubble BubbleMail Preview
// @namespace     http://www.davep.org/
// @description   Provides a simple BubbleMail preview facility.
// @include       http://www.redbubble.com/mybubble/bubblemail/new*
// ==/UserScript==

// Look for the private message form.
var pmForm = document.getElementById( 'private_message-form' );

// If we got it...
if ( pmForm ) {
   
   // Create the div that will hold the preview.
   var preview = document.createElement( 'div' );
   preview.className = 'private_message';

   // Create the preview button.
   var previewButton   = document.createElement( 'input' );
   previewButton.type  = 'submit';
   previewButton.value = "Preview";
   previewButton.addEventListener( 'click', function () { showPreview( preview ); }, true );

   // Insert the preview div.
   pmForm.parentNode.insertBefore( preview, pmForm );

   // Insert the preview link.
   preview.parentNode.insertBefore( previewButton, preview );
}

// Show the preview.
function showPreview( where )
{
   var editor = document.getElementById( 'message_message' );

   if ( editor ) {
      where.innerHTML =
         '<h2 style="color: red;">WARNING: This preview isn\'t perfect. Some things will fail to preview correctly. Sorry about that.</h2>' +
         textilizeThis( editor.value );
   } else {
      where.innerHTML = '<p style="color: red">I HAZ A FAIL!</p>';
   }
}

/*
    Make textareas textileable.
    (c) Phil Wilson, greasemonkey@philwilson.org
    based on Textileable by Roberto De Almeida (http://dealmeida.net/en/Projects/PyTextile/greasemonkey_and_textile.html)
    and the JS Textile function by Jeff Minard (http://www.creatimation.net/textile.js)   

    GPL.
*/

function textilizeThis(s) {
   var r = s;
    // quick tags first
    qtags = [['\\*', 'strong'],
             ['\\?\\?', 'cite'],
             ['\\+', 'ins'],  //fixed
             ['~', 'sub'],   
             ['\\^', 'sup'], // me
             ['@', 'code']];
    for (var i=0;i<qtags.length;i++) {
        ttag = qtags[i][0]; htag = qtags[i][1];
        re = new RegExp(ttag+'\\b(.+?)\\b'+ttag,'g');
        r = r.replace(re,'<'+htag+'>'+'$1'+'</'+htag+'>');
    }
    // underscores count as part of a word, so do them separately
    re = new RegExp('\\b_(.+?)_\\b','g');
    r = r.replace(re,'<em>$1</em>');
	
	//jeff: so do dashes
    re = new RegExp('[\s\n]-(.+?)-[\s\n]','g');
    r = r.replace(re,'<del>$1</del>');

    // links
    re = new RegExp('"\\b(.+?)\\(\\b(.+?)\\b\\)":([^\\s]+)','g');
    r = r.replace(re,'<a href="$3" title="$2">$1</a>');
    re = new RegExp('"\\b(.+?)\\b":([^\\s]+)','g');
    r = r.replace(re,'<a href="$2">$1</a>');

    // images
    re = new RegExp('!\\b(.+?)\\(\\b(.+?)\\b\\)!','g');
    r = r.replace(re,'<img src="$1" alt="$2">');
    re = new RegExp('!\\b(.+?)\\b!','g');
    r = r.replace(re,'<img src="$1">');
    
    // block level formatting
	
		// Jeff's hack to show single line breaks as they should.
		// insert breaks - but you get some....stupid ones
	    re = new RegExp('(.*)\n([^#\*\n].*)','g');
	    r = r.replace(re,'$1<br />$2');
		// remove the stupid breaks.
	    re = new RegExp('\n<br />','g');
	    r = r.replace(re,'\n');
	
    lines = r.split('\n');
    nr = '';
    for (var i=0;i<lines.length;i++) {
        line = lines[i].replace(/\s*$/,'');
        changed = 0;
        if (line.search(/^\s*(bq\.|>)\s+/) != -1) { line = line.replace(/^\s*(bq\.|>)\s+/,'\t<blockquote>')+'</blockquote>'; changed = 1; }
		
		// jeff adds h#.
        if (line.search(/^\s*h[1-6]\.\s+/) != -1) { 
	    	re = new RegExp('h([1-6])\.(.+)','g');
	    	line = line.replace(re,'<h$1>$2</h$1>');
			changed = 1; 
		}
		
		if (line.search(/^\s*\*\s+/) != -1) { line = line.replace(/^\s*\*\s+/,'\t<liu>') + '</liu>'; changed = 1; } // * for bullet list; make up an liu tag to be fixed later
        if (line.search(/^\s*#\s+/) != -1) { line = line.replace(/^\s*#\s+/,'\t<lio>') + '</lio>'; changed = 1; } // # for numeric list; make up an lio tag to be fixed later
        if (!changed && (line.replace(/\s/g,'').length > 0)) line = '<p>'+line+'</p>';
        lines[i] = line + '\n';
    }
	
    // Second pass to do lists
    inlist = 0; 
	listtype = '';
    for (var i=0;i<lines.length;i++) {
        line = lines[i];
        if (inlist && listtype == 'ul' && !line.match(/^\t<liu/)) { line = '</ul>\n' + line; inlist = 0; }
        if (inlist && listtype == 'ol' && !line.match(/^\t<lio/)) { line = '</ol>\n' + line; inlist = 0; }
        if (!inlist && line.match(/^\t<liu/)) { line = '<ul>' + line; inlist = 1; listtype = 'ul'; }
        if (!inlist && line.match(/^\t<lio/)) { line = '<ol>' + line; inlist = 1; listtype = 'ol'; }
        lines[i] = line;
    }

    r = lines.join('\n');
	// jeff added : will correctly replace <li(o|u)> AND </li(o|u)>
    r = r.replace(/li[o|u]>/g,'li>');

    return r;
}
