// Bind events to jQuery functions.
$(window).bind('scroll', repositionElements);
$(window).bind('resize', getElementPositions);

// Initialize TinyMCE
tinyMCE.init({
	theme: "advanced",
	theme_advanced_buttons1: "bold,italic,link,|,bullist,numlist",
	theme_advanced_buttons2: "",
	theme_advanced_buttons3: "",
	theme_advanced_toolbar_location : "bottom",
	theme_advanced_toolbar_align : "left",
	cleanup_on_startup: true,
	valid_elements: "a[href|class],img[class|src|alt|title|width|height],hr[class],em,strong,ul,ol,li,p,div,blockquote,b,i"
});

// Initialize global variables to prevent IE JS errors.
var viewportheight = 0;
var viewportwidth = 0;
var headerheight = 0;
var viewerheight = 0;
var mynotesheight = 0;//TODO: is this used?
var mynoteswidth = 0;
var myesvtextwidth = 0;
var myMediaScrollWidth = 0;
var annotationToolHeight = 0;
var footerpos = 0;
var offset = 0;
var textHeight = 0;



//
// When the DOM is ready, make a few adjustments.
//
$(document).ready(function() {
	$("#outerwrap").addClass("js");
	initializeExpandables();
	getElementPositions();// Calls equalizeColumns through repositionElements()
	initializeEditables();
	initializeTooltips();
	initializeFloatingToolbar();
	initializeSearchBox();
	initializeExpandShrink();
	initializeVerseNotes();
});


// Queries the DOM on DomReady for viewport
// dimensions and element positions.
function getElementPositions() {
	viewportheight = $(window).height();
	viewportwidth = $(window).width();
	headerheight = $('#header').height();
	viewerheight = $('#viewer').height();
	mynotesheight = $('#mynotes-container .inner').height();// Is this used?
	mynoteswidth = $('#mynotes-container .inner').width();
	myesvtextwidth = $('#esvtext-container').width() -4;// left border (2) + right border (2)
	myMediaScrollWidth = myesvtextwidth-16;// Make space for right button (16px)
	annotationToolHeight = $("#annotationtools").height();
	footerpos = $('#footer').position();
	repositionElements();// Handles scrolling positions
}


// Repositions the Toolbar at the bottom of the viewport
// or resting atop the footer on scroll or resize.
function repositionElements() {
	equalizeColumns();
	offset = $(window).scrollTop();
	viewportbottom = viewportheight + offset;
	
	/* Adjust media-scroll width */
	$('#media-scroll').css('width', myMediaScrollWidth);
	
/* Toolbar won't display below footer: */
	// footer is in viewport (screen) 
	if(viewportbottom > footerpos['top']) {
		// Change class to absolute
		if( !$('#annotationtools').hasClass('position-absolute'))
			$('#annotationtools').removeClass('position-fixed').addClass('position-absolute');
		$("#annotationtools").css("top", footerpos['top'] - annotationToolHeight);
	} 
	else { // footer is out of viewport (screen)
		if( !$('#annotationtools').hasClass('position-fixed') ) 
			$('#annotationtools')
										.addClass('position-fixed')
										.removeClass('position-absolute')
										.css("top", '');
	}
	$("#footer").css("top", footerpos['top']);	// Force re-draw of footer after repositioning to fix Safari 3 bug.
}

// Initialize Cross-Reference Tooltips
function initializeTooltips() {

	// First the cross-references...

	$(".cf").tooltip({
		track: false, 
		delay: 120, 
		showURL: false, 
		opacity: 0.9, 
		extraClass: "esvtexttooltip", 
		top: 10, 
		left: -30
	});

	// Then the ESV Notes.

	$("a.bible,a.note,a.note-id,span.footnote a").tooltip({
		track: false, 
		delay: 120, 
		showURL: false, 
		opacity: 0.9, 
	    extraClass: "notestooltip",
		top: 10, 
		left: -100
	});
}

// Initialize editable notes
function initializeEditables() {
	$("div.note-content").dblclick(function() {
		$(this)
				.after('<input type="button" id="cancelNote" value="Cancel" onclick="javascript:cancelNote(this);" />')
				.after('<input type="button" id="saveNote" value="Save" onclick="javascript:editableBlur();"/>');
		$("#addNote").hide();
		var contentText = $(this).html();
		$.data($(this).parent()[0], 'tmpData', contentText);
		tinyMCE.execCommand("mceAddControl", true, $(this).attr("id"));
		setTimeout(function() { $(document).one("click", editableBlur) }, 10);
	});
};

