/* checked with JSLint www.jslint.com */
/*global LinkManager, UrlGen, SeoLinkManager, SeoUrlFormatter, UrlState */

/**
 * Submits a search based on the Ntt, Ntk, Ntx, and searchWithin elements
 * of the given form.
 * @param {Object}  form                  the search form element
 * @param {boolean} applyDimensionSearch  whether or not to apply dimension search
 * @param {String}  controller            this should be the same as the Java LinkManager's controller
 */
function submitSearch(form, applyDimensionSearch, controller) {
	if (form.Ntt.value === '') {
		alert('\u8bf7\u8f93\u5165\u641c\u7d22\u8bcd');
	}
	else {
		var linkMgr = new LinkManager(controller);
		var searchWithin = form.searchWithin && form.searchWithin.checked;
		document.location = linkMgr.generateSearchLink(form.Ntk.value, form.Ntt.value, form.Ntx.value, searchWithin, applyDimensionSearch);
	}
}

/**
 * Constructs a javascript LinkManager object that provides a similar set of methods
 * as the Java LinkManager object. 
 *
 * The javascript LinkManager object should have "processUrlGen" methods to accompany
 * the "generate" methods, since the "processUrlGen" methods can be shared between the
 * LinkManager and SeoLinkManager "generate" methods
 * @constructor
 * @param {String} controller  this should be the same as the Java LinkManager's controller.
 */
LinkManager = function (controller) {
	this.controller = controller;
};
LinkManager.prototype = {
	/**
	 * the page to send all links to
	 * @type String
	 */
	controller: undefined,
	/**
	 * Generates a search link by manipulating/adding Ntt, Ntk, Ntx, D, and Dx parameters to the 
	 * current query string.
	 * @param {String}  key              the search key 
	 * @param {String}  terms            the search terms
	 * @param {String}  opts             the search options
	 * @param {boolean} searchWithin     whether or not to "search within"
	 * @param {boolean} dimensionSearch  whether or not to append the D and Dx parameters
	 * @type String
	 */
	generateSearchLink: function (key, terms, opts, searchWithin, dimensionSearch) {
		var urlGen = this.processSearchLinkUrlGen(key, terms, opts, searchWithin, dimensionSearch, new UrlGen(), new UrlGen('N=0'));
		return this.controller + '?' + urlGen.toString();			
	},
	/**
	 * Applies the logic to determine search within behavior, returning a processed UrlGen object
	 * @type UrlGen
	 * @param {String}  key              the search key 
	 * @param {String}  terms            the search terms
	 * @param {String}  opts             the search options
	 * @param {boolean} searchWithin     whether or not to "search within"
	 * @param {boolean} dimensionSearch  whether or not to append the D and Dx parameters
	 * @param {UrlGen}  urlg             the UrlGen with the current application state
	 * @param {UrlGen}  emptyUrlg        the UrlGen to use to clear the search if searchWithin == false
	 * @return the processed UrlGen object
	 */
	processSearchLinkUrlGen: function (key, terms, opts, searchWithin, dimensionSearch, urlg, emptyUrlg) {
		var Ntk = "";
		var Ntt = "";
		var Ntx = "";
		
		if (searchWithin) {
			var curNtk = urlg.getParam("Ntk");
			if (curNtk !== null && curNtk.length > 0) {
				Ntk = curNtk + "|";
			}
			var curNtx = urlg.getParam("Ntx");
			if (curNtx !== null && curNtx.length > 0) {
				Ntx = curNtx + "|";
			}
			var curNtt = urlg.getParam("Ntt");
			if (curNtt !== null && curNtt.length > 0) {
				Ntt = curNtt + "|";
			}
			// we need to remove the offset param
			urlg.removeParam("No");
			urlg.removeParam("Nao");
		}
		else {
			urlg = emptyUrlg;
		}
		
		Ntk += key;
		Ntt += terms;
		Ntx += opts;

		urlg.addParam("Ntk", Ntk);
		urlg.addParam("Ntx", Ntx);
		urlg.addParam("Ntt", Ntt);

		if (dimensionSearch) {
			if (searchWithin) {
				// replace all pipe symbols with a plus sign
				urlg.addParam("D", Ntt.replace(/\|/g, "+"));
				// This we'll have to use the latest opts
				urlg.addParam("Dx", opts);
			}
			else {
				urlg.addParam("D", terms);
				urlg.addParam("Dx", opts);
			}
			
		}
		return urlg;
	}
};

/**
 * Contructs a javascript UrlGen object.
 * <p/>
 * var urlg = new UrlGen("N=0") will create a UrlGen object
 * with one parameter.
 * <p/>
 * var urlg = new UrlGen() will create a UrlGen object from the
 * document.location.search object, similar to the Java line:<br/>
 * UrlGen urlg = new UrlGen(request.getQueryString(), "UTF-8").
 * <p/>
 * var urlg = new UrlGen("") will create a UrlGen object 
 * with no parameters.
 * @constructor
 * @param {String} queryString the queryString 
 */
UrlGen = function (queryString) {
	if (queryString) {
		this.paramArray = queryString.split('&');
	}
	else {
		var search = document.location.search;
		this.paramArray = search.substring(1, search.length).split('&');
	}
};
UrlGen.prototype = {
	/**
	 * Internal array of parameters. The parameters
	 * are Strings representing the name and value, 
	 * separated by the equals sign ("="). e.g. ["N=0", "Ne=8061"].
	 * @type Array
	 */
	paramArray: undefined,
	/**
	 * Gets the given parameter from the internal array.
	 * @type String
	 * @return the value of the given parameter or
	 * <code>null</code> if no param was found.
	 */
	getParam: function (paramName) {
		var retval = null;
		for (var i = 0; i < this.paramArray.length; i++) {
			var param = this.paramArray[i];
			var nameAndValue = param.split('=');
			if (nameAndValue[0] === paramName) {
				retval = unescape(nameAndValue[1]);
				break;
			}
		}
		return retval;
	},
	/**
	 * Adds the given parameter name and value ot the internal array.
	 */
	addParam: function (paramName, paramValue) {
		if (paramValue) {
			var paramArray = this.paramArray;
			var addToArray = true;
			for (var i = 0; i < paramArray.length; i++) {
				var param = paramArray[i];
				var nameAndValue = param.split('=');
				if (nameAndValue[0] === paramName) {
					paramArray[i] = paramName + '=' + paramValue;
					addToArray = false;
					break;
				}
			}
			if (addToArray) {
				paramArray.push(paramName + '=' + paramValue);
			}
		}
	},
	/**
	 * Removes the given parameter from the internal array.
	 * @type String
	 * @return the value of the removed parameter or
	 * <code>null</code> if no param was found.
	 */
	removeParam: function (paramName) {
		var retval = null;
		for (var i = 0; i < this.paramArray.length; i++) {
			var param = this.paramArray[i];
			var nameAndValue = param.split('=');
			if (nameAndValue[0] === paramName) {
				this.paramArray.splice(i, 1);
				retval = unescape(nameAndValue[1]);
				break;
			}
		}
		return retval;
	},
	/**
	 * The query string representation of the parameters in the internal array.
	 * names and values separated by "=", parameters separated
	 * by "&". e.g. "N=0&Ne=8061"
	 * @type String
	 * @return the query string representation or "" if the internal array is empty.
	 */
	toString: function () {
		return this.paramArray.join('&');
	}
};
