// JavaScript Document for Homework 8, INP271, Mike Behnke

var setOpt = {
	
	//set variables that will be used in multiple functions
	content : null, lineSpacing : null, highlightKw : null,	highlightText : null,
	hideQuotation : null, allKws : null, expireDate : new Date(),
	
	//set functions
	init : function() {
		// Object detection
		if (!document.createElement) {return;}
		
		// Acquire content block for use throughout document
		setOpt.content = jslib.getObj('content');

		// Build the Customize Article Display block
		setOpt.buildCADblock();

	// set any cookies created to expire in 30 days
		var thirtyDays = setOpt.expireDate.getTime() + (30 * 24 * 60 * 60 * 1000);
		setOpt.expireDate.setTime(thirtyDays);

		// Assign event handlers and functions called
		jslib.addEvent(setOpt.lineSpacing,'click',setOpt.adjustLineSpacing);
		jslib.addEvent(setOpt.highlightKw,'click',setOpt.highlightKeywords);
		jslib.addEvent(setOpt.highlightText,'click',setOpt.highlightTextHover);
		jslib.addEvent(setOpt.hideQuotation,'click',setOpt.hideTheQuotation);

    // Call functions once to check cookie states and set accordingly
		setOpt.adjustLineSpacing();
		setOpt.highlightKeywords();
		setOpt.highlightTextHover();
		setOpt.hideTheQuotation();
		
		// Get Keywords with no duplicates and output
		setOpt.outputKWs();
		
		// Build Print URLs and insert superscript tags after links in content
		setOpt.outputPurls();
		
		// Build the search and recent articles div areas
		setOpt.buildSR();

		// Request search XML data
		jslib.sendRequest('xml/all_articles.xml?' + Math.random(), setOpt.storeSearchArts);

		// Set timer for search box and query box
		jslib.addEvent(setOpt.searchInput, 'keyup', setOpt.setTimer);
		jslib.addEvent(setOpt.searchSelect, 'change', setOpt.setTimer);

		// Get list of recent Articles, build and display
		setOpt.getNewArts();

		// request recent Articles data every minute
		var artRefresh = setInterval(setOpt.getNewArts, 60000);
	},
	
	buildCADblock : function () {
		// Create Customize Article Display block
		var holderDiv = document.createElement('div');
		holderDiv.id = 'cadBox';
		var theH3 = document.createElement('h3');
		var theForm = document.createElement('form');
		theForm.id = 'custartdisp';
		var theButton = [], theP = [];
		for (var i=0; i<4; i++) {
			theP[i] = document.createElement('p');
			theButton[i] = document.createElement('input');
			theButton[i].type = 'button';
   switch (i) {
				case 0: theButton[i].value = '';
								theButton[i].id = 'linespace';
								setOpt.lineSpacing = theButton[i]; break;
				case 1: theButton[i].value = '';
								theButton[i].id = 'highkey';
								setOpt.highlightKw = theButton[i]; break;
				case 2: theButton[i].value = '';
								theButton[i].id = 'hightext';
								setOpt.highlightText = theButton[i]; break;
				case 3: theButton[i].value = '';
								theButton[i].id = 'hidequote';
								setOpt.hideQuotation = theButton[i]; break;
			}
			theP[i].appendChild(theButton[i]);
			theForm.appendChild(theP[i]);
		}
		
		// Build the Customize Article Display block in memory, insert into sidecol
		theH3.appendChild(document.createTextNode('Customize Article Display'));
		holderDiv.appendChild(theH3);
		holderDiv.appendChild(theForm);
		var theSideCol = jslib.getObj('sidecol');
		theSideCol.appendChild(holderDiv);
	},
	
	outputKWs : function() {
	// Build Keyword List with no duplicates
		//setOpt.allKws = setOpt.content.getElementsByTagName('span');
		if (setOpt.allKws[0] != null) {
			var kwData = [];
			for (var h=0; h<setOpt.allKws.length; h++) {
				kwData[h] = setOpt.allKws[h].firstChild.nodeValue;
			}
			if(kwData.splice) {
				var lastDiv = setOpt.content.getElementsByTagName('div');
				ldLength = lastDiv.length;
				var theKWp = document.createElement('p');
				var kwStart = document.createElement('strong')
				kwStart.appendChild(document.createTextNode('Keywords: '));
				theKWp.appendChild(kwStart);
				for (var i=0; i<kwData.length; i++) {
					for (var j=i+1; j<kwData.length; j++) {
						if (kwData[i] == kwData[j]) {
							kwData.splice(j,1);
						}
					}
					if (i<kwData.length-1) {
						theKWp.appendChild(document.createTextNode(kwData[i] + ', '));
					} else {
						theKWp.appendChild(document.createTextNode(kwData[i]));
						}

				}
			setOpt.content.insertBefore(theKWp,lastDiv[ldLength-1]);
			}
		}
	},
	
	outputPurls : function() {
	// Build Print URLs and insert supercript tags after links in content		
		var allUrls = setOpt.content.getElementsByTagName('a');
		if (allUrls[0] != null) {
			var urlDiv = document.createElement('div');
			urlDiv.className = 'printonly'; 
			var aHrefs = [], theLIs = [], linkTags = [];
			for (var h=0; h<allUrls.length; h++) {
				aHrefs[h] = allUrls[h].href;
				linkTags[h] = document.createElement('sup');
				linkTags[h].className = 'printonly';
			}
			if(aHrefs.splice) {
				var lastDiv = setOpt.content.getElementsByTagName('div');
				ldLength = lastDiv.length;			
				var aH4 = document.createElement('h4')
				aH4.appendChild(document.createTextNode('Links in this article:'));
				var theOL = document.createElement('ol');
				var numLinks = aHrefs.length;
				
				// Start loop(s) at 1 to skip #maincontent target for jumplink					
				for (var i=1; i<aHrefs.length; i++) {	
					// Start nested loop at 1 more than outside loop 
					// This assumes earlier duplicates have all been caught
					for (var j=i+1; j<aHrefs.length; j++) {
						if (aHrefs[i] == aHrefs[j]) {
							aHrefs.splice(j,1);						
						}
					}
					theLIs[i] = document.createElement('li');
					theLIs[i].appendChild(document.createTextNode(aHrefs[i]));
					theOL.appendChild(theLIs[i]);
				}
			
				// Append unique numbers in URLs
				for (var k=1; k<numLinks; k++) {
					for (var l=1; l<aHrefs.length; l++) {
						// Compare each URL on page to the unique URLs and write the 
						// unique reference number for each tag 
						if (allUrls[k].href == aHrefs[l]) {
							linkTags[k].appendChild(document.createTextNode('(' + l + ')'));
						}
					}
					allUrls[k].appendChild(linkTags[k]);
				}			
				urlDiv.appendChild(aH4);
				urlDiv.appendChild(theOL);
				// Insert URL div into document before copyright div
				setOpt.content.insertBefore(urlDiv,lastDiv[ldLength-1]);
			}
		}	
	},
	
	// Functions to handle button events
	adjustLineSpacing : function() {	
		var lsState = jslib.findCookie('ls');
		if (this.value == 'Increase Line Spacing' || (setOpt.lineSpacing.value == '' && lsState == 'inc')) {
		  setOpt.content.className = 'lhincrease';
		  setOpt.lineSpacing.value = 'Decrease Line Spacing';
		  jslib.createCookie('ls','inc',setOpt.expireDate);
		} else {
				// default setting
				setOpt.content.className = '';
				setOpt.lineSpacing.value = 'Increase Line Spacing';
				jslib.createCookie('ls','dec',setOpt.expireDate);
			} 
	},
	
	highlightKeywords : function() {
    setOpt.allKws = setOpt.content.getElementsByTagName('span');
		var kwlength = setOpt.allKws.length;
		var kwState = jslib.findCookie('kw');
		if (this.value == 'Highlight Keywords' || (setOpt.highlightKw.value == '' && kwState == 'hk')) {
			for (var i = 0; i < kwlength; i++) {
				setOpt.allKws[i].className = 'keyword';
			}
			setOpt.highlightKw.value = 'No Keyword Highlight';
			jslib.createCookie('kw','hk',setOpt.expireDate);
		}	else {
		    // default setting
				for (var i = 0; i < kwlength; i++) {
					setOpt.allKws[i].className = '';
				}
				setOpt.highlightKw.value = 'Highlight Keywords';
				jslib.createCookie('kw','nk',setOpt.expireDate);
			}
	},
	
	highlightTextHover : function() {
		var paras = setOpt.content.getElementsByTagName('p');
		var paraslength = paras.length;
		var htState = jslib.findCookie('ht');
		if (this.value == 'Highlight Text on Hover' || (setOpt.highlightText.value == '' && htState == 'ht')) {
			for (var i = 0; i < paraslength; i++) {
			  jslib.addEvent(paras[i],'mouseover',setOpt.hoveron);
				jslib.addEvent(paras[i],'mouseout',setOpt.hoveroff);
			}
			setOpt.highlightText.value = 'No Text Highlights';
			jslib.createCookie('ht','ht',setOpt.expireDate);
		} else {
				// default setting
				for (var i = 0; i < paraslength; i++) {
			 		jslib.removeEvent(paras[i],'mouseover',setOpt.hoveron);
					jslib.removeEvent(paras[i],'mouseout',setOpt.hoveroff);
				}
				setOpt.highlightText.value = 'Highlight Text on Hover';
				jslib.createCookie('ht','nt',setOpt.expireDate);
			}
	},
	
	hoveron : function() {  // for use with highlightTextHover
  	this.className = 'jshover';
	},
	hoveroff : function() {  // for use with highlightTextHover
  	this.className = '';
	},
	
	hideTheQuotation : function() {
		var blockq = document.getElementsByTagName('blockquote');
		var blockqlength = blockq.length;
		var bqState = jslib.findCookie('bq');
		if (this.value == 'Hide Quotations' || (setOpt.hideQuotation.value == '' && bqState == 'hq')) {
			for (var i=0; i<blockqlength; i++) {
			  blockq[i].className = 'hideit';
			}
			setOpt.hideQuotation.value = 'Show Quotations';
			jslib.createCookie('bq','hq',setOpt.expireDate);
		} else {
		    // default state
				for (var i=0; i<blockqlength; i++) {
			  	blockq[i].className = '';
			  }
			  setOpt.hideQuotation.value = 'Hide Quotations';
			  jslib.createCookie('bq','sq',setOpt.expireDate);
    }
  },

  // This JS manages the AJAX portions of HW8,
	// although utility portions are in jslib object

	searchData : null, searchSelect : null, searchInput : null, allArts : null,
	recentArts : null, searchArea : null, searchResArea : null, artsArea : null,
	searchForm : null, waitingDiv : null, timer : null, waitingMsg : false,

	buildSR : function () {
    var theSideCol = jslib.getObj('sidecol');

    setOpt.searchArea = document.createElement('div');
    setOpt.searchArea.id = 'searchSection';
    setOpt.artsArea = document.createElement('div');
    setOpt.artsArea.id = 'artsSection';

		// Create Search Form controls and Header
		var searchRH3 = document.createElement('h3');
		var searchRHtext = document.createTextNode('Article Search');
		setOpt.searchArea.appendChild(searchRH3).appendChild(searchRHtext);

		// Search Select Scope Modifier
		setOpt.searchForm = document.createElement('form');
		setOpt.searchForm.id = 'artSearch';
		setOpt.searchForm.setAttribute('action','');
		setOpt.searchForm.setAttribute('method','post');

  	setOpt.searchSelect = document.createElement('select');
		// Select options in pairs, visible text first, category second
		var selectOptions = ['All Topics','all','AJAX','ajax','CSS','css','JavaScript','js','PHP','php','Photoshop','ps','Ruby','ruby','User Experience','ux','XHTML','xhtml','XSLT','xslt','Web Careers','career'];
		for (var i=0,numOptions=selectOptions.length; i<numOptions; i=i+2) {
			var searchROption = document.createElement('option');
   		var optDisplay = document.createTextNode(selectOptions[i]);
   		searchROption.setAttribute('value',selectOptions[i+1]);
			setOpt.searchSelect.appendChild(searchROption).appendChild(optDisplay);
		}
		setOpt.searchForm.appendChild(setOpt.searchSelect);
		setOpt.searchForm.appendChild(document.createTextNode(' for:'));
		setOpt.searchForm.appendChild(document.createElement('br'));

		// Search Input Box
		setOpt.searchInput = document.createElement('input');
		setOpt.searchInput.setAttribute('type','text');
		setOpt.searchInput.setAttribute('size','16');
		setOpt.searchForm.appendChild(setOpt.searchInput);

		// Create div for waiting text
		setOpt.waitingDiv = document.createElement('div');
		setOpt.searchForm.appendChild(setOpt.waitingDiv);

		// Put searchForm into searchArea div
    setOpt.searchArea.appendChild(setOpt.searchForm);

		// Create div to hold Search Results
		setOpt.searchResArea = document.createElement('div');
		setOpt.searchResArea.id = 'searchResults';
		setOpt.searchArea.appendChild(setOpt.searchResArea);

		// Insert into document
		theSideCol.appendChild(setOpt.searchArea);
		theSideCol.appendChild(setOpt.artsArea);
	},

	storeSearchArts : function (xhr) {
		setOpt.allArts = xhr.responseXML;
	},

	setTimer : function () {

		// if called via action on select menu but no query text present,
		// go to doSearch to clear any results and then return
		if (!setOpt.searchInput.value) {return;}

		// clear time if it is running
		if (setOpt.timer) {clearTimeout(setOpt.timer);}

		// display waiting message if not there already
		if (!setOpt.waitingMsg) {

		  // If showing 'No results were found.' in waitingDiv then remove it
			if (setOpt.waitingDiv.firstChild) {
			  setOpt.waitingDiv.removeChild(setOpt.waitingDiv.firstChild);}

			setOpt.waitingDiv.id = 'waiting';
			setOpt.waitingDiv.className = 'bold';
			var waitingTxt = document.createTextNode('Waiting for you to finish entering your search...');

			setOpt.searchForm.appendChild(setOpt.waitingDiv).appendChild(waitingTxt);
			setOpt.waitingMsg = true;
		}

		setOpt.timer = setTimeout('setOpt.doSearch()',2500);
	},

	doSearch : function () {
		// clear any previous search results
		setOpt.searchResArea.innerHTML = '';

		// If no value, do nothing except clearing results
		if (!setOpt.searchInput.value) {return;}

		// Determine total possible results
		var totalResults = setOpt.allArts.getElementsByTagName('article').length;

		// lowercase the query and scope to eliminate mismatches due to case
		var queryValue = setOpt.searchInput.value.toLowerCase();
		var scopeValue = setOpt.searchSelect.value.toLowerCase();

		// Remove the waiting message and flip waitingMsg to false again
		setOpt.waitingDiv.removeChild(setOpt.waitingDiv.firstChild);
		setOpt.waitingDiv.id = '';
		setOpt.waitingMsg = false;

		var resultsUL = document.createElement('ul');
		resultsUL.id = 'resultsList';
		// Check for results and build into an unordered list
		for (var i=0, numResults=0; i<totalResults; i++) {

			// get each article title and category, lowercase them
			var article = setOpt.allArts.getElementsByTagName('title')[i].firstChild.nodeValue.toLowerCase();
			var category = setOpt.allArts.getElementsByTagName('category')[i].firstChild.nodeValue.toLowerCase();

			// See if there is a match, and if so, build the list item
			if (article.match(queryValue) && (category.match(scopeValue) || scopeValue == 'all')) {
				numResults++;
				var resultLI = document.createElement('li');

				// create link
				var resultA = document.createElement('a');
				var linkText = document.createTextNode(setOpt.allArts.getElementsByTagName('title')[i].firstChild.nodeValue);
				var linkUrl = setOpt.allArts.getElementsByTagName('url')[i].firstChild.nodeValue;
				resultA.appendChild(linkText);
				resultA.setAttribute('href',linkUrl);

				// get rating and number of voters
				var avgRtg = setOpt.allArts.getElementsByTagName('rtg')[i].firstChild.nodeValue;
				var numRaters = setOpt.allArts.getElementsByTagName('raters')[i].firstChild.nodeValue;

				// make link bold if rating is 8 or higher
				if (avgRtg >= 8) {
					resultA.className = 'bold';
				}

				// Write Rating line to span
				var rtgSpan = document.createElement('span');
				var rtgSpanText = 'Avg Rtg: ' + avgRtg + ' (' + numRaters + ' votes)';
				rtgSpan.appendChild(document.createTextNode(rtgSpanText));

				// write data to li
				resultLI.appendChild(resultA);
				resultLI.appendChild(document.createElement('br'));
				resultLI.appendChild(rtgSpan);
			}
			if (numResults > 0) {resultsUL.appendChild(resultLI);}
		}

		if (numResults == 0) {
			// No results found, put 'No results were found.' under Seach Input box
			var noResultsMsg = document.createTextNode('No results were found.');
			setOpt.waitingDiv.appendChild(noResultsMsg);
		} else {
			// Results found, display header, insert UL below header
			var resultsHeader = document.createElement('h3');
			resultsHeader.id = 'resultsHeader';
			var resHeadText = numResults + ' Search Result';
			if (numResults > 1) {resHeadText += 's';}
			setOpt.searchResArea.appendChild(resultsHeader).appendChild(document.createTextNode(resHeadText));
			setOpt.searchResArea.appendChild(resultsUL);
		}
	},

	// gets or refreshes the article XML data when called
	getNewArts : function () {
		jslib.sendRequest('xml/recent_articles.xml?' + Math.random(), setOpt.displayArts);
	},

	displayArts : function (xhr) {
		// assign recent Article XML data to a variable
		setOpt.recentArts = xhr.responseXML;

		// Clear ArtsArea
		setOpt.artsArea.innerHTML = '';

		// Create H3 Header
		var artsH3 = document.createElement('h3');
		var artHeader = document.createTextNode('Recent Articles');
		setOpt.artsArea.appendChild(artsH3).appendChild(artHeader);

		var totalRArts = setOpt.recentArts.getElementsByTagName('article').length;
		var ulHolder = document.createElement('ul');
		ulHolder.id = 'artlist';
		for (var i=0; i<totalRArts; i++) {
		  var newLI = document.createElement('li');
		  var newLink = document.createElement('a');
		  var artTitle = document.createTextNode(setOpt.recentArts.getElementsByTagName('title')[i].firstChild.nodeValue);
		  var artURL = setOpt.recentArts.getElementsByTagName('url')[i].firstChild.nodeValue;
		  newLink.setAttribute('href',artURL);
		  ulHolder.appendChild(newLI).appendChild(newLink).appendChild(artTitle);
		}
		setOpt.artsArea.appendChild(ulHolder);
	}

}

jslib.addEvent(window, 'load', setOpt.init);
