/*  (c) Copyright 2006 Apple Computer, Inc. All rights reserved.  */

var page = new Page();

/*////////////////////////////  SEARCH SUBMIT   //////////////////////////////*/

function SearchFunction(page) { 
	var me = this;
	var defaultHits = 10;

	this.initFromQueryString = function() {
		this.lang = urlDecode(getQueryStringValue('lang'));
		this.searchString = urlDecode(getQueryStringValue('q'));
		this.formattedSearchString = this.formatSearchForQuery(this.searchString);
		this.path =  urlDecode(getQueryStringValue('path'));
		this.rawPath = this.path ? urlEncode('/' + this.path.split('/')[1]) : null;
		this.GUID =  urlDecode(getQueryStringValue('GUID'));
		this.rawGUID = getQueryStringValue('GUID');
		this.hitStart = this.hitCountWithDefault(getQueryStringValue('hitStart'), 1);
		this.hitAmount = this.hitCountWithDefault(getQueryStringValue('hitAmount'), defaultHits);
	};
	
	this.initFromForm = function(formObj) {
		this.searchString = formObj.q.value;
		this.formattedSearchString = this.formatSearchForQuery(urlEncode(this.searchString));
		this.path =  formObj.path.value;
		this.rawPath = this.path ? urlEncode('/' + this.path.split('/')[1]) : null;
		this.GUID =  formObj.GUID.value;
		this.rawGUID =  urlEncode(formObj.GUID.value);
		this.lang = formObj.lang.value;
		if (page.lang != this.lang) { page.translate(this.lang); }
		this.hitStart = formObj.hitStart ? this.hitCountWithDefault(formObj.hitStart, 1): 1;
	};
				
	this.submit = function() {
		page.setFormValues(this);
		this.xSubmitSearch();
	};
	
	this.resubmit= function(formObj) {
		this.initFromForm(formObj);
		this.submit();
	};
	
	this.hitCountWithDefault = function(value, defaultValue) {
		value = isNumeric(value) ? Number(value) : defaultValue;
		if (value < 1) { value = defaultValue;  }
		return value;
	};	
	
	this.formatSearchForQuery = function(string) {
	 	// remove wildcard character completely & trim spaces
	 	string = trim(string);
	 	string =  string.replace(/\*/g, "");
		var escapeChars = ['~', '+', '-', '!', '(', ')', '{', '}', '[', ']', '^' ,'\\', '?', ':', '"' , '&', '|', '#'
		];
    var myRegExp = new RegExp('(\\' + escapeChars.join('|\\') + ')', 'g');
  	string = string.replace(myRegExp, '\\$1');

  	string = urlEncode(string);
  	return string;
	}
	
	this.xSubmitSearch = function() {
		var connection = new DMHTTPConnection();
		connection.alertOnException = false;
		
		
		var parameter = "";
		if (this.rawPath && this.formattedSearchString && this.rawGUID) {
			var object = new Object;
			object['rss-query-get'] = this.formattedSearchString + " AND channelId:" + this.GUID;
			connection.setRootObject(object);
		  parameter = "webdav-method=rss-query-get";
			parameter = parameter + "&scope=" + this.rawPath;
			parameter = parameter + "&query=(" + this.formattedSearchString + urlEncode(") AND channelId:") + this.rawGUID ;
			parameter = parameter + "&hitAmount=" + this.hitAmount + "&hitStart=" + this.hitStart;
			parameter = parameter + "&report=full&format=xml";
			connection.callMethod(this.path, parameter, this.cbDisplayResults);
			//connection.callMethod('/_rss/Query', parameter, this.cbDisplayResults);
		} else if (this.rawPath && this.rawGUID) {
			this.cbDisplayResults(status, document.createElement("span"));
		} else {
			this.cbDisplayResults(status, null)
		}
	};
	
	this.cbDisplayResults = function(status, xmlresponse) {
		if (status < 400) {
			page.searchResults = new SearchResults(xmlresponse, me, 'results');
		} else {
			page.searchResults = new SearchResults(document.createElement("span"), me, 'results');
		}
		page.searchResults.insertResults();
	};
		
}

/*////////////////////////////  SEARCH RESULTS   //////////////////////////////*/


