bbc.guidance = function() {

	var str = bbc.guidanceLocalisation,
		helper = bbc.helpers,
		callbackId,
		pgForm,
		pgFormWrapper,
		postPath,
		guidanceState,
		skinColour;

	function $(id) { return document.getElementById(id); }

	function formSubmitMsg(el,text,bit) {

		if (text) el.innerHTML = text;
		if (1 & bit || 2 & bit) {
			el.style.display = (1 & bit) ? "block" : "none";
		}

		if (4 & bit) helper.addClass(el,"validate");
		if (8 & bit) helper.removeClass(el,"validate");
	}

	function getCookieStatus() {

		var m = document.cookie.match(/(^|;)\s*BBCPGstat=(.)/);
		return ["","unset","off","on"][(m) ? 1 + (1 * m[2]) : 0] || "unknown";
	}

	function validate() {

		var pass,passMsg;
		if ((/^verify|turnoff$/).test(guidanceState)) {
			pass = $("password"),
			passMsgEl = $("password-label");
		}

		switch (guidanceState) {
			case "verify":
				if (!helper.isStr(pass.value)) {
					formSubmitMsg(passMsgEl,str.enterPass,4);
					pass.focus();
					return;
				}
				break;

			case "turnoff":
				if (!helper.isStr(pass.value)) {
					formSubmitMsg(passMsgEl,str.plsPass,4);
					pass.focus();
					return;
				}
				break;

			case "unknown":
				var checkbox = $("over16"),
					over16Msg = $("over16-label");

				if (!checkbox.checked) {
					formSubmitMsg(over16Msg,str.plsConfOver16,4);
					return;
				}
				break;
		}

		postRequest((pass) ? "password=" + escape(pass.value) : null);
	}

	function getFormContent(name) { return bbc.guidance.forms[name] || ""; }

	function showOverlayForm(html,newGuidanceState) {

		var node = helper.node;
		guidanceState = newGuidanceState;

		// TODO: move node creation to overlay
		if (!pgForm || !pgFormWrapper) {
			pgForm = $("pg-form");
			pgFormWrapper = $("pg-form-wrapper");

			if (!pgForm || !pgFormWrapper) {
				pgFormWrapper = node("div",{"id": "pg-form-wrapper","class": "c"});

				pgForm = node("div",{"id": "pg-form"}, [
					node("div",{"class": "tr"}),
					node("div",{"class": "tl"}),
					node("div",{"class": "tb"}, [
						node("div")
					]),
					node("div",{"class": "tc"},[
						node("div",{"class": "bars"}),
						pgFormWrapper
					]),
					node("div",{"class": "br"}),
					node("div",{"class": "bl"}),
					node("div",{"class": "bb"},[
						node("div")
					])
				]);
			}
		}

		pgFormWrapper.innerHTML = html;
		pgForm.className = skinColour || "black";
		document.body.appendChild(pgForm);

		// fire show form callback
		bbc.guidance.callbacks.showForm();

		if (bbc.guidance.overlay) {
			bbc.guidance.overlay.show(pgForm);
		}

		// focus on required input field
		var el = $((guidanceState == "unknown") ? "over16" : "password");
		// for the Bigscreen site, ensure field hasn't been hidden before calling focus() (this will cause a JS error in IE)
		if(el.className.indexOf("hidden") == -1) {
			window.setTimeout(function() { el.focus(); },100);
		}
		
		// wire up event handlers
		$("pg-form-element").onsubmit = function() { validate(); return false; };
		$("_guidance_cancel_").onclick = function() { hideOverlayForm(); return false; };

		//make sure links to guidance open in popup if need be
		var isPopup = (/emp\/pop/).test(location) || (/iplayer\/console/).test(location);
		if (isPopup) {
			if ($("pgHelpLink")) {
				$("pgHelpLink").onclick = function() { window.open(this.href,"_blank"); return false; };
			}
			if ($("pgSetupLink")) {
				$("pgSetupLink").onclick = function() { window.open(this.href,"_blank"); return false; };
			}
		}
	}

	// hideOverlayForm() returns true if using guidance overlay form popup component and it commenced when called
	function hideOverlayForm() { return (bbc.guidance.overlay && pgForm) ? bbc.guidance.overlay.hide(pgForm) : false; }

	function processResponseOnClose() {

		// detach overlay callback and call processResponse
		bbc.guidance.overlay.closed = false;
		processResponse();
	}

	function processResponse() {

		var cb = bbc.guidance.callbacks;

		switch (guidanceState) {
			case "unknown":
			case "verify":
				cb.pass("passed",callbackId);
				break;

			case "turnoff":
				cb.toggle("off",callbackId);
				break;

			case "turnon":
				cb.toggle("on",callbackId);
				break;
		}
	}

	function processFail() {

		switch (guidanceState) {
			case "unknown":
			case "turnon":
				alert(str.error);
				break;

			case "verify":
			case "turnoff":
				formSubmitMsg($("password-label"),str.reEnter,4);
				$("password").focus();
				break;
		}
	}

	function postRequest(postContent) {

		var requestType = "POST",
			callBacks = {
				ok: function() {

					if (hideOverlayForm()) {
						// setup callback to processResponse() only after overlay fadeout completes
						bbc.guidance.overlay.closed = processResponseOnClose;
						return;
					}

					// call processResponse() right away
					processResponse();
				},
				fail: function() { bbc.guidance.callbacks.fail(); },
				error: function() { alert(str.error); }
			};

		switch (guidanceState) {
			case "verify":
				postPath = "/mediaselector/4/pg/verify";
				break;

			case "turnon":
				postPath = "/mediaselector/4/pg/on";
				requestType = "GET";
				break;

			case "turnoff":
			case "unknown":
				postPath = "/mediaselector/4/pg/off";
				break;
		}

		helper.sendRequest(
			postPath,
			(requestType == "POST") ? (postContent || "empty=value") : null,
			requestType,callBacks
		);
	}

	return {
		status: getCookieStatus,

		verify: function(title,guidance,id,colour) {

			if (id) callbackId = id;
			skinColour = colour;

			switch (getCookieStatus()) {
				case "off":
				case "unset":
					bbc.guidance.callbacks.pass("off",callbackId);
					break;

				case "unknown":
					showOverlayForm(getFormContent("over16").replace("{GUIDANCE}",guidance).replace("{EPISODE_TITLE}",title),"unknown");
					break;

				case "on":
					showOverlayForm(getFormContent("password").replace("{GUIDANCE}",guidance),"verify");
					break;
			}
		},

		toggle: function(id,colour) {

			if (id) callbackId = id;
			skinColour = colour;

			switch (getCookieStatus()) {
				case "on":
					showOverlayForm(getFormContent("turnOff"),"turnoff");
					break;

				case "off":
					guidanceState = "turnon";
					postRequest();
					break;
			}
		},

		gotoGuidance: function() {

			var href = ((/bbc.co.uk/).test(location)) ? "/guidance" : "http://www.bbc.co.uk/guidance",
				isPopup = (/emp\/pop/).test(location) || (/iplayer\/console/).test(location);

			if (isPopup) window.open(href,"_blank");
			else location.href = href;
		},

		callbacks: {
			pass: function() {},
			toggle: function() {},
			showForm: function() {},
			fail: function() { processFail(); }
		}
	};
}();
