(function($) {
	// Document load function
	$(function() {
		// Deal with nested sup tags from MS Word HTML
		$('.word-html sup sup').each(function() {
			var temp = $(this).html();
			$(this.parentNode).html(temp);
		});
		// Deal with nested MsoFootnoteReference tags from MS Word HTML
		$('.word-html .MsoFootnoteReference .MsoFootnoteReference').each(function() {
			var temp = $(this).html();
			$(this.parentNode).html(temp);
		});
		
		// Transform paragraph into li
		function transformBullet(element) {
			$(element).children().eq(0).remove();
			$('<li></li>').insertBefore(element).append($(element).contents()).addClass($(element).attr('class'));
			$(element).remove();
		}
		
		// Deal with bullet lists from MS word documents. Note that list items
		// seem to be converted to HTML as paragraphs with the following
		// classes:
		// 
		//     MsoListParagraphCxSpFirst
		//     MsoListParagraphCxSpMiddle
		//     MsoListParagraphCxSpLast
		// 
		// Also note that MsoListParagraphCxSpFirst is only used for the
		// first paragraph of the entire list (including subordinate lists).
		// 
		// Unordered lists seem to have a span as the first element of the
		// first paragraph, ordered lists seem to have a text node as the
		// first element of the first paragraph. Although there is no way to
		// absolutely guarantee this.
		// 
		// The lists seem to use an odd combination of margins and non-breaking
		// spaces to position the paragraph elements.
		// 
		// Note it is highly probably that this logic will not work in all
		// circumstances.
		$('.MsoListParagraphCxSpFirst').each(function() {
			// Try to determine if this is an ordered list or unordered list
			if($(this).contents().get(0).nodeType == 3) {
				$('<ol class="MsoList" />').insertBefore(this);
			} else {
				$('<ul class="MsoList" />').insertBefore(this);
			}
		});
		
		// Wrap each list paragraph
		$('.MsoListParagraphCxSpFirst, .MsoListParagraphCxSpMiddle, .MsoListParagraphCxSpLast').wrap('<li class="MsoListItem" />');
		
		// Move list items into appropriate lists
		$('li.MsoListItem').each(function() {
			$(this).prev('ul.MsoList, ol.MsoList').append(this);
		});
		
		function parseMeasurement(value) {
			return new Number(value.match(/^\d+/));
		}
		
		function cleanUnorderedListItem(item) {
			// First item should be the only formatting node.
			$(item).contents().eq(0).remove();
		}
		
		function cleanOrderedListItem(item) {
			// The formatting nodes at the beginning of the list item should
			// either be formatting nodes (contain non-breaking spaces) or
			// should be the text node containing the item number. The item
			// number should be followed by a formatting node.
			var numberNode = null;
			$(item).contents().each(function() {
				if(this.nodeType === 3) {
					if(numberNode === null) {
						// First text node found
						numberNode = this;
					} else {
						// Unexpected formatting, quit
						return false;
					}
				} else {
					var nodeText = $(this).text();
					if(nodeText.length > 0 && nodeText.trim().length == 0) {
						if(numberNode !== null) {
							// Formatting node immediately proceeding the
							// text node containing the list item number.
							// Remove all preceeding content and quit.
							$(this).prevAll().add(this).remove();
							$(numberNode).remove();
							return false;
						}
					} else {
						// Unexpected formatting, quit
						return false;
					}
				}
			});
		}
		
		function cleanListItem(item) {
			var $para = $(item).children('p');
			
			// Eliminate the paragraph container (jQuery's unwrap had some
			// issues hence the explicit move).
			$para.contents().appendTo(item);
			$para.remove();
			
			
			// Attempt to clean the numbering and indents from an ordered
			// list.
			if($(item).parents('ol').length) {
				cleanOrderedListItem(item);
			} else {
				cleanUnorderedListItem(item);
			}
		}
		
		function cleanList(outerList, innerListWrapper) {
			var indents = new Array();
			var parents = new Array();
			var currentIndent = null;
			var currentParent = outerList;
			var prevLi = null;
			$(outerList).children().each(function () {
				var indent = parseMeasurement($(this).children('p').css('margin-left'));
				cleanListItem(this);
				
				//alert(indent);
				if(currentIndent === null) currentIndent = indent;
				
				// Update indent as appropriate
				if(indent < currentIndent) {
					while(indent < currentIndent) {
						//alert('Decrease Indent');
						var newIndent = indents.pop();
						var newParent = indents.pop();
						if(newIndent === false || newParent === false) {
							break;
						}
						currentIndent = newIndent;
						currentParent = newParent;
					}
				} else if(indent > currentIndent) {
					if(prevLi) {
						//alert('Increase Indent');
						indents.push(currentIndent);
						parents.push(currentParent);
						
						currentParent = $(innerListWrapper).appendTo(prevLi).get(0);
					}
				}
				
				if(currentParent !== outerList) {
					$(currentParent).append(this);
				}
				
				currentIndent = indent;
				prevLi = this;
			});
		}
		
		// Try to deal with nested lists, and clean up MS Word formatting
		$('ul.MsoList').each(function() {
			cleanList(this, '<ul />');
		});
		$('ol.MsoList').each(function() {
			cleanList(this, '<ol />');
		});
	});
})(jQuery);