function SearchResults(xmlresponse, searchFunction, divId) {
	this.xmlresponse = xmlresponse;
	this.divId = divId;	
	this.results = this.xmlresponse ? this.xmlresponse.getElementsByTagName("item") : new Array();	
	this.searchString = searchFunction.searchString;
	this.resultStart = searchFunction.hitStart;
	this.resultEnd = eval(this.resultStart) + this.results.length - 1;
	
	this.getResultCount = function() {
		var summaryResult= this.xmlresponse && this.xmlresponse.getElementsByTagName('hitTotal').length > 0 ? this.xmlresponse.getElementsByTagName('hitTotal')[0] : null;
		var count = 0; 
		if (summaryResult && summaryResult.firstChild) { 
			count = summaryResult.firstChild.nodeValue; 
		} else { 
			count = this.results.length;
		}	
		return count;
	};
	this.resultCount = this.getResultCount();

	this.getBlogTitle = function() {
		var summaryResult = this.xmlresponse ? this.xmlresponse.getElementsByTagName('channelTitle') : new Array();
		var blogTitle = "";
		for (var i=0; i<summaryResult.length; i++) {
			if	(summaryResult[i].firstChild) { blogTitle = summaryResult[i].firstChild.nodeValue; break; }
		}
		this.blogTitle = blogTitle;
	};
	this.getBlogTitle();
	
	
	this.nextResults = function() {
		if (this.resultEnd < this.resultCount) {
			searchFunction.hitStart = searchFunction.hitCountWithDefault(this.resultEnd + 1, this.resultStart);
			searchFunction.xSubmitSearch();
		}
	};
	
	this.previousResults = function() {
		if (this.resultStart > 1) {
			searchFunction.hitStart = searchFunction.hitCountWithDefault(this.resultStart - searchFunction.hitAmount, this.resultStart);
			searchFunction.xSubmitSearch();
		}
	};
	
	// do display
	this.insertResults = function() {
		var searchResult;
		if (this.xmlresponse) {
			page.buildSummaryHTML(this);
			for (var i=0; i<this.results.length; i++) {
				searchResult = new SearchResult(this.results[i]);
				page.buildResultHTML(searchResult, this);
			}
			page.buildPagination(this);
			zebraStripe('results','DIV','result','odd','even');
		} else {
			page.displayError();
			return;
		}
		page.makeVisible();
	}

}


/*////////////////////////////  SINGLE RESULT  //////////////////////////////*/

function SearchResult(resultData)  {	
		
	this.formatDate = function(entryDate, pubDate) {
		var date;
		date = entryDate && entryDate != 'null' ? entryDate : ( pubDate && pubDate != 'null' ? pubDate : null);
		return date;
	};
	
	this.formatLink = function(string) {
		var location =  string.split('?');
		var URL = location[0];
		var queryString = location.length > 1 ? location[1] : null;
		if (queryString) {
			var keyPairs = queryString.split("&");
			var anchor = '';
			for (var i=0;i<keyPairs.length;i++) {
				var keyPair = keyPairs[i].split("=");
				if (keyPair[0] == 'subprops') {
					anchor = keyPair[1];
				}
			} 
			anchor = anchor.replace(/\-/g, "_");
			if (anchor) { URL = URL + "#comment_" + anchor; }
		}
		return URL;
	};
	
	this.formatSummary = function(string) {	
	
		if (string.length >= 197) { 
				string = string.substring(0, 197) + "...";
		}
	
		if (resultData.getElementsByTagName("c.a.d.idisk.subprops")) {
			string = removeTags(string, "b");
			string = removeTags(string, "i");
			string = removeTags(string, "u");
			string = escapeHTML(string);
			string = replaceLineBreaks(string);
		}
		
		
		return string;
	}

	this.createResult = function() {
		var result = resultData.firstChild;
		while (result) {
			if (result.tagName) {
				if (result.tagName == "link" && result.firstChild) { this.link = result.firstChild.nodeValue; }
				if (result.tagName == "title" && result.firstChild) { this.title = result.firstChild.nodeValue; } 
				if (result.tagName.toLowerCase() == "pubdisplaydate" && result.firstChild) { this.pubDate = result.firstChild.nodeValue; }
				if (result.tagName.toLowerCase() == "blogentrydisplaydate" && result.firstChild) { this.entryDate = result.firstChild.nodeValue; 
				}
				if (result.tagName == "description" && result.firstChild) { this.summary = result.firstChild.nodeValue; }
				if (this.summary) {
					this.formattedSummary = this.formatSummary(this.summary);
				}
			}
			result = result.nextSibling;
		}
		
		if (!this.title && this.link) { this.title = this.link.replace("http://web.mac.com/", "") };
		this.date = this.formatDate(this.entryDate, this.pubDate);
		this.link = this.formatLink(this.link);
	};
	this.createResult();
	
}

/*////////////////////////////  PAGE STATE & HTML CREATION  //////////////////////////////*/

