// Variables and functions that are (or might be) used in multiple other APIs

var urlStart = location.href.substr(0, location.href.lastIndexOf("/")) + "/";		// urlStart + "filename.html");
var urlStartBookID = location.href.substr(0, location.href.lastIndexOf("/")) + "/" + bookId + "/";		// urlStart + "filename.html");

var username = null;	// Will be set later in text.php; declare it here for safety


// *************************************************************
function ______SERVER_COMMUNICATION______ () {}

// we have to call the following function before sending info to the server.  
// Otherwise, when the php programs write Javascript code, the newlines and 
// single quotes muck things up.
function EncodeProblemCharacters(s) {
	if (s == null || s == "") {
		return "";
	}
	var ns = s.replace (/\\/g, "&#x5C;");
	ns = ns.replace (/\r\n/g, "<br>");
	ns = ns.replace (/\r/g, "<br>");
	ns = ns.replace (/\n/g, "<br>");
	ns = ns.replace (/'/g, "&#x27;");	//  '

	return ns;
}

// decode the problem charcters encoded above.  
// Only do this if a string has to be inserted into a form value; if the string 
// is being outputted to the screen, it will display better without decoding it.
function DecodeProblemCharacters(s) {
	if (s == null || s == "") {
		return "";
	}
	var ns = s.replace (/<br>/g, "\n");
	ns = ns.replace (/&#x27;/g, "'");
	ns = ns.replace (/&#x5C;/g, "\\");

	return ns;
}

// To send string data that might include special characters through Servercom(), 
// use the standard javascript escape() function.

// Set up a queue for servercom calls, so that we can submit stuff whenever we want
// and not have to worry about whether or not textfn has finished loading
var scQ = new Array();

// We set scRunning to true when we start textfn loading; then ServercomDone()
// resets it to false.  If scRunning is true, we know we have to add the call to the queue.
var scRunning = false;

function Servercom(data) {
	// if scRunning is false, there's nothing in the queue, so just call ServercomLoad
	if (scRunning == false) {
		ServercomLoad(data);
	
	// otherwise add the call to the queue; ServercomDone will execute it
	} else {
		scQ[scQ.length] = data;
	}
}

function ServercomLoad(data) {
	scRunning = true;
	servercomF.location.replace(GetFilename(urlStart + "text/textfn3.php?accountId=" + accountId + "&username=" + username + "&password=" + password + "&bookId=" + bookId + "&logoutFileName=" + logoutFileName + "&fn=" + data));
}

function ServercomDone() {
	// We just finished running one server query.

	// If there is something in the queue, take it out of the queue and submit it
	if (scQ.length > 0) {
		// Submit scQ[0]
		ServercomLoad(scQ[0]);
		
		// Then move everything else up
		for (var i = 1; i < scQ.length; ++i) {
			scQ[i-1] = scQ[i];
		}
		
		// And delete the last scQ
		scQ.length = scQ.length - 1;
		
		// If the queue is down to nothing, we'll set scRunning to true
		// when the just-made call to ServercomLoad returns.
		
		// alert("Queued servercom call executed (" + scQ.length + " remaining).");

	// Else there is nothing in the queue, so set scRunning to false
	} else {
		scRunning = false;
	}
}

// *************************************************************
function ______MULTI_BOOK_SUPPORT______ () {}
// One big associative array to store all the stuff
var altBookData = null;

// bookId is not in this; it gets set separately
var multiBookVars = new Array(
	// loaded in textfn3:
	'chaptersInStandardVersion', 'co', 'lastTrueSectionIndex', 'accountId', 'pagesRead', 'lastSection', 'suppInfo', 
	
	// sections.js:
	// PW 7/7/2009: added 'completedChapters', 'pages' for JumpToPageNumber links in the ebook
        'sections', 'completedChapters', 'pages',
	
	// notes: (notes themselves are in sections[])
	'noteSets', 'modifiableSets', 'firstModifiable', 'lastNoteSetUsed', 'stickyNoteHash', 
	
	// highlighting:
	'hlSpans', 
	
	// bookmarks: none (in sections[])
	
	// discussion questions (ebookQuestionsAPI.js):
	'dqs', 
	
	// ebookNavigation:
	'curSection', 'curDroppedChapter', 'curLeftHighlightedDiv', 'curLeftHighlightedPart', 'leftDropped', 
	
	// ebookPrefs:
	'prefStyles', 
	
	// ebookSuppWin
	'glossaryHistoryArr', 'lastDefinedTermId', 'indexHistoryArr', 'searchHistoryArr', 'searchType', 'lastSupp', 'SH', 
	
	// definitions and related stuff (not all books have all of these):
	'T_ID', 'L_ID', 'E_ID', 'C_ID', 
	
	// defaults.js:
	'bookTitle', 'edition', 'noteUploadSizeLimit', 'leftHighlightBgdColor', 'leftHighlightPartBorderColorNormal', 'leftHighlightPartBorderColorHighlighted', 'chapterStartSectionOffset', 'defaultFontSize', 'defaultFontFace', 'textFarRight', 'fixedTextWidth', 'eBookToolsBgcolor', 'chapterType', 'defaultPopInBgColor', 'dqpromptStart', 'definitionWidth', 'dqlinks1', 'dqlinks2', 'addCommentRefs', 'noGlossary', 'printOptionInEbookTools', 'commentStyle'
);

// Stash variables we have to duplicate for multiple books
function StashBookVars(bookIdToStash) {
	// Establish altBookData hash if necessary
	if (altBookData == null) {
		altBookData = new Object();
	}
	
	// Establish record for this book -- overwrite if it's already there
	altBookData[bookIdToStash] = new Object();
	
	// Stash all the vars
	for (var i = 0; i < multiBookVars.length; ++i) {
		var v = multiBookVars[i];
		
		// copy the variable from window[] to altBookData[bookIdToStash]
		altBookData[bookIdToStash][v] = window[v];
	}
}

// Clear the window's object and array vars, to prepare for a new set of them
function ClearBookVars() {
	for (var i = 0; i < multiBookVars.length; ++i) {
		var v = multiBookVars[i];
		if (window[v] != null && typeof(window[v]) == "object") {
			if (window[v][0] != null) {
				window[v] = new Array();
			} else {
				window[v] = new Object();
			}
		}
	}
}

// Retrieve variables for a book, 
// stashing vars for the old book first
function RetrieveBookVars(bookIdToRetrieve) {
	// if we don't have any alt books, 
	// or if the bookIdToRetrieve is the current bookId,
	// no need to retrieve, so just return
	if (altBookData == null || bookIdToRetrieve == bookId) {
		return false;
	}
	
	// If we don't have a record for this book, throw an error
	if (altBookData[bookIdToRetrieve] == null) {
		alert("No data found for book " + bookIdToRetrieve);
		return false;
	}
	
	// Stash the current book's current set of data first
	StashBookVars(bookId);
	
	// Now retrieve all the vars
	for (var i = 0; i < multiBookVars.length; ++i) {
		var v = multiBookVars[i];
		
		// copy the variable from altBookData[][] to window[]
		window[v] = altBookData[bookIdToRetrieve][v];
	}
	
	// Lastly set bookId itself
	bookId = bookIdToRetrieve;
}


// *************************************************************
function ______MISCELLANEOUS_FUNCTIONS______ () {}

function StoreCookie(name, val) {
	//alert(name + ":" + val);
	var later = new Date();
	later.setFullYear (later.getFullYear() + 10);
	document.cookie = name + "=" + val + "; path=/; expires=" + later.toGMTString();
}

function GetCookieVal(name) {
	var cook = document.cookie;					// get the cookie
	var pos = cook.indexOf (name + '=');	// look for the named field
	if (pos != -1) {		// if found
		var start = pos + name.length + 1;
		var end = cook.indexOf(";", start);
		if (end == -1) end = cook.length;
		//alert(name + ":" + cook.substring(start, end));
		return cook.substring(start, end);
	} else {
		//alert(name + ":null");
		return null;
	}
}

function ClearCookie(name) {
	var earlier = new Date();
	earlier.setFullYear(earlier.getFullYear() - 10);
	document.cookie = name + "=0; path=/; expires=" + earlier.toGMTString();	
}

function SetVisibility(l, v) {
	if (l != null) {
		if (v == null) {
			v = (l.style.visibility == "hidden") ? "visible" : "hidden";
		}
		l.style.visibility = v;
	}
	return v;
}

function SetDisplay(l, d) {
	if (l != null) {
		if (d == null) {
			d = (l.style.display == "block") ? "none" : "block";
		}
		l.style.display = d;
	}
	return d;
}

// Scroll to an element (adapted from http://www.quirksmode.org/js/findpos.html)
function ScrollToElement(win, obj, offset) {
	if (obj.offsetParent) {		// Should be true for any v5+ browser
		var top = 0;
		while (obj.offsetParent) {
			top += obj.offsetTop;
			obj = obj.offsetParent;
		}
		
		// And scroll to it
		win.scrollTo(0, top + offset);
	}
}

// get a filename; either the actual file, or an angel file that
// will write out that file.
function GetFilename(fn) {

	// KC 9/25/2009 Fix for CrunchIt!s

	// For testing, set angelStyle = 1
	// And make dummy value for angelUrlStart
	//angelStyle = 1;
	//angelUrlStart = "http://coursesstaging.bfwpub.com/BFW/si.asp";

	//alert("angelStyle = " + angelStyle);

	// eBooks in Portals
	if (angelStyle == 1) {
		// For everything but crunchits
		//angelStyle = 0;
		if (fn.indexOf("crunchit/") < 0) {
			return angelUrlStart + "?file=" + escape(fn)
		} else {
			// For CrunchIts we just want to go the file rather than use si.asp (defined in ebookAngelAPI.js)
			return fn;
		}
	// Standalone eBooks
	} else {
		return fn;
	}

}

// get the searchstring for a file loaded via GetFilename above.
function GetSearchString(win) {
	// if angelStyle, meaning that the file was loaded via angelUrlStart above,
	// the search string will be of the form:
	// ?file=http://ebooks.bfwpub.com/file.ext?params
	// and everything after "file" will be escaped.
	// So we have to unescape, then extract everything after the first question mark
	if (angelStyle == 1) {
		var s = unescape(win.location.search.substr(1));	// file=...
		var i = s.indexOf('?') + 1;		// position of first char after first ?
		return s.substr(i);					// the search string of the file being loaded

	// if not angelStyle, just return everything after ?
	} else {
		return win.location.search.substr(1);
	}
}