function editableBlur() {
	var edit = $("span.mceEditor:first");
	if (edit.length == 1){
		var container = edit.parent();
		var contentID = edit.prev().attr('id');
		hideEditor(contentID);
		// Save on Server
		saveNote(container, 'active');// Main div containing notes
	}
}

function hideEditor(contentID){
	tinyMCE.execCommand("mceRemoveControl", true, contentID);
	$("#saveNote, #cancelNote").remove();
	$("#addNote").show();
}


function deleteNote(deleteButton){
	var container = $(deleteButton).parents("div[id^=note_]");
	if (!confirm("Are you sure you want to delete this note?")) return;
	container.hide();
	// TODO add undo funtion here
	saveNote(container, 'delete');
}

function cancelNote(cancelButton){
	var container = $(cancelButton).parents("div.note-container");
	var contentTextOld = $.data(container[0], 'tmpData');
	var contentID = $("span.mceEditor:first").prev().attr('id');
	hideEditor(contentID);// Hide old content
	container.find('.note-content').html(contentTextOld);
}

function saveNote(noteContainer, method){
	var saveObj = {};
	var classID = noteContainer.attr('id');// div's id is the same as class for all notes
	var $notes = $('.' + classID); 
	//var titleText = $notes.filter('.notes-title').text();
	var contentText = $notes.filter('.note-content').html();
	var contentTextOld = $.data(noteContainer[0], 'tmpData');
	
	// If data is the same, don't save
	if(contentText == contentTextOld) return false;
	// Hide if blank and don't save
	if (contentText == ''){
		noteContainer.hide();
		return false;
	} 

	contentText = $.quoteString(contentText);
	contentText = contentText.substring(1, contentText.length-1);// remove start and end quotes
	contentText = encodeURIComponent(contentText);
			
	var start_id = $.data(noteContainer[0], 'start_id');
	var end_id = $.data(noteContainer[0], 'end_id');
	
	saveObj.id = classID;
	saveObj.start_id = start_id;
	saveObj.end_id = end_id;
	saveObj.content_type = 'text/html';
	//saveObj.content_title = titleText;
	saveObj.content_text = contentText;
	saveObj.share_status = '';
	saveObj._method = method;
		
	// Save on Server
	saveUser('annotations', 'notes', saveObj);
}

/* For notes, the JSON should contain: (annotations_verse)
	 *  *id or custom_id
	 *  *start_id
	 *  *end_id
	 *  *content_type (text/html)
	 *  *content
	 *  *share_status (optional)
	 *  *_method (optional; should be set to "DELETE" when deleting a highlight [which sets the status to 'deleted'])
	 *
	 * Be sure to sanitize the HTML input (removing unnecessary or potentially harmful tags and attributes) before saving it.
	 *   *a[href|class],img[class|src|alt|title|width|height],hr[class],em,strong,ul,ol,li,p,div,blockquote,b,i
	 */

function initializeFloatingToolbar(){
	
	$().bind("mouseup", function(e){
		var selRange = $('.esv-text').getRangeAt();// Only selection in esv-text
		
		if (selRange === false) {
			$('.floatingToolbar').floatingToolbar(e, {closeToolbar: true});
		}
		else{
			$('.floatingToolbar').floatingToolbar(e, {range: selRange});
		}
	});
	
	// Stop mouseup on toolbar for clicks to work.
	$('.floatingToolbar').bind("mouseup", function(e){
		e.stopPropagation();// jquery method
	});
}

// Handles highlighting
function highlightRange(myClass, myOptions){
	var myRange = myOptions.range;
	var b_save = true;// Save
	var saveObj = {};// Default object
	
	if(typeof myOptions.highlightObj != 'undefined'){// Toolbar, removes old highlight and changes to new highlight
		var highlightObj = $(myOptions.highlightObj);
		var highlightClass = myOptions.highlightClass;
		
		// Remove Class from span selection
		highlightObj.removeClass(highlightClass);	
	}
	else{
		var highlightObj = $().wrapSelection({wrapRange : myRange});
		var highlightClass = '';
	}
	var tmpId = highlightObj.attr('class');

	var offset = highlightObj.wordOffset();// Run Offset program, send selectClass to help identify it.
	saveObj.start_id = offset.firstId + '.' + offset.firstOffset;
	saveObj.end_id = offset.lastId + '.' + offset.lastOffset;
	saveObj.id = tmpId;
	saveObj.hlClass = myClass;
	saveObj.share_status = '';
	saveObj._method = '';

	var params = {lastClass: highlightClass, myClass: myClass, saveObj: saveObj};// Create undoRedo param for class
	highlightObj
		.addClass(myClass)// Highlight
		.undoRedo($.fn.unHighlight, $.fn.reHighlight, params);// Add to undo queue

	// save highlight to client
	myOptions.highlightObj = highlightObj;
	myOptions.highlightClass = myClass;

	// Deleting Highlight: Outer Wrap Highlight 
	if (myClass == 'h6') {
		//delete, where "|" represents new highlight
		//Handle highlight classes h1..h5 
		//	"text |here <span class='.h6'>deleted here</span> Rest| here"
		var search = $('.' + tmpId).find('.h1, .h2, .h3, .h4, .h5, .h6');
		if (search.length > 0) deleteHighlight(search);

		// Deleting Outer parent: Exact highlight, the new selection is inside the tag	
		// If a highlight is exactly selected, highlight but don't save h6.
		//	Doesn't handle an extra text node on either side.	
		outerParent = $('.' + tmpId).parent('.h1, .h2, .h3, .h4, .h5, .h6');
		if(outerParent.children().length == 1 && 
			outerParent.text().length == $('.' + tmpId).text().length){

			deleteHighlight(outerParent);
//			console.log('Deleting Outer Parent...', outerParent.parent());
			var highObjectParent= getHighlightObj( outerParent.parent() )
			outerParent
				.children()// Object being deleted
					.removeClass('h6')// Remove the h6 class
				.andSelf()// Wraper highlight that was deleted
					.addClass(highObjectParent.myClass)// Match old code
			b_save = false;// Don't save the h6 class
		}
	}
	// Save on Server
	if(b_save) saveUser('annotations', 'highlights', saveObj);
}

/*
 * Takes jquery object and deletes them
 */
function deleteHighlight(search){
//	console.log('Search (' + search.length + ')', search);
	search.each(function(){
		var saveObj = {};
		var offset = {};

		var highObject = getHighlightObj(this);
		var id = highObject.id;
		var myClass = highObject.myClass;

		saveObj = {};
//		console.log('Deleting Highlight: ', id, myClass,  $(this)[0])
		$(this).removeClass(myClass);

		offset = $(this).wordOffset();// Run Offset program, send selectClass to help identify it.
		saveObj.start_id = offset.firstId + '.' + offset.firstOffset;
		saveObj.end_id = offset.lastId + '.' + offset.lastOffset;
		saveObj.id = id;
		saveObj.hlClass = myClass;
		saveObj.share_status = '';
		saveObj._method = 'delete';
		saveUser('annotations', 'highlights', saveObj);
	});// end each
}

function getHighlightObj(node){
//	console.log('Getting highlight Object', node);
	var regexp = new RegExp("h\d","gi")
	var allClasses = $(node).attr('class');
	if(allClasses != ''){
		var a_id = allClasses.split(' ',1);
		var id = a_id[0]
	}
	var matching = allClasses.match(/h\d/);// ex: returns array with h1, h2, etc
	myClass = (matching) ? matching[0] : '';
	return {id: id, myClass : myClass};
}

/*
 * Generic Save function
 */
function saveUser(type, method, obj){
	// checks and sets auth.user
	if(auth.user == '0') getAuth();
	
	// Catch auth.user if undefined
	if(auth.user == -1){
		setTimeout(function(){saveUser(type, method, obj);}, 500);// check in .5 seconds
		return false;
	}

	var url = '/api/users/' + auth.user;
	if(type == 'annotations' && method == 'highlights')
		url += '/annotations/highlights';
	else if(type == 'annotations' && method == 'notes')
		url += '/annotations/notes';

	var json = 'json=' + $.compactJSON(obj); 
	var data = $.ajaxQueue({
		  type: "POST",
		  url: url,
		  data: json,
		  dataType: 'json',
		  cache: false,
		  success: function(result){
			$('.' + result.custom_id)
				.addClass(result.id);
		  }
		});
}