function Page() {
	this.lang = urlDecode(getQueryStringValue('lang'));
	if (this.lang == "") { this.lang = "en"; }
	this.searchFunction = new SearchFunction(this);
	this.searchFunction.initFromQueryString();
	var localize;
	
	this.translate = function(language) {
		if (language) this.lang = language;
		localize = new LocalizedStrings(this.lang);
		document.title = localize.PageTitle;
		if (localize.ReturnLink) { 
			document.getElementById('return').innerHTML = localizedStringWithArgs(localize.ReturnLink, this.searchFunction.path); 
		}
		document.getElementById('header').style.background = "url('" + localize.HeaderImage + "') no-repeat";
		document.getElementsByTagName('link')[0].href = localize.CSS;
	};
	
	this.setFormValues = function(searchFunction) {
		document.forms['search1'].q.value = searchFunction.searchString;
		document.forms['search2'].q.value = searchFunction.searchString;
		document.forms['search1'].path.value = searchFunction.path;
		document.forms['search2'].path.value = searchFunction.path;
		document.forms['search1'].GUID.value = searchFunction.GUID;
		document.forms['search2'].GUID.value = searchFunction.GUID;
		document.forms['search1'].lang.value = searchFunction.lang;
		document.forms['search2'].lang.value = searchFunction.lang;
	};


	this.buildSummaryHTML = function(searchResults) {
			
			if (searchResults.resultCount > 0) {
				document.getElementById('search2').style.visibility = 'visible';
				document.getElementById('info').style.display = '';
				document.getElementById('result_summary').innerHTML = localizedStringWithArgs(localize.SearchedFor, trim(searchResults.searchString), searchResults.blogTitle) + "&nbsp; " + localizedStringWithArgs(localize.NowShowing, searchResults.resultStart, searchResults.resultEnd, searchResults.resultCount);
				document.getElementById('results').innerHTML = "";
			} else {
				document.getElementById('search2').style.visibility = 'hidden';
				document.getElementById('info').style.display = 'none';
				document.getElementById('result_summary').innerHTML = '';
				document.getElementById('results').innerHTML = "<div class='result'><h3 class='noresult'>" + localize.NoResults + "</h3></div>";
			}		
		};	
	
	this.buildPagination = function(searchResults) {
			var prevLink = document.getElementById('previous');
			var nextLink = document.getElementById('next');
			
			if (searchResults.resultStart > 1) {
				prevLink.href = "javascript:page.searchResults.previousResults();";
				prevLink.style.visibility = "visible";
			} else {
				prevLink.removeAttribute("href");
				prevLink.style.visibility = "hidden";
			}
			
			document.getElementById('pageCount').innerHTML = "";
			if (searchResults.resultStart > 1 || searchResults.resultCount > searchResults.resultEnd) {
				var details = document.createTextNode(searchResults.resultStart + " - " + searchResults.resultEnd + " " + localize.Of + " " + searchResults.resultCount);
				document.getElementById('pageCount').appendChild(details);
			} 
		
			if (searchResults.resultCount > searchResults.resultEnd) {
				nextLink.href = "javascript:page.searchResults.nextResults();";
				nextLink.style.visibility = "visible";
			} else {
				nextLink.removeAttribute("href");
				nextLink.style.visibility = "hidden";
			}
		};	
		
	this.buildResultHTML = function(resultObject, resultSummary) {
			var HTML = "";
			if (resultObject.date) { HTML = HTML + "<div class='caption date'>" + resultObject.date + "</div>\n"; }
			if (resultObject.link && resultObject.title) { 
				HTML = HTML + "<h3><a href='" + resultObject.link + "'>" + resultObject.title + "</a></h3>\n"; 
			} else if (resultObject.title) {
				HTML = HTML + "<h3>" + resultObject.title + "</h3>\n"; 
			}
			HTML = HTML + "<div class='break'></div>";
			if (resultObject.formattedSummary) { HTML = HTML + "<p class='body_text_dark'>" + highlightWord(resultObject.formattedSummary, resultSummary.searchString) +"</p>"; }
			if (resultObject.link) { HTML = HTML + "<p class='caption entryid'>" + insertBreak(resultObject.link, 150, "/?#") + "</p>"; }
			HTML = HTML + "<div class='break'></div>";
			
			var container = document.getElementById(resultSummary.divId);
			itemBlock = document.createElement("div");
			itemBlock.className = "result";
			itemBlock.innerHTML = HTML;
			container.appendChild(itemBlock);
	};
	
	this.displayError = function() {
		document.location.replace("http://www.mac.com/WebObjects/Comments.woa/wa/error?lang=" + page.lang);
	};
		
	this.makeVisible = function() {
		document.body.style.visibility = "visible";
	}
		
}

