/*jslint browser: true, eqeqeq: true, undef: true */
/*global $ */
/******************************************************************************
Lines above are for jslint, the JavaScript verifier.
http://www.jslint.com/
******************************************************************************/

$.extend({
	text: function (s) {
		return $(document.createTextNode(s));
	}
});

var ESCO = {
	states: [
		"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC",
		"FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY",
		"LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT",
		"NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH",
		"OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT",
		"VT", "VA", "WA", "WV", "WI", "WY"
	],
	initDataByState: function () {
		if (this.dataByState) {
			return;
		}
		this.dataByState = {};
		this.data.forEach(function (item) {
			var states_served = item.states_served;
			var physical_locations = item.physical_locations;
			if (states_served.constructor === Array) {
				item.states_served_hash = {};
				states_served.forEach(function (state) {
					item.states_served_hash[state] = true;
				});
			}
			if (physical_locations.constructor === Array) {
				item.physical_locations_hash = {};
				physical_locations.forEach(function (state) {
					item.physical_locations_hash[state] = true;
				});
			}
		}, this);
		this.states.forEach(function (state) {
			var all = this.data.filter(function (item) {
				return (item.states_served === true ||
					(state in item.states_served_hash));
			}).sort(this.sortByProvider);
			var inState = all.filter(function (item) {
				return (state in item.physical_locations_hash);
			});
			var outOfState = all.filter(function (item) {
				return !(state in item.physical_locations_hash);
			});
			this.dataByState[state] = {
				"inState": inState,
				"outOfState": outOfState,
				"all": all
			};
		}, this);
	},
	sortByProvider: function (a, b) {
		return a.company_name.localeCompare(b.company_name);
	},
	initStateSelectorDropdown: function () {
		var that = this;
		$("#stateSelectorDropdown").unbind("change").change(function () {
			var state = $(this).val();
			that.updateState(state);
		}).change(/* trigger */);
	},
	updateState: function (state) {
		this.$providers.empty();
		if (!(state in this.dataByState) ||
		    this.dataByState[state].constructor !== Object) {
			return;
		}
		var dataByState = this.dataByState[state];
		var inState = dataByState.inState;
		var outOfState = dataByState.outOfState;

		if (inState.length > 0) {
			inState.forEach(function (provider) {
				this.appendProvider(provider);
			}, this);
		}
		else {
			this.appendMessageNoInStateProviders();
		}
		
		if (outOfState.length > 0) {
			this.appendMessageOutOfStateProviders();
			outOfState.forEach(function (provider) {
				this.appendProvider(provider);
			}, this);
		}
	},
	appendMessageNoInStateProviders: function () {
		this.$providers.append($("<p class='highlight' style='font-weight: bold;'></p>").
				       text("There are no ESCO Service Providers located in this state."));
	},
	appendMessageOutOfStateProviders: function () {
		var $div = $("<div style='margin: 1.5em 0;'></div>");
		$div.append($("<h2></h2>").text("Additional ESCO\u2019s that provide services in your state"));
		$div.append($("<p class='tight'></p>").text("The following ESCO\u2019s provide services in your state, however their main office may not be located in your area. Please refer to each provider\u2019s information for actual geographical coverage."));
		this.$providers.append($div);
	},
	appendProvider: function (provider) {
		var $provider = $("<div class='escoProvider'></div>");
		var $leftColumn = $("<div class='leftColumn'></div>");
		var $rightColumn = $("<div class='rightColumn'></div>");
		var $info = $("<div class='escoProviderInfo'></div>");
		var $toggle = $("<div class='escoProviderToggle'></div>");
		var $contact = $("<div class='escoProviderContact'></div>");
		var $serving = $("<div class='escoProviderServing'></div>");
		var $services = $("<div class='escoProviderServices'></div>");
		
		this.populateProviderInfo($info, provider);
		$leftColumn.append($info);
		this.populateProviderToggle($toggle, $services, provider);
		$leftColumn.append($toggle);

		this.populateProviderContact($contact, provider);
		$rightColumn.append($contact);
		this.populateProviderServing($serving, provider);
		$rightColumn.append($serving);

		this.populateProviderServices($services, provider);

		$provider.append($leftColumn);
		$provider.append($rightColumn);
		$provider.append($("<div style='clear: both;'></div>"));
		$provider.append($services);

		this.$providers.append($provider);
	},
	populateProviderInfo: function ($info, provider) {
		$info.append($("<h3></h3>").
			     append($("<a></a>").
				    attr("href", provider.web_link).
				    attr("target", "_blank").
				    text(provider.company_name)));
	},
	populateProviderToggle: function ($toggle, $services, provider) {
		var $p = $("<p></p>");
		var $a = $("<a href='#'></a>");
		var hidden = true;
		var hideServices = function () {
			hidden = true;
			$services.hide();
			$a.text("Show ESCO Services");
			$toggle.removeClass("escoProviderToggleExpanded");
			$toggle.addClass("escoProviderToggleCollapsed");
		};
		var showServices = function () {
			hidden = false;
			$services.show();
			$a.text("Hide ESCO Services");
			$toggle.removeClass("escoProviderToggleCollapsed");
			$toggle.addClass("escoProviderToggleExpanded");
		};
		var toggle = function () {
			if (hidden) {
				showServices();
			}
			else {
				hideServices();
			}
			return false;
		};
		hideServices();
		$a.unbind("click").click(toggle);
		$toggle.append($p.append($a));
	},
	populateProviderContact: function ($contact, provider) {
		var $div = $("<div class='tanRoundedBox'></div>");
		var $p = $("<p>");
		if (provider.contact_name) {
			$p.append($.text(provider.contact_name)).append("<br />");
		}
		$p.append($.text(provider.contact_telephone_number));
		$div.append($("<h4>Contact</h4>"));
		$div.append($p);
		$contact.append($div);
	},
	populateProviderServing: function ($serving, provider) {
		var $p = $("<p></p>");
		if (provider.states_served === true) {
			$p.html("<b>Serving all states</b>");
		}
		else {
			$p.html("<b>Serving the following states:</b> " +
				provider.states_served.join(", "));
		}
		$serving.append($p);
	},
	populateProviderServices: function ($services, provider) {
		$services.append("<h4>ESCO Services</h4>");
		provider.service_categories.forEach(function (category) {
			this.appendProviderServiceCategory($services, category);
		}, this);
		$services.append($("<div style='clear: both;'></div>"));
	},
	appendProviderServiceCategory: function ($services, category) {
		var $category = $("<div class='escoProviderServicesCategory'></div>");
		$category.append($("<h5></h5>").text(category.name));
		if (category.services.length) {
			var $ul = $("<ul></ul>");
			category.services.forEach(function (service) {
				$ul.append($("<li></li>").text(service));
			}, this);
			$category.append($ul);
		}
		else {
			$category.append($("<p>No services provided.</p>"));
		}
		$services.append($category);
	},
	init: function () {
		this.$providers = $("#escoProviders");
		this.$providers.empty();

		this.$errorArea = $("<div class='errorArea'></div>");
		this.$providers.append(this.$errorArea);

		this.initDataByState();
		this.initStateSelectorDropdown();
	}
};

$(document).ready(function () {
	ESCO.init();
});


