/**
 * Sets up search data
 * calls your ajax function with the following parameters:
 * 1: url
 * 2: hash of key/value pairs
 * 3: callback function
 * 
 * @class Search
 * @requires an ajax library and a function that calls it
 * @namespace INTRIGO
 * @param {String} url: url where data is sent to for searching
 * @param {Function} ajaxFunc: ajax function used to call url and send data
 * @param {Function} callbackFunc: function that receives your ajax call and the search data
 */
if (!INTRIGO) var INTRIGO = {};
INTRIGO.Search = function(url, ajaxFunc, callbackFunc) {
	if (typeof(url) == 'string')
		this._url = url;
	else alert('INTRIGO.Search error: url must be a valid string');
	
	if (typeof(ajaxFunc) == 'function' && typeof(callbackFunc) == 'function') {
		this._ajaxFunc = ajaxFunc;
		this._callbackFunc = callbackFunc;
	}
	else alert('INTRIGO.Search error: ajaxFun and callbackFunc must be a valid functions');
	
	this._params = {};
}
INTRIGO.Search.prototype = {
	_url: null,
	_ajaxFunc: null,
	_callbackFunc: null,
	_params: null,
	_preSearchFunc: null,
	
	/**
	 * sends the search
	 * @param {String} value[optional]
	 * @param {String} field[optional]
	 * @return INTRIGO.SEARCH instance of self
	 */
	search: function(value, field) {
		if (!this._params.search)
			this._params.search = {};
		
		if (this._preSearchFunc) {
			this._preSearchFunc();
		}
		
		this._params.search.field = field;
		this._params.search.value = value;
		this._ajaxFunc(this._url, this.urlEncode(), this._callbackFunc);
		return this;
	},
	
	/**
	 * sets a function that gets called before the search
	 * @param {Function} func
	 * @return INTRIGO.SEARCH instance of self
	 */
	setPreSearchFunction: function(func) {
		if (typeof(func) == 'function') {
			this._preSearchFunc = func;
		}
		return this;
	},
	
	/**
	 * sends the latest search if one
	 * @return INTRIGO.SEARCH instance of self
	 */
	searchLatest: function() {
		if (this._params.search) {
			this.search(this._params.search.value, this._params.search.field);
		}
		else {
			this.search();
		}
	},
	
	/**
	 * sets an order by column and direction
	 * @param {String} order
	 * @param {String} direction[optional]
	 * @return INTRIGO.SEARCH instance of self
	 */
	setOrderBy: function(order, direction) {
		if (!this._params.order)
			this._params.order = {};
		
		if (!direction) {
				if (order == this._params.order.field && this._params.order.direction == 'ASC') {
					this.setOffset(0);
					this._params.order.direction = 'DESC';
				}
				else {
					this.setOffset(0);
					this._params.order.direction = 'ASC';
				}
				
		} 
		else this._params.order.direction = direction;
		
		if (order) {
			this._params.order.field = order;
		}
		
		return this;
	},
	
	/**
	 * sets the offset value
	 * @param {Integer} value
	 * @return INTRIGO.SEARCH instance of self
	 */
	setOffset: function(value) {
		this._params.offset = value;
		return this;
	},
	
	/**
	 * gets the set offset
	 * @return {String} offset
	 */
	getOffset: function() {
		return this._params.offset;
	},
	
	/**
	 * sets the limit value
	 * @param {Integer} value
	 * @return INTRIGO.SEARCH instance of self
	 */
	setLimit: function(value) {
		this._params.limit = value;
		return this;
	},
	
	/**
	 * gets the set limit
	 * @param {String} limit
	 */
	getLimit: function() {
		return this._params.limit;
	},
	
	/**
	 * adds a list of filters
	 * @param {Hash} hash: see addFilter
	 * @return INTRIGO.SEARCH instance of self
	 */
	addFilters: function(hash) {
		if (typeof(hash) == 'object') {
			for (var i in hash) {
				this.addFilter(i, hash[i]);
			}
		}
		return this;
	},
	
	/**
	 * adds a filter to the filters list
	 * @param {String} key: a field to filter by
	 * @param {String} value: the value to filter for
	 * @return INTRIGO.SEARCH instance of self
	 */
	addFilter: function(key, value) {
		if (!this._params.filters)
			this._params.filters = {};
		if (key)
			this._params.filters[key] = value;
		return this;
	},
	
	/**
	 * removes a filter (if it exists) based on its key
	 * @param {Object} key
	 * @return INTRIGO.SEARCH instance of self
	 */
	removeFilter: function(key) {
		if (this._params.filters) {
			if (this._params.filters[key]) {
				this._params.filters[key] = null
				delete(this._params.filters[key]);
			}
		}
		return this;
	},
	
	/**
	 * removes all filters
	 * @return INTRIGO.SEARCH instance of self
	 */
	removeAllFilters: function() {
		this._params.filters = {};
		return this;
	},
	
	/**
	 * adds a list of fields that will be returned
	 * @param {Array}: an array of fields
	 * @return INTRIGO.SEARCH instance of self
	 */
	addReturnFields: function(array) {
		if (typeof(array) == 'object') {
			for (var i in array) {
				this.addReturnField(array[i]);
			}
		}
		return this;
	},
	
	/**
	 * adds a return field to the list
	 * @param {String} field: field name to add
	 * @return INTRIGO.SEARCH instance of self
	 */
	addReturnField: function(field) {
		if (!this._params.returnFields)
			this._params.returnFields = [];
		if (field) {
			this._params.returnFields[this._params.returnFields.length] = field;
		}
		return this;
	},
	
	/**
	 * returns the return fields
	 * @return Array
	 */
	getReturnFields: function() {
		if (this._params.returnFields) {
			return this._params.returnFields;
		}
	},
	
	/**
	 * removes a field name from the list
	 * @param {String} field: field name to remove
	 * @return INTRIGO.SEARCH instance of self
	 */
	removeReturnField: function(field) {
		if (typeof(this._params.returnFields) == 'array' && field) {
			var tmp = [];
			for (var i = 0; i < this._params.returnFields.length; i++) {
				alert(this._params.returnFields[i])
				if (this._params.returnFields[i] != field) {
					tmp[tmp.length] = this._params.returnFields[i];
				}
			}
			this._params.returnFields = tmp;
		}
		return this;
	},
	
	/**
	 * encodes the parameters into a postable string
	 * @return String
	 */
	urlEncode: function() {
		function setString(value) {
			if (value)
				return value;
			else return '';
		};
		var tmp = '';
		var params = this._params;
		
		tmp = "search[field]=" + setString(params.search.field);
		tmp += "&search[value]=" + setString(params.search.value);
		tmp += "&offset=" + setString(params.offset);
		tmp += "&limit=" + setString(params.limit);
		
		if (params.order) {
			tmp += "&order[field]=" + setString(params.order.field);
			tmp += "&order[direction]=" + setString(params.order.direction);
		}
		
		if (typeof(params.returnFields) == 'object') {
			for (var i = 0; i < params.returnFields.length; i++) {
				tmp += "&returnFields[]=" + params.returnFields[i];
			}
		}
		
		if (typeof(params.filters) == 'object') {
			for (var i in params.filters) {
				tmp += "&filters[" + i + "]=" + params.filters[i];
			}
		}
		
		return tmp;
	}
};