<!--//<%

//
//	common server/client code, use this for defining common classes and such
//	note: the browser is sent the contents of this file, no confidential info goes in here at all (passwords, validators, etc.)

redd = {};

//	-----

redd.arrayFind = function (needle, haystack) {
	for (var i = haystack.length; i--;)
		if (haystack[i] == needle)
			return i;
	return null;
};

redd.arrayFindProperty = function (needle, property, haystack) {
	for (var i = haystack.length; i--;)
		if (haystack[i][property] == needle[property])
			return i;
	return null;
};

redd.htmlEncodeMap = {
	34:"&quot;",
	38:"&amp;",
	39:"&#39;",
	60:"&lt;",
	62:"&gt;"
};

redd.htmlEncode = function (input) {
	input = String(input).split("");
	for (var i = input.length; i--;)
	{
		charAt = input[i];
		ascAt = charAt.charCodeAt(0);
		if (redd.htmlEncodeMap[ascAt])
			input[i] = redd.htmlEncodeMap[ascAt];
		else if (ascAt > 126)
			input[i] = "&#"+ ascAt +";";
	}
	input = input.join("");
	return input;
};

redd.trimString = function (str, wh) {
	if(!str.replace){ return str; }
	if(!str.length){ return str; }
	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
	return str.replace(re, "");
};

//	-----

Trusty = {};

Trusty.Consumer = function (id, firstname, surname) {
	this.id = id;
	this.firstname = firstname;
	this.surname = surname;
};

Trusty.SubTrade = function (id, name) {
	this.i = id;
	this.n = name;
};

Trusty.RankCriteria = function (id, name) {
	this.id = id;
	this.name = name;
};

Trusty.SearchResultGroup = function (name, results) {
	this.name = name;
	
	if (typeof results == "undefined")
		this.results = [];
	else
		this.results = results;
};

Trusty.SearchResult = function (id, name, rank, phone, service, ontime, cost, clean, quality, suburb, state, cat, subcat, icons, votes, subcattext) {
	this.i = id?id:0;
	this.n = name?name:"Name";
	this.r = [rank?rank:0, service?service:0, ontime?ontime:0, cost?cost:0, clean?clean:0, quality?quality:0];
	this.p = phone?phone:"Phone";
	this.s = suburb?suburb:"Suburb";
	this.st = state?state:"State";
	this.c = cat?cat:11;
	this.sc = subcat?subcat:null;
	this.sct = subcattext?subcattext:"";
	this.ic = icons?icons:"pm";
	this.v = votes?votes:0;
	
	this._v = true;	// visibile on client-side (used for post-search filtering)
};

Trusty.maxRank = 5;

Trusty.rankCriteriaList = [
	new Trusty.RankCriteria(0, "Overall"),
	new Trusty.RankCriteria(1, "Service"),
	new Trusty.RankCriteria(2, "On Time"),
	new Trusty.RankCriteria(3, "Cost"),
	new Trusty.RankCriteria(4, "Cleanliness"),
	new Trusty.RankCriteria(5, "Quality")
];

Trusty.State = function (id, code, name) {
	this.id = id;
	this.code = code;
	this.name = name;
};

Trusty.stateSortCode = function (a, b) {
	if (a.code > b.code)
		return 1;
	else if (a.code < b.code)
		return -1;
	return 0;
};

Trusty.stateList = [
	new Trusty.State(1, 'ACT', 'Australian Capital Territory'),
	new Trusty.State(2, 'NSW', 'New South Wales'),
	new Trusty.State(3, 'NT', 'Northern Territory'),
	new Trusty.State(4, 'QLD', 'Queensland'),
	new Trusty.State(5, 'SA', 'South Australia'),
	new Trusty.State(6, 'TAS', 'Tasmania'),
	new Trusty.State(7, 'VIC', 'Victoria'),
	new Trusty.State(8, 'WA', 'Western Australia')
];

//	-----

//
//	Third-Party Code

//
//	JSON
//	Dojo defines JSON code on the client but we can't use it (easily) on the server, use this instead

var JSON = function () {
	var m = {
			'\b': '\\b',
			'\t': '\\t',
			'\n': '\\n',
			'\f': '\\f',
			'\r': '\\r',
			'"' : '\\"',
			'\\': '\\\\'
		},
		s = {
			array: function (x) {
				var a = ['['], b, f, i, l = x.length, v;
				for (i = 0; i < l; i += 1) {
					v = x[i];
					f = s[typeof v];
					if (f) {
						v = f(v);
						if (typeof v == 'string') {
							if (b) {
								a[a.length] = ',';
							}
							a[a.length] = v;
							b = true;
						}
					}
				}
				a[a.length] = ']';
				return a.join('');
			},
			'boolean': function (x) {
				return String(x);
			},
			'null': function (x) {
				return "null";
			},
			number: function (x) {
				return isFinite(x) ? String(x) : 'null';
			},
			object: function (x) {
				if (x) {
					if (x instanceof Array) {
						return s.array(x);
					}
					var a = ['{'], b, f, i, v;
					for (i in x) {
						if (!x.hasOwnProperty || x.hasOwnProperty(i)) {
							v = x[i];
							f = s[typeof v];
							if (f) {
								v = f(v);
								if (typeof v == 'string') {
									if (b) {
										a[a.length] = ',';
									}
									a.push(s.string(i), ':', v);
									b = true;
								}
							}
						}
					}
					a[a.length] = '}';
					return a.join('');
				}
				return 'null';
			},
			string: function (x) {
				if (/["\\\x00-\x1f]/.test(x)) {
					x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
						var c = m[b];
						if (c) {
							return c;
						}
						c = b.charCodeAt();
						return '\\u00' +
							Math.floor(c / 16).toString(16) +
							(c % 16).toString(16);
					});
				}
				return '"' + x + '"';
			}
		};
	return {
/*
	Stringify a JavaScript value, producing a JSON text.
*/
		stringify: function (v) {
			var f = s[typeof v];
			if (f) {
				v = f(v);
				if (typeof v === 'string') {
					return v;
				}
			}
			return;
		},
/*
	Parse a JSON text, producing a JavaScript value.
	It returns false if there is a syntax error.
*/
		parse: function (text) {
			try {
				return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
						text.replace(/"(\\.|[^"\\])*"/g, ''))) && //"
					eval('(' + text + ')');
			} catch (e) {
				return false;
			}
		}
	};
}();

function encodeBase64String (input)
{
	var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

	var input = String(input);
	var output = "";
	var chr1, chr2, chr3 = "";
	var enc1, enc2, enc3, enc4 = "";
	var i = 0;

	do
	{
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);

		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;

		if (isNaN(chr2))
			enc3 = enc4 = 64;
		else if (isNaN(chr3))
		enc4 = 64;

		output = output + 
		keyStr.charAt(enc1) + 
		keyStr.charAt(enc2) + 
		keyStr.charAt(enc3) + 
		keyStr.charAt(enc4);
		chr1 = chr2 = chr3 = "";
		enc1 = enc2 = enc3 = enc4 = "";
	} while (i < input.length);

	return output;
}

function decodeBase64String (input)
{
	var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

	var input = String(input);
	var output = "";
	var chr1, chr2, chr3 = "";
	var enc1, enc2, enc3, enc4 = "";
	var i = 0;

	// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
	input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

	do
	{
		enc1 = keyStr.indexOf(input.charAt(i++));
		enc2 = keyStr.indexOf(input.charAt(i++));
		enc3 = keyStr.indexOf(input.charAt(i++));
		enc4 = keyStr.indexOf(input.charAt(i++));

		chr1 = (enc1 << 2) | (enc2 >> 4);
		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
		chr3 = ((enc3 & 3) << 6) | enc4;

		output = output + String.fromCharCode(chr1);

		if (enc3 != 64)
			output = output + String.fromCharCode(chr2);
		if (enc4 != 64)
			output = output + String.fromCharCode(chr3);

		chr1 = chr2 = chr3 = "";
		enc1 = enc2 = enc3 = enc4 = "";

	} while (i < input.length);

	return output;
}

//%>-->
