var codeEditor = function() {

	var fonts = ['arial', 'tahoma', 'verdana'];
	var sizes = [1, 2, 3 ,4 ,5];
	var colors = ['Standard', 'Black', 'Darkgrey' , 'Redone', 'Redthree', 'Pinkthree', 'Orangethree', 'Yellowone', 'Purplethree', 'Greentwo', 'Greenthree', 'Bluetwo', 'Tvnzblue', 'Browntwo', 'Tvnzbluesteel', 'Tvnzbluesteelgrey'];
	var colorIndex = 0; // index of above array, blue
	var charLimit = 1000;
	var init = function(id) {
		$(document).ready(function() {
			if(!Array.indexOf){ // This is for IE, as IE cannot do an indexOf on an Array, this creates the prototype, so it can be done
				Array.prototype.indexOf = function(obj){
					for(var i=0; i<this.length; i++){
						if(this[i]==obj){
							return i;
						}
					}
					return -1;
				}
			}
			addToolbar(id); // adds the tool bar, and binds all clicks etc
		});
	}

	// Limit the given id's text size to charLimit chars and update the remaining character count limit
	// bbcode tags are ignored in the char count.
	var applyCharLimit = function(id) {
		var s = $("#"+id).val();
		var size = getCharCount(s);
		var rv = size < charLimit;
		if ( size > charLimit ) {
			var hi = s.length;
			var lo = 0;
			var p; // use binary search to get min no of chars we need to lop off to get it to fit (allows for contained bbcode tags)
			do {
				p = Math.round((hi+lo)/2);
				size = getCharCount(s.substr(0,p));
				if ( size > charLimit )
					hi = p;
				else if ( size < charLimit )
					lo = p;
				else
					break;
			}
			while (lo != hi);
			$("#"+id).val(s.substr(0,p));
		}
		$(".charCount").html("Characters Left: " + (1000 - size));
		return rv; // returns true if there's room for more chars
	}
	var addToolbar = function(id) {
		// creates and appends the tool bar and buttons
		$("#"+id).parent().createPrepend('div', {className:'toolbar'}, [
			'select', {id: 'font', name: 'font', className: 'dropDown'}, [
				'option', {value: ''}, 'Fonts'
			],
			'select', {id: 'fontSize', name: 'fontSize', className: 'dropDown'}, [
				'option', {value: ''}, 'Size'
			],
			'a', {title: 'Colors'}, [
				'img', {id: 'btnColor', className: 'button noRight bg' + codeEditor().colors[colorIndex], src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnColor.gif'}, ''
			],
			'a', {title: 'Colors'}, [
				'img', {id: 'btnColorPicker', className: 'button noLeft', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnSelector.gif'}, ''
			],
			'a', {title: 'Bold'}, [
				'img', {id: 'btnBold', className: 'button', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnBold.gif'}, ''
			],
			'a', {title: 'Italic'}, [
				'img', {id: 'btnItalic', className: 'button', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnItalic.gif'}, ''
			],
			'a', {title: 'Underline'}, [
				'img', {id: 'btnUnderline', className: 'button', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnUnderline.gif'}, ''
			],
			'a', {title: 'Quote'}, [
				'img', {id: 'btnQuote', className: 'button', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnQuote.gif'}, ''
			],
			'a', {title: 'Reset text formatting'}, [
				'img', {id: 'btnRemove', className: 'button', src: 'http://images.tvnz.co.nz/tvnz_site_images/entertainment/images/btnRemove.gif'}, ''
			],
			'div', {id: 'colorPicker', className:'colorPicker'}, ''
		]);

		// populates the fonts, sizes, and colors
		// font (note doesn't use flydom as 3.1.1 mangles value attribute name)
		for (var i = 0; i < codeEditor().fonts.length; i++) {
			$("#"+id).parent().find(".toolbar #font").append('<option value='+codeEditor().fonts[i]+'>'+capitalize(codeEditor().fonts[i])+'</option>');
		}
		// size
		for (var i = 0; i < codeEditor().sizes.length; i++) {
			$("#"+id).parent().find(".toolbar #fontSize").append('<option value='+codeEditor().sizes[i]+'>'+codeEditor().sizes[i]+'</option>');
		}
		// color
		for (var i = 0; i < codeEditor().colors.length; i++) {
			$("#"+id).parent().find(".toolbar #colorPicker").createAppend('a', {href: '#', className: "bg" + codeEditor().colors[i]}, '');
		}


		// binds the click/change events to the buttons
			// font
		$("#"+id).parent().find(".toolbar #font").change(function() {
			if (this.selectedIndex != 0) {
				addTag("font", this.value, id);
				this.selectedIndex=0;
			}
		});
			// size
		$("#"+id).parent().find(".toolbar #fontSize").change(function() {
			if (this.selectedIndex != 0) {
				addTag("size", this.value, id);
				this.selectedIndex=0;
			}
		});
			// color btn
		$("#"+id).parent().find(".toolbar #btnColor").click(function() {
			addTag('color', codeEditor().colors[colorIndex], id);
		});
			// color picker btn
		$("#"+id).parent().find(".toolbar #btnColorPicker").click(function() {
			showColorPicker(id);
		});
			// buttons in color picker
		$("#"+id).parent().find("#colorPicker a").each(function() {
			$(this).click(function() {
				// substr the class to remove the "bg" off the class
				setColor($(this).attr("class").substr(2), id);
				return false;
			});
		});
			// bold
		$("#"+id).parent().find(".toolbar #btnBold").click(function() {
			addTag("b", null, id);
		});
			// italics
		$("#"+id).parent().find(".toolbar #btnItalic").click(function() {
			addTag("i", null, id);
		});
			// underline
		$("#"+id).parent().find(".toolbar #btnUnderline").click(function() {
			addTag("u", null, id);
		});
			// quote
		$("#"+id).parent().find(".toolbar #btnQuote").click(function() {
			addTag("quote", null, id);
		});
			// remove
		$("#"+id).parent().find(".toolbar #btnRemove").click(function() {
			var $textBox = document.getElementById(id);
			var selectedText;
			if ($.browser.msie) {
				$textBox.focus();
				selectedText = document.selection.createRange();
				if (selectedText.text.length > 0) {
					$textBox.value = $textBox.value.replace(selectedText.text, stripBBCode(selectedText.text));
				}
			} else {
				var len = $textBox.value.length;
				var start = $textBox.selectionStart;
				var end = $textBox.selectionEnd;
				selectedText = $textBox.value.substring(start, end);
				if (selectedText.length > 0) {
					$textBox.value = $textBox.value.replace(selectedText, stripBBCode(selectedText));
				}
			}
		});

		$("#messageEditor").checkSubmit();

		$(".editor #btnPreview").click(function() {
			$(".preview").animate({height: 'show'}, 250, "linear");
			$.post("/content/community/preview", {post_text: $("#"+id).val()}, function(response) {
				$(".editor .messagePreview").html(response);
			}, "html");
		});

		$(".editor #btnCancel").click(function() {
			history.back();
		});

		// binds a keyup event on the textbox to show the char count
		$("#"+id).keyup(function() {
			applyCharLimit(id);
		});
		$("#"+id).keydown(function(e) {
			return applyCharLimit(id) ||
				   (e.keyCode < 48 && e.keyCode != 32 /*space*/ ) ; // probably a non-printing key so allow it even if limit reached
		});
		$("#"+id).change(function(e) {
			applyCharLimit(id); // catches paste etc
		});

		// shows the current char count on page load
		applyCharLimit(id);
	}

	var stripBBCode = function(bbcode) {
		var A = new RegExp("\\[(\\w+)(=[^\\]]*)?\\]","gi");
		var I = new RegExp("\\[\\/(\\w+)\\]","gi");
		return bbcode.replace(A, "").replace(I, "");
		//var regEx = /\[(\/?)(b|u|i|quote(=?.+?)?|color(=?.+?)?|size(=?.+?)?|font(=?.+?)?)\]/ig;
		//return bbcode.replace(regEx, "");
	}

	var getCharCount = function(bbcode) {
		var A = new RegExp("\\[(\\w+)(=[^\\]]*)?\\]","gi");
		var I = new RegExp("\\[\\/(\\w+)\\]","gi");
		return bbcode.replace(A, "").replace(I, "").length;
	}

	var parseToHTML = function(bbcode) {

		// this function changes all open tags to the correct html open tag, changes ANY closing tag to a </span>

		var regExFrom = [
			new RegExp("\\[b\]", "gi"),
			new RegExp("\\[u\]", "gi"),
			new RegExp("\\[i\]", "gi"),
			new RegExp("\\[quote=(.*?)\]", "gi"),
			new RegExp("\\[quote\]", "gi"),
			new RegExp("\\[color=(.*?)\]", "gi"),
			new RegExp("\\[size=(.*?)\]", "gi"),
			new RegExp("\\[font=(.*?)\]", "gi"),
			new RegExp("\\[\\/(\\w+)\\]","gi")
		]

		var regExTo = [
			'<span class="bold">',
			'<span class="underline">',
			'<span class="italic">',
			'<span class="quote"><span>$1</span>',
			'<span class="quote">',
			'<span class="$1">',
			'<span class="size$1">',
			'<span class="$1">',
			'</span>'
		]

		for (var i = 0; i < regExFrom.length; i++) {
			bbcode = bbcode.replace(regExFrom[i], regExTo[i]);
		}

		return bbcode;
	}

	var addTag = function(tag, value, id) {
		if (value != null) {
			var openTag = "[" + tag + "=" + value + "]";
			var closeTag = "[/" + tag + "]";
		} else {
			var openTag = "[" + tag + "]";
			var closeTag = "[/" + tag + "]";
		}

		var $textBox = document.getElementById(id);
		var alreadyTagged  = new RegExp(("^"+openTag+".*"+closeTag+"$").replace(/([\[\]])/g,'\\$1'));
		if ($.browser.msie) {
			$textBox.focus();
			var sel = document.selection.createRange();
			if ( sel.text.length == 0 || // no selection (will just insert tagopenclose)
				(sel.text.length > 0 && !sel.text.match(alreadyTagged))) { // ignore if selection already surrounded by same open/close tag
				sel.text = openTag + sel.text + closeTag;
			}
		} else {
			var len = $textBox.value.length;
			var start = $textBox.selectionStart;
			var end = $textBox.selectionEnd;

			var sel = $textBox.value.substring(start, end);
			if ( sel.length == 0 || // no selection (will just insert tagopenclose)
					(sel.length > 0 && !sel.match(alreadyTagged))) { // ignore if selection already surrounded by same open/close tag
				var scrollTop = $textBox.scrollTop;
				var scrollLeft = $textBox.scrollLeft;

				var rep = openTag + sel + closeTag;
				$textBox.value =  $textBox.value.substring(0,start) + rep + $textBox.value.substring(end,len);

				$textBox.scrollTop = scrollTop;
				$textBox.scrollLeft = scrollLeft;
			}
		}
	}

	var showColorPicker = function(id) {
		if ($("#"+id).parent().find("#colorPicker").is(":visible")) {
			$("#"+id).parent().find("#colorPicker").animate({height: 'hide'}, 250, "linear");
		} else {
			$("#"+id).parent().find("#colorPicker").animate({height: 'show'}, 250, "linear");
		}
	}

	var setColor = function(color, id) {
		colorIndex = codeEditor().colors.indexOf(color); // changes color index
		addTag('color', codeEditor().colors[colorIndex], id); // adds the tag to the textbox
		$("#"+id).parent().find("#colorPicker").animate({height: 'hide'}, 250, "linear"); // hides the color Picker
		$("#"+id).parent().find("#btnColor").attr("class", "button noRight bg" + codeEditor().colors[colorIndex]); // changes the class on the button
	}

	var capitalize = function(str) {
		var wordArray = str.split(" ");
		for (var i = 0; i < wordArray.length; i++) {
			var tempChar = wordArray[i].substring(0, 1);
			var tempRest = wordArray[i].substring(1, wordArray[i].length);
			wordArray[i] = tempChar.toUpperCase() + tempRest;
		}
		return wordArray.join(" ");
	}

	return {
		init : init,
		fonts : fonts,
		sizes : sizes,
		colors : colors,
		colorIndex : colorIndex,
		parseToHTML : parseToHTML
	}
}

$.fn.checkSubmit = function() {
	/* Change a form's submission type to ajax */
	$(this).submit(function(){
		if ($(".editorTitle").length>0) {
			if ($(".editorTitle").val().length>0) {
				$(".editor #btnPost").each(function() {
					$(this).addClass("disabled");
					$(this).attr('disabled', 'disabled');
				});
				return true;
			} else {
				alert("Please insert a title.");
				return false;
			}
		} else {
			return true;
		}
	});
	return this;
}


