/**
 * gbRichEdit - getButterfly Rich Text Editor plugin - http://getbutterfly.com/
 * 
 * @author	Ciprian Popescu
 * @version 5.0
 * 
 * Licensed under The MIT License
 * http://opensource.org/licenses/mit-license.php
 * 
 */

// define the gre plugin
(function($) {
	if(typeof $.fn.gre === 'undefined') {
		// define default options
		var defaults = {
			media_url: 'gre/images/',
			content_css_url: 'gre/gre.css',
			max_height: 250
		};
		$.fn.gre = function(options) {
			$.fn.gre.html = function(iframe) {
				return iframe.contentWindow.document.getElementsByTagName('body')[0].innerHTML;
			};

			// build main options before element iteration
			var opts = $.extend(defaults, options);

			// iterate and construct the rich text editors
			return this.each(function(){
				var textarea = $(this);
				var iframe;
				var element_id = textarea.attr('id');

				// enable design mode
				function enableDesignMode() {
					var content = textarea.val();

					// Mozilla needs this to display caret
					if($.trim(content) == '')
						content = '<br>';

					// already created? show/hide
					if(iframe) {
						//console.log('already created'); // for debug purposes
						textarea.hide();
						$(iframe).contents().find('body').html(content);
						$(iframe).show();
						$('#toolbar-' + element_id).remove();
						textarea.before(toolbar());
						return true;
					}

					// for compatibility reasons, need to be created this way
					iframe = document.createElement('iframe');
					iframe.frameBorder 	= 0;
					iframe.frameMargin 	= 0;
					iframe.framePadding = 0;
					iframe.height 		= 100;

					if(textarea.attr('class'))
						iframe.className = textarea.attr('class');
					if(textarea.attr('id'))
						iframe.id = element_id;
					if(textarea.attr('name'))
						iframe.title = textarea.attr('name');

					textarea.after(iframe);

					var css = '';
					if(opts.content_css_url)
						css = "<link type='text/css' rel='stylesheet' href='" + opts.content_css_url + "' />";

					var doc = '<!DOCTYPE HTML><html><head>' + css + '</head><body class="frameBody">' + content + '</body></html>';
					tryEnableDesignMode(doc, function(){
						$('#toolbar-' + element_id).remove();
						textarea.before(toolbar());
						// hide textarea
						textarea.hide();
					});
				}

				function tryEnableDesignMode(doc, callback) {
					if(!iframe)
						return false;

					try {
						iframe.contentWindow.document.open();
						iframe.contentWindow.document.write(doc);
						iframe.contentWindow.document.close();
					} catch(error) {
						//console.log(error); // for debug purposes
					}
					if(document.contentEditable) {
						iframe.contentWindow.document.designMode = 'On';
						callback();
						return true;
					}
					else if(document.designMode != null) {
						try {
							iframe.contentWindow.document.designMode = 'on';
							callback();
							return true;
						} catch(error) {
							//console.log(error); // for debug purposes
						}
					}
					setTimeout(function(){ tryEnableDesignMode(doc, callback) }, 500);
					return false;
				}

				function disableDesignMode(submit) {
					var content = $(iframe).contents().find('body').html();

					if($(iframe).is(':visible'))
						textarea.val(content);

					if(submit !== true) {
						textarea.show();
						$(iframe).hide();
					}
				}

				// create toolbar and bind events to its elements
				function toolbar() {
					var tb = $("\
						<div class='gre-toolbar' id='toolbar-"+ element_id +"'>\
							<select>\
								<option value=''>Block style</option>\
								<option value='p'>Paragraph</option>\
								<option value='h3'>Title</option>\
								<option value='address'>Address</option>\
							</select>\
							<a href='#' class='bold'><img src='" + opts.media_url + "edit-bold.png' alt='bold' /></a>\
							<a href='#' class='italic'><img src='" + opts.media_url + "edit-italic.png' alt='italic' /></a>\
							<a href='#' class='unorderedlist'><img src='" + opts.media_url + "edit-list.png' alt='unordered list' /></a>\
							<a href='#' class='orderedlist'><img src='" + opts.media_url + "edit-list-order.png' alt='ordered list' /></a>\
							<a href='#' class='link'><img src='" + opts.media_url + "edit-link.png' alt='link' /></a>\
							<a href='#' class='image'><img src='" + opts.media_url + "edit-image.png' alt='image' /></a>\
							<a href='#' class='disable'><img src='" + opts.media_url + "edit-html.png' alt='close' /></a>\
						</div>\
					");

					$('select', tb).change(function(){
						var index = this.selectedIndex;
						if(index != 0) {
							var selected = this.options[index].value;
							formatText('formatblock', '<' + selected + '>');
						}
					});
					$('.bold', tb).click(function(){ formatText('bold');return false; });
					$('.italic', tb).click(function(){ formatText('italic');return false; });
					$('.unorderedlist', tb).click(function(){ formatText('insertunorderedlist');return false; });
					$('.orderedlist', tb).click(function(){ formatText('insertorderedlist');return false; });
					$('.link', tb).click(function(){
						var p = prompt('Insert URL address (starting with http://):');
						if(p)
							formatText('CreateLink', p);
						return false;
					});

					$('.image', tb).click(function(){
						var p = prompt('Insert image URL address (starting with http://):');
						if(p)
							formatText('InsertImage', p);
						return false;
					});

					$('.disable', tb).click(function(){
						disableDesignMode();
						var edm = $('<small><a class="gre-minilink" href="#">Back to visual mode</a></small>');
						tb.empty().append(edm);
						edm.click(function(e){
							e.preventDefault();
							enableDesignMode();
							$(this).remove();
						});
						return false;
					});

					$(iframe).parents('form').submit(function(){
						disableDesignMode(true);
					});

					var iframeDoc = $(iframe.contentWindow.document);

					var select = $('select', tb)[0];
					iframeDoc.mouseup(function(){
						setSelectedType(getSelectionElement(), select);
						return true;
					});

					iframeDoc.keyup(function(){
						setSelectedType(getSelectionElement(), select);
						var body = $('body', iframeDoc);
						if(body.scrollTop() > 0) {
							var iframe_height = parseInt(iframe.style['height']);
							if(isNaN(iframe_height))
								iframe_height = 0;
							var h = Math.min(opts.max_height, iframe_height + body.scrollTop()) + 'px';
							iframe.style['height'] = h;
						}
						return true;
					});

					return tb;
				};

				function formatText(command, option) {
					iframe.contentWindow.focus();
					try {
						iframe.contentWindow.document.execCommand(command, false, option);

						// convert nasty markup to light xhtml
						var markup = iframe.contentWindow.document.body.innerHTML;

						markup = markup.replace(/<span\s*(class="Apple-style-span")?\s*style="font-weight:\s*bold;">([^<]*)<\/span>/ig, '<strong>$2</strong>');
						markup = markup.replace(/<span\s*(class="Apple-style-span")?\s*style="font-style:\s*italic;">([^<]*)<\/span>/ig, '<em>$2</em>');

						iframe.contentWindow.document.body.innerHTML = markup;
					} catch(e) {
						//console.log(e); // for debug purposes
					}
					iframe.contentWindow.focus();
				};

				function setSelectedType(node, select) {
					while(node.parentNode) {
						var nName = node.nodeName.toLowerCase();
						for(var i=0;i<select.options.length;i++) {
							if(nName == select.options[i].value) {
								select.selectedIndex = i;
								return true;
							}
						}
						node = node.parentNode;
					}
					select.selectedIndex = 0;
					return true;
				};

				function getSelectionElement() {
					if(iframe.contentWindow.document.selection) {
						// IE selections
						selection = iframe.contentWindow.document.selection;
						range = selection.createRange();
						try {
							node = range.parentElement();
						} catch(e) {
							return false;
						}
					} else {
						// Mozilla selections
						try {
							selection = iframe.contentWindow.getSelection();
							range = selection.getRangeAt(0);
						} catch(e) {
							return false;
						}
						node = range.commonAncestorContainer;
					}
					return node;
				};

				enableDesignMode();
			}); //return this.each
		}; // gre
	} // if
})(jQuery);