function getAuth(){
//	console.log('No Auth.user');
	auth.user = -1;// default
	var url = '/api/users';
	$.ajax({
		type: 'POST',
		url: url,
		success: function(result){
			auth.user = result;
		}
	});
}	

/*
 * Queued Ajax requests.
 * A new Ajax request won't be started until the previous queued 
 * request has finished.
 * 
 * Modified from the ajaxQueue plugin: http://plugins.jquery.com/project/ajaxqueue
 */
jQuery.ajaxQueue = function(o){
	var _old = o.complete;
	o.complete = function(){
		if ( _old ) _old.apply( this, arguments );
			jQuery([ jQuery.ajaxQueue ]).dequeue( "ajax" );// modified using comments: http://plugins.jquery.com/node/1440
	};

	jQuery([ jQuery.ajaxQueue ]).queue("ajax", function(){
		jQuery.ajax( o );
	});
};

// My Notes Toolbar
function initializeNotesToolbar(){
	$("[id^='highlighter-class']").each(function(){
		$(this).bind("click", toggleToolbarOn);
		});
}

function toggleToolbarOn(){
//	var selector = this.data('selector');
	var highlightClass = toolbarClass(this)
	toolbarData('state', highlightClass);
	
//	console.log('Turn On: class=', highlightClass);
}

// Notes Toolbar: un-Activates highlight class in state variable
function toggleToolbarOff(){
	toolbarData('state', '');// Turn off status
}

// expect jquery object.
function toolbarClass(obj){
	var id = $(obj).attr('id');
	var a_id = id.split('-');// highlighter-class-h1
	return a_id[2];// highlightClass
}

// toolbar data:  mirror to data, but specific to My Notes Toolbar
function toolbarData(name, value){
//	if(typeof(name) != 'undefined') return false;// exit
	
	// Get data
	if (typeof(value) != 'undefined') {
		$('#annotationtools').data(name, value);
	}
	else {
		return $('#annotationtools').data(name);
	}
}

// Equalize column height.
function equalizeColumns() {
	var studyNotesHeight = $('#esvnotes-container > .inner').height();
	var notesHeight = $('#mynotes-container > .inner').height();
	var headerHeight = $('#header').height();
	var textHeight = $("#esvtext-content > .inner").height();
//	// Use the tallest Height
	var viewerheight = (studyNotesHeight >= notesHeight) ? studyNotesHeight : notesHeight;
	if (textHeight > viewerheight) viewerheight = textHeight + 50;
//	//Change footer size
	footerpos['top'] = viewerheight + headerHeight + 25;// 25 is an adjustment, not sure why.  Borders and such?
	
	$("#esvtext-container").css("height", viewerheight);
	
	$("#esvtext-content").css("height", viewerheight - $('.passagetitle').outerHeight({ margin: true }));
	$("#esvnotes-container").css("height", viewerheight);
	$("#mynotes-container").css("height", viewerheight);
//	console.log('EqualizeColumns:', viewerheight);
}

//Initialize partial notes
function initializeExpandables() {
	//don't truncate if the notes are shorter than the text
	if ($("#esvtext-content > .inner").height() >= $('#esvnotes-container > .inner').height() - 100) return;
	$.data("is_truncated", true);
	$("#esvnotes-container div.inner div").truncate({
		maxLength: 400
		});
}

function initializeSearchBox() {
	$("#q").click(function() {
		var $this = $(this);
		if ($this.val() == 'Search by Verse or Topic') $this.val("");
	});
}

function initializeExpandShrink() {
	if (!$.data("is_truncated")) return;
	$("#esvnotes-buttons").css("display", "block");
	$("#expand-all").click(function(e) {
		e.preventDefault();
		$("a.show-more").click();
	});
	$("#shrink-all").click(function(e) {
		e.preventDefault();
		$("a.show-less").click();
	});
}

function initializeVerseNotes(){
	$('#mynotes-container').verseNote();
}