if (!window['VTLS']) window['VTLS'] = {};
VTLS.Find = {
	'results' : [],
	'results_count' : 0,
	'results_shown' : 0,
	'render' : null,
	'pager' : null,
	'sort_type' : null,
	'events' : {
		'afterFilter' : [],
		'afterRank' : [],
		'beforeRequest' : [],
		'onError' : [],
		'onResults' : [],
		'onRefresh' : [],
		'onPrefLoad' : []
	},
	'slider' : {
		'training' : 0,
		'hospital' : 0,
		'experience' : 0,
		'distance' : 0
	},
	'filter' : {
		'abms' : false,
		'disc' : false,
		'poor' : false,
		'male' : false,
		'female' : false,
		'mdd' : false,
		'dod' : false,
		'usedu' : false,
		'lang' : false
	},
	'request' : function(frm) {
		this.raise('beforeRequest', frm);
		VTLS.XHR.request(frm, null, this.response, this);
	},
	'response' : function(rs, is_restore) {
		if (typeof rs != 'object') {
			this.raise('onError', 'An unexpected error occurred. Please try again later.');
		}
		else if (rs.error) {
			this.raise('onError', rs.error);
		}
		else if (rs.results) {
			var note = (rs.note ? rs.note : null);
			rs = rs.results;
			this.results = rs;
			if (!is_restore) this.cache(rs);
			this.results_count = rs.length;
			this.augment();
			this.raise('onResults', rs, note);
			this.refresh();
		}
	},
	'augment' : function() {
		var r, a, i, j, l, speca, specn, s, c;
		for (i = 0; i < this.results_count; i++) {
			r = this.results[i];
			if (r._promo) continue;
			r.i = i;
			r.score = null;
			if (r.master_id && r.master_name) r.profile_uri = 'doctor/profile/' + r.master_id + '/' + r.master_name;
			r.highlight = r.highlight ? r.highlight.split(',') : [];
			if (r.display_title.length < 1 && r.abms_titles.length > 0) {
				a = r.abms_titles;
				a = a.split(';');
				speca = []; specn = [];
				for (j = 0, l = a.length; j < l; j++) {
					c = a[j].charAt(0);
					s = a[j].substring(1);
					if (c == '@') speca.push(s);
					else specn.push(s);
				}
				r.display_title = speca.length ? speca.join(', ') : (specn.length ? specn.join(', ') : '');
			}
			delete r.abms_titles;
		}
	},
	'sift' : function() {
		var n = 0, n_nonpromo = 0;
		var vis, anyfilters = false;
		for (var i = 0; i < this.results_count; i++) {
			vis = true;
			if (!this.results[i]._promo) do {
				if (this.filter.male && this.results[i].gender != 'M') { vis = false; break; }
				if (this.filter.female && this.results[i].gender != 'F') { vis = false; break; }
				if (this.filter.abms && this.results[i].is_board_certified == 'N') { vis = false; break; }
				if (this.filter.usedu && this.results[i].is_us_educated != 'Y') { vis = false; break; }
				if (this.filter.lang && this.filter.lang != '' && this.results[i].languages.toLowerCase().indexOf(this.filter.lang.toLowerCase()) == -1 ) { vis = false; break; }
				if (this.filter.poor && this.results[i].has_negative_reviews == 'Y') { vis = false; break; }
				if (this.filter.disc && this.results[i].is_disciplined != 'N') { vis = false; break; }
				if (this.filter.mdd && this.results[i].degree_type != 'M' && this.results[i].degree_type != 'B') { vis = false; break; }
				if (this.filter.dod && this.results[i].degree_type != 'D' && this.results[i].degree_type != 'B') { vis = false; break; }
			} while (false);
			if (vis) n++;
			if (vis && !this.results[i]._promo) n_nonpromo++;
			this.results[i].visible = vis;
		}
		if (n != this.results_count || n_nonpromo < 7) for (var i = 0; i < this.results_count; i++) {
			if (this.results[i]._promo) {
				this.results[i].visible = false;
				n--;
			}
		}
		for (var i = 0; i < this.results_count; i++) {
			if (this.results[i]._promo && this.results[i].pos == 0 && !this.results[i].visible) {
				this.results[i].visible = true;
				n++;
			}
		}
		this.page.count = Math.ceil(n / this.page.per);
		this.page.current = 0;
		this.results_shown = n;
		this.raise('afterFilter', this.results, n);
		this.paginate();
	},
	'rank' : function() {
		var s_trng_val = this.slider.training;
		var s_hosp_val = this.slider.hospital;
		var s_expn_val = this.slider.experience;
		var s_dist_val = this.slider.distance;
		var s_lo = Math.min(s_trng_val, s_hosp_val, s_expn_val, s_dist_val);
		var s_lo_n = s_lo * -1;
		var s_hi = Math.max(s_trng_val, s_hosp_val, s_expn_val, s_dist_val);
		var s_range = s_hi - s_lo;
		if (s_range > 0) {
			s_trng_val = ((s_trng_val + s_lo_n) / (s_range)) * 4;
			s_hosp_val = ((s_hosp_val + s_lo_n) / (s_range)) * 4;
			s_expn_val = ((s_expn_val + s_lo_n) / (s_range)) * 4;
			s_dist_val = ((s_dist_val + s_lo_n) / (s_range)) * 4;
			var s_sum = s_trng_val + s_hosp_val + s_expn_val + s_dist_val;
			var max_affect = 36 + 36 * (s_range / 4) ;
			var max_score = 97;
			var s_trng_wt = (s_trng_val / s_sum) * max_affect;
			var s_hosp_wt = (s_hosp_val / s_sum) * max_affect;
			var s_expn_wt = (s_expn_val / s_sum) * max_affect;
			var s_dist_wt = (s_dist_val / s_sum) * max_affect;
		}
		var strongc = 0;
		var provider;
		
		for (var i = 0; i < this.results_count; i++) {
			provider = this.results[i];
			provider.score = null;
			if (s_range < 1 || provider._promo) continue;
			provider.score = Math.round(max_score - (
				  s_trng_wt * (((provider.quality_training ? Math.max(Math.min(+provider.quality_training, 4), 1) : 1) - 4) / -3)
				+ s_hosp_wt * (((provider.quality_hospital ? Math.max(Math.min(+provider.quality_hospital, 4), 1) : 1) - 4) / -3)
				+ s_expn_wt * this.rank_exp_gradient(provider.experience ? Math.max(Math.min(+provider.experience, 50), 0) : 0)
				+ s_dist_wt * ((provider.distance ? Math.max(Math.min(+provider.distance, 30), 0) : 30) / 30)
			));
			if (provider.score >= 70 && provider.visible) strongc++;
		}
		this.raise('afterRank', strongc);
	},
	'rank_played' : function() {
		return (this.slider.distance || this.slider.experience || this.slider.training || this.slider.hospital);
	},
	'rank_exp_gradient' : function (exp) {
		if (exp >= 15 && exp <= 35) return 0;
		else if (exp < 15) return (15 - exp) / 15;
		else return (exp - 35) / 15;
	},
	'rank_distance_gradient' : function(distance) {
		return distance / 30;
	},
	'sort' : function() {
		switch (this.sort_type) {
			case 'name':
				this.results.sort(function(a, b) {
					if (a._promo) return -1;
					if (b._promo) return 1;
					return (b.last_name < a.last_name) - (a.last_name < b.last_name); 
				});
				break;
			case 'distance':
			default:
				this.results.sort(function(a, b) {
					if (a._promo) return -1;
					if (b._promo) return 1;
					return (a.distance - b.distance);
				});
				break;
			case 'score':
				this.results.sort(function(a, b) {
					if (a._promo) return -1;
					if (b._promo) return 1;
					return (b.score - a.score);
				});
				break;
		}
		var tmp = [];
		for (var i = 0; i < this.results_count; i++) {
			var sfound = false;
			for (var j = 0; j < this.results_count; j++) {
				var s = this.results[j];
				if (s._promo && s.hasOwnProperty('pos') && s.pos == i) { tmp.push(s); sfound = true; break; }
			}
			if (!sfound) for (var j = 0; j < this.results_count; j++) {
				var s = this.results[j];
				if (!s._promo && !s._added) { s._added = 1; tmp.push(s); break; }
			}
		}
		for (var i = 0; i < this.results_count; i++) if (tmp[i].hasOwnProperty('_added')) delete tmp[i]._added;
		this.results = tmp;
	},
	'display' : function() {
		var shown = [];
		var per = this.page.per;
		var m = per * this.page.current;
		for (var i = 0; i < this.results_count; i++) if (this.results[i].visible) {
			if (m > 0) {
				 m--;
			}
			else if (per > 0) {
				shown.push(this.results[i]);
				per--;
			}
			else {
				break;
			}
		}
		this.paginate();
		this.render.call(this, shown);
	},
	'refresh' : function() {
		this.sift();
		this.rank();
		this.sort();
		this.raise('onRefresh');
		this.pref_save();
		this.display();
	},
	'paginate' : function() {
		var n = this.results_shown;
		var lo = (this.page.current * this.page.per) + 1;
		this.pager.call(this, this.page.count, lo, Math.min(lo + (this.page.per - 1), n), n);
	},
	'page' : {
		'per' : 8,
		'current' : 0,
		'count' : 0,
		'prev' : function() {
			if (this.current > 0) this.current--;
			VTLS.Find.display();
		},
		'next' : function() {
			if (this.current < this.count - 1) this.current++;
			VTLS.Find.display();
		},
		'first' : function() {
			this.current = 0;
			VTLS.Find.display();
		},
		'last' : function() {
			this.current = this.count - 1;
			VTLS.Find.display();
		},
		'goto' : function(p) {
			this.current = Math.max(0, Math.min(p, this.count - 1));
			VTLS.Find.display();
		}
	},
	'filter_summary' : function () {
		var summary = '';
		if (this.filter.male) summary += '<b>Males</b>, ';
		if (this.filter.female) summary += '<b>Females</b>, ';
		if (this.filter.abms) summary += '<b>ABMS certified</b>, ';
		if (this.filter.usedu) summary += '<b>U.S. educated</b>, ';
		if (this.filter.lang) summary += '<b>' + this.filter.lang + ' speaking</b>, ';
		if (this.filter.poor) summary += '<b>Reviewed positively</b>, ';
		if (this.filter.disc) summary += '<b>Not disciplined</b>, ';
		if (this.filter.mdd) summary += '<b>MDs</b>, ';
		if (this.filter.dod) summary += '<b>DOs</b>, ';
		if (summary.length > 1) summary = summary.substr(0, summary.length - 2);
		return summary;
	},
	'compare' : function(ii, imgid) {	
		var r, ci;
		for (var i = 0; i < this.results_count; i++) {
			r = this.results[i];
			if (r.i != ii) continue;
			ci = VTLS.Compare.inlist(r);
			if (ci === false) VTLS.Compare.add(r)
			else VTLS.Compare.remove(ci);
			break;
		}
	},
	'cache' : function(rs) {
	},
	'restore' : function(rs) {
	},
	'pref_save' : function() {
		var data = [];
		data.push(this.sort_type);
		data.push(this.slider.training);
		data.push(this.slider.hospital);
		data.push(this.slider.experience);
		data.push(this.slider.distance);
		data.push(this.filter.abms ? 1 : 0);
		data.push(this.filter.disc ? 1 : 0);
		data.push(this.filter.poor ? 1 : 0);
		data.push(this.filter.male ? 1 : 0);
		data.push(this.filter.female ? 1 : 0);
		data.push(this.filter.mdd ? 1 : 0);
		data.push(this.filter.dod ? 1 : 0);
		data.push(this.filter.usedu ? 1 : 0);
		data.push(this.filter.lang ? this.filter.lang : '');
		data = data.join(',');
		qookie.create('find_pref', data, 1);	
	},
	'pref_load' : function() {
		var data = decodeURIComponent(qookie.read('find_pref'));
		if (!data) return;
		var p = 0;
		data = data.split(',');
		this.sort_type = data[p++];
		this.slider.training = +data[p++];
		this.slider.hospital = +data[p++];
		this.slider.experience = +data[p++];
		this.slider.distance = +data[p++];
		this.filter.abms = +data[p++] ? true : false;
		this.filter.disc = +data[p++] ? true : false;
		this.filter.poor = +data[p++] ? true : false;
		this.filter.male = +data[p++] ? true : false;
		this.filter.female = +data[p++] ? true : false;
		this.filter.mdd = +data[p++] ? true : false;
		this.filter.dod = +data[p++] ? true : false;
		this.filter.usedu = +data[p++] ? true : false;
		this.filter.lang = data[p++];
		if (this.filter.lang == '') this.filter.lang = false;
		this.raise('onPrefLoad');
	},
	'subscribe' : function(ev, fn) {
		if (!this.events.hasOwnProperty(ev)
		||   typeof fn != 'function') return;
		this.events[ev].push(fn);
	},
	'raise' : function(ev) {
		if (!this.events.hasOwnProperty(ev)) return;
		var args = [];
		for (var i = 1, l = arguments.length; i < l; i++)
			args.push(arguments[i]);
		for (var i = 0, l = this.events[ev].length; i < l; i++)
			this.events[ev][i].apply(this, args);
	}
};