/*////////////////////////////  UTILITY FUNCTIONS   //////////////////////////////*/

function getQueryStringValue(variable) {
	var queryString = window.location.search.substring(1);
	var keyPairs = queryString.split("&");
	for (var i=0;i<keyPairs.length;i++) {
		var keyPair = keyPairs[i].split("=");
		if (keyPair[0] == variable) {
			return keyPair[1];
		}
	} 
	return "";
}

function urlDecode(string) {
	string = string.replace(/\+/ig," ");
	string = decodeURIComponent(string);
	return string;
}

function urlEncode(string) {
	 string = encodeURIComponent(string);
	 return string;
 } 

function replaceLineBreaks(string) {
	string = string.replace(/\n/g, "<br>");
	string = string.replace(/\r/g, "<br>");
	return string;
}

function escapeHTML(string) {
	string = string.replace(/\</g, "&lt;");
	string = string.replace(/\>/g, "&gt;");
	return string;
}

function localizedStringWithArgs() {
	var string = arguments[0];
	for (var i=1; i<arguments.length; i++) {
		string = string.replace('%' + i + '$@', arguments[i]);
	}
	return string;
}

function isNumeric(string) {
	 string = string.toString();
   var numerals = "0123456789";
   var result = true;  
   if (string && string.length == 0) return false;
   for (var i=0; i<string.length; i++) {
      if (numerals.indexOf(string.charAt(i)) == -1) {
         result = false;
         break;
        }
   }
   return result;
 }


function insertBreak(string, maxLength, breakChars) {
	try { var length = Number(maxLength) } catch (e) { return string; }
	
	if (string.length > maxLength) { 
		for (var i=maxLength; i>0; i--) {
			if (breakChars.indexOf(string.charAt(i)) > -1 && string.length > i) {
				 var firstLine = string.substring(0,i+1);
				 var secondLine = string.substring(i+1);
				 break;
			}
		}
		if (secondLine && secondLine.length > maxLength) {
			secondLine = insertBreak(secondLine, maxLength, breakChars);
		}
		string = firstLine && secondLine ? firstLine + "<br>" + secondLine : string;
	}
	return string;
}


function zebraStripe(e,child,classname,odd,even) {
	if (!document.getElementById) { return false; }
	var elements = document.getElementById(e).getElementsByTagName(child);
	var newclass;
	var j = 0;
	// looping over the set of child elements
	for (var i = 0; i < elements.length; i ++)  {
		if (elements[i].className.lastIndexOf(classname) >= 0) { // if child contains class classname
			if (j % 2 == 0) { newclass  = odd; } else { newclass = even; }
			elements[i].className = elements[i].className + ' ' + newclass;
			j++;
		}
	}
	return true;
}


function highlightWord(string, selection) {
	var components = trim(selection).split(' ');
	var formatted, word, exp, match, replacement, emb;
	for (var i = 0; i< components.length; i++) {
		word = components[i];
		pattern = new RegExp("\\b" + escapeChars(word) + "\\b",'i');
		formatted = '';
		// Look for matches in the excerpt string
		while ((match = pattern.exec(string)) != null) {
			emb = '<strong>' + match[0] + '</strong>';
			// add match to result
			formatted = formatted + string.slice(0,match.index) + emb
			// search over result
			string = string.slice(match.index + word.length);
		}
		// add in the unmatched remainder
		formatted = formatted + string;
		string = formatted;
	}
	return formatted;			
}


function trim(string) {
  string =  string.replace(/^\s*|\s*$/g, "");
  return string;
}


function escapeChars(string) {
		var escapeChars = ['~', '+', '-', '!', '(', ')', '{', '}', '[', ']', '^' ,'\\', '?', ':', '"' , '&', '|', '#', '*'];
    var myRegExp = new RegExp('(\\' + escapeChars.join('|\\') + ')', 'g');
  	string = string.replace(myRegExp, '\\$1');  	
  	return string;
	}
	
function removeTags(string, tag) {
	var openTag = new RegExp('<[\\s\\xA0]*' + tag + '[\\s\\xA0]*>','ig');
	var closeTag = new RegExp('</[\\s\\xA0]*' + tag + '[\\s\\xA0]*>','ig');

	// if too many close tags after cleaning, remove the extras
	string = string.replace(openTag,'');
	string = string.replace(closeTag,'');

	return string;
}


