if (typeof(poller) != "object" || poller == null) {
	var poller = {
		_mode: 'today', // or 'yesterday'

		_pollLoaded: false,

		_formBox: null,

		_pollId: null,

		_prevPollId: null,

		_curPollInfo: null,

		onload: function() {
			// get the uid to give credit for the poll
			var getVars = parseGetVars(window.location.href);

			this._uid = (getVars.uid != undefined? getVars.uid: '0');

			this._formBox = YAHOO.util.Dom.get('formbox');
			this._getCurrentPoll();

			this._mode = 'today';

			this._showYesterdayLinkIfAppropriate();
		},

		onunload: function() {
			if (this._getCurrentAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._getCurrentAjaxRequest);
				this._getCurrentAjaxRequest = null;
			}

			if (this._submitPollAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._submitPollAjaxRequest);
				this._submitPollAjaxRequest = null;
			}

			if (this._getPollResultAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._getPollResultAjaxRequest);
				this._getPollResultAjaxRequest = null;
			}
		},

		_showYesterdayLinkIfAppropriate: function() {
			if (this.getUserGuid() != null)  {
				// voter is logged in
				this.showYesterdayLink(true);
			} else {
				// voter is not logged in
				this.showYesterdayLink(false);
			}
		},

		/**
		 * Returns the user GUID if logged in, or null if not
		 */
		getUserGuid: function() {
			return YAHOO.util.Cookie.get("userguid");
		},

		getLastPollTaken: function() {
			return YAHOO.util.Cookie.get("lastpolltaken");
		},

		setLastPollTaken: function(pollId) {
			var myDate=new Date(); 
			myDate.setDate(myDate.getDate()+30); // 30 days in future
			// expiration doesn't matter, as long as another poll comes
			// along before the expiration date.
																	 
			YAHOO.util.Cookie.set("lastpolltaken", pollId, { expires: myDate });
		},

		/**
		 * switches mode from question to result
		 * 0=nothing 1=questions 2=result
		 */
		showPanel: function(num) {
			var bpanel = YAHOO.util.Dom.get('pollblank');
			var qpanel = YAHOO.util.Dom.get('pollquestions');
			var rpanel = YAHOO.util.Dom.get('pollresults');

			switch(num) {
			case 0:
				YAHOO.util.Dom.removeClass(bpanel, 'hidden');
				YAHOO.util.Dom.addClass(qpanel, 'hidden');
				YAHOO.util.Dom.addClass(rpanel, 'hidden');
				break;
			case 1:
				YAHOO.util.Dom.addClass(bpanel, 'hidden');
				YAHOO.util.Dom.removeClass(qpanel, 'hidden');
				YAHOO.util.Dom.addClass(rpanel, 'hidden');
				break;
			case 2:
				YAHOO.util.Dom.addClass(bpanel, 'hidden');
				YAHOO.util.Dom.addClass(qpanel, 'hidden');
				YAHOO.util.Dom.removeClass(rpanel, 'hidden');
				break;
			}
		},

		showYesterdayLink: function(show) {
			var ylink = YAHOO.util.Dom.get('seeyesterdaylink');
			var jlink = YAHOO.util.Dom.get('joinrtwlink');

			var yrlink = YAHOO.util.Dom.get('togglelinkres');
			var jrlink = YAHOO.util.Dom.get('joinrtwlinkres');

			if (show) {
				// main page
				YAHOO.util.Dom.addClass(jlink, 'hidden');
				YAHOO.util.Dom.removeClass(ylink, 'hidden');

				// results page
				YAHOO.util.Dom.replaceClass(yrlink, "hidden", "resultsbottomtext");
				YAHOO.util.Dom.replaceClass(jrlink, "resultsbottomtext", "hidden");
			} else {
				// main page
				YAHOO.util.Dom.addClass(ylink, 'hidden');
				YAHOO.util.Dom.removeClass(jlink, 'hidden');

				// results page
				YAHOO.util.Dom.replaceClass(yrlink, "resultsbottomtext", "hidden");
				YAHOO.util.Dom.replaceClass(jrlink, "hidden", "resultsbottomtext");
			}
		},

		/**
		 * ajax stuff for getting the poll
		 */
		_getCurrentAjaxRequest: null,

		_getCurrentSuccess: function(o) {
			var lastPollTaken = this.getLastPollTaken();

			this._getCurrentAjaxRequest = null;

			//alert("CURRENT: " + o.responseText);
			this._curPollInfo = o.responseXML.documentElement;
			this._pollId = getFirstChildNodeValue(this._curPollInfo.getElementsByTagName('Id'));
			var prevNode = this._curPollInfo.getElementsByTagName('PreviousPollId')[0];
			if (prevNode == undefined) {
				this._prevPollId = this._pollId;
			} else {
				this._prevPollId = prevNode.firstChild.nodeValue;
				if (this._prevPollId == '0') {
					this._prevPollId = this._pollId; // What if there is no tomorrow?  There wasn't one today!
				}
			}

			//alert("ID: " + this._pollId);
			//alert("Prev ID: " + this._prevPollId);
			var guid = this.getUserGuid();
			if (guid != null) {
				// don't trust the cookie--we might have taken the poll
				// when we were anon
				this.checkIfUserHasVoted(guid);
				return;

			} else if (this._pollId == lastPollTaken) {
				//show the results
				this.getPollResult();
				return;
			}

			this._showQuestions();
		},

		_showQuestions: function() {
			this.showPanel(1);

			this._showYesterdayLinkIfAppropriate();

			var pollQuestion = getFirstChildNodeValue(this._curPollInfo.getElementsByTagName('PollQuestion'));
			var answers = this._curPollInfo.getElementsByTagName('PollAnswer');

			setInnerHtml('pollquestion', pollQuestion);

			var formstr = '<form class="pollform" id="pollradio">';

			for(var i = 0; i < answers.length; i++) {
				var innerId = getFirstChildNodeValue(answers[i].getElementsByTagName('Id'));
				var answer = getFirstChildNodeValue(answers[i].getElementsByTagName('Answer'));

				formstr += '<div class="fullquestion"><input type="radio" name="poll" value="' + innerId +
					'" class="pollradioinput">&nbsp;' + answer + "</input></div>";
			}

			formstr += '</form>';

			this._formBox.innerHTML = formstr;

			this._pollLoaded = true;
		},

		_getCurrentFailure: function(o) {
			this._getCurrentAjaxRequest = null;
			this._submitPollAjaxRequest = null; // uses this callback, as well
			this._getPollResultAjaxRequest = null; // uses this callback, as well

			if (!alertOnFault(o.responseXML.documentElement)) {
				alert("HTTP error: " + o.status + ' ' + o.statusText);
			}
		},

		_getCurrentPoll: function() {
			if (this._getCurrentAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._getCurrentAjaxRequest);
			}

			var soapXMLStr = buildSOAPXMLStr('GetCurrentPoll', '');

			YAHOO.util.Connect.setDefaultPostHeader('text/xml; charset=utf-8'); // SOAP 1.1
			YAHOO.util.Connect.initHeader('SOAPAction', '"' + _SOAP_namespace + 'GetCurrentPoll"'); // SOAP 1.1
			//YAHOO.util.Connect.setDefaultPostHeader('application/soap+xml; charset=utf-8'); // SOAP 1.2

			this._getCurrentAjaxRequest = YAHOO.util.Connect.asyncRequest('POST', SOAP_URL, poller_getCurrentCallback, soapXMLStr);
		},

		/**
		 * Ajax stuff for submitting the poll.
		 */
		_submitPollAjaxRequest: null,

		_submitPollSuccess: function(o) {
			this._submitPollAjaxRequest = null;

			this.setLastPollTaken(this._pollId);

			this.getPollResult();
		},

		submitPoll: function() {
			if (!this._pollLoaded) { return; }

			if (this._submitPollAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._submitPollAjaxRequest);
			}

			var guid = this.getUserGuid();
			if (guid == null) {
				guid = 'none';
			}

			form = YAHOO.util.Dom.get('pollradio');
			var answer = null;
			for(var i = 0; i < form.poll.length; i++) {
				if (form.poll[i].checked) {
					answer = form.poll[i].value;
					//alert("value: " + answer);
					break;
				}
			}

			if (answer == null) { return; } // gotta choose something

			var soapXMLStr = buildSOAPXMLStr('VoteForPollAnswer', 
				'<userGuid>' + guid + '</userGuid>' +
				'<hostId>' + this._uid + '</hostId>' + 
				//'<hostUserGuid>none</hostUserGuid>' + 
				'<pollAnswerId>' + answer + '</pollAnswerId>' +
				'<pollId>' + this._pollId + '</pollId>');

			YAHOO.util.Connect.setDefaultPostHeader('text/xml; charset=utf-8'); // SOAP 1.1
			YAHOO.util.Connect.initHeader('SOAPAction', '"' + _SOAP_namespace + 'VoteForPollAnswer"'); // SOAP 1.1
			//YAHOO.util.Connect.setDefaultPostHeader('application/soap+xml; charset=utf-8'); // SOAP 1.2

			this._submitPollAjaxRequest = YAHOO.util.Connect.asyncRequest('POST', SOAP_URL, poller_submitPollCallback, soapXMLStr);
		},

		/**
		 * Ajax stuff for getting the poll result
		 */
		_getPollResultAjaxRequest: null,

		_setGraphImgWidths: function() {
			var e = document.getElementById('resultsbox');
			var maxWidth = e.offsetWidth;

			imgList = e.getElementsByTagName('img');

			var w1 = (document.getElementById('pollresultscol1')).offsetWidth;
			var w2 = (document.getElementById('pollresultscol2')).offsetWidth;
			maxWidth -= (w1 + w2);
			maxWidth -= 30; // subtract off endcaps, fudge

			for(var i = 0; i < imgList.length; i++) {
				var img = imgList[i];
				var name = img.getAttribute('name');

				if (name == 'fronting' || name == 'backing') {
					//beejjs.debug.write("width was: " + img.offsetWidth);
					img.width = img.offsetWidth * maxWidth / 100;
					//beejjs.debug.write("setting to: " + img.offsetWidth * maxWidth / 100);
					//beejjs.debug.write("width now: " + img.width);
					img.height = 12;
				}
			}
		},

		_getPollResultSuccess: function(o) {
			this.showPanel(2);

			this._showYesterdayLinkIfAppropriate();

			this._getPollResultAjaxRequest = null;

			//alert("results success: " + o.responseText);
			var doc = o.responseXML.documentElement;
			var pollQuestion = getFirstChildNodeValue(doc.getElementsByTagName('PollQuestion'));

			if (pollQuestion == '') {
				setInnerHtml('pollresultquestion', 'Empty poll question');
				setInnerHtml('resultsbox', '');
			} else {

				// we're in business

				var answers = doc.getElementsByTagName('PollAnswer');

				var e = YAHOO.util.Dom.get('pollresultquestion');
				setInnerHtml('pollresultquestion', pollQuestion);

				// pass 0--get total votes
				var totalVotes = 0;
				for(var i = 0; i < answers.length; i++) {
					var votes = getFirstChildNodeValue(answers[i].getElementsByTagName('Votes'));
					totalVotes += parseInt(votes);
				}

				// display, using 100 as the pixel width for 100% of votes
				var htmlStr = '<table class="pollresultstable"><tbody>';

				var id1 = 'id="pollresultscol1"';
				var id2 = 'id="pollresultscol2"';
				var id3 = 'id="pollresultscol3"';

				for(var i = 0; i < answers.length; i++) {
					var answer = getFirstChildNodeValue(answers[i].getElementsByTagName('Answer'));
					var votes = getFirstChildNodeValue(answers[i].getElementsByTagName('Votes'));
					votes = parseInt(votes);
					var percent = parseInt(100 * votes / totalVotes);

					answer = answer.replace(/ /g, '&nbsp;');
					// this is a KLUDGE HACK that should be removed
					var commaIndex = answer.indexOf(',');
					if (commaIndex != -1) { answer = answer.slice(0, commaIndex); }

					htmlStr += '<tr><td ' + id1 + ' class="percentcol">' +
						beejjs.util.leadingZeroPad('' + percent, 2) + '%</td>';

					htmlStr += '<td ' + id2 + ' class="answercol">' +
						answer + '</td>';

					htmlStr += '<td ' + id2 + ' class="graphcol">' +
						'<div class="graphbacking">' +
							'<nobr><img src="img/pollbl.png"></img><img name="backing" src="img/pollbc.png" width="100" height="12"></img><img src="img/pollbr.png"></img></nobr>';
					if (percent > 0) {
						htmlStr += '<div class="graphfronting">' +
								'<nobr><img src="img/pollfl.png"></img><img name="fronting" src="img/pollfc.png" width="' + percent + '" height="12"></img><img src="img/pollfr.gif"></img></nobr>';
							'</div>';
					}
					htmlStr += '</div></td></tr>';

					id1 = id2 = id3 = ''; // only need ids on first row
				}

				htmlStr += '</tbody></table>';

				//beejjs.debug.write(htmlStr);
				setInnerHtml('resultsbox', htmlStr);

				// ok now that we're all set up, we need to grow the percent
				// column to the width of the parent container to make it
				// look all big:
				this._setGraphImgWidths();
				
				// finally, attempt to tell the parent window that we've taken the
				// poll--this only works if we're on the main site
				if (parent.goldMgr != undefined && parent.goldMgr.refreshGoldAmounts != undefined) {
					parent.goldMgr.refreshGoldAmounts();
				}
			}

			switch(this._mode) {
				case 'today':
					this._setPollResInnerHtml('See yesterday\'s poll result');
					break;
				default:
					this._setPollResInnerHtml('Back to today\'s poll');
					break;
			}
		},

		_setPollResInnerHtml: function(s) {
			var e = YAHOO.util.Dom.get('pollresday');
			if (e != null) {
				e.innerHTML = s;
			}
		},

		setRefCookie: function() {
			if (this._uid != 0) {
				// keep the poll owner as a referrer... this will be
				// picked up later by userMgr when the user registers
				var myDate = new Date(); 
				myDate.setDate(myDate.getDate()+30); // 30 days in future
				YAHOO.util.Cookie.set("pollreferrer", this._uid, { expires: myDate });
			}
		},

		toggleResultsViewMode: function() {
			switch(this._mode) {
				case 'today':
					this._mode = 'yesterday';
					break;
				default:
					this._mode = 'today';
					break;
			}

			this._setPollResInnerHtml('Loading...');

			this.getPollResult();
		},

		getYesterdaysPollResult: function() {
			this._mode = 'yesterday';
			this.getPollResult();
		},

		getPollResult: function() {
			var id;

			if (this._getPollResultAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._getPollResultAjaxRequest);
				this._getPollResultAjaxRequest = null;
			}

			switch(this._mode) {
				case 'today':
					id = this._pollId;
					break;
				default:
					if (this._prevPollId == '0') {
						id = this._pollId;
					} else {
						id = this._prevPollId;
					}
					break;
			}

			var soapXMLStr = buildSOAPXMLStr('GetPollResult',
				'<pollId>' + id + '</pollId>');

			YAHOO.util.Connect.setDefaultPostHeader('text/xml; charset=utf-8'); // SOAP 1.1
			YAHOO.util.Connect.initHeader('SOAPAction', '"' + _SOAP_namespace + 'GetPollResult"'); // SOAP 1.1
			//YAHOO.util.Connect.setDefaultPostHeader('application/soap+xml; charset=utf-8'); // SOAP 1.2

			this._getPollResultAjaxRequest = YAHOO.util.Connect.asyncRequest('POST', SOAP_URL, poller_getPollResultCallback, soapXMLStr);
		},

		/**
		 * User has voted stuff
		 */
		_getHasVotedResultAjaxRequest: null, 

		_userHasVotedSuccess: function(o) {
			_getHasVotedResultAjaxRequest = null;

			var doc = o.responseXML.documentElement;
			var hasVotedStr = getFirstChildNodeValue(doc.getElementsByTagName('HasUserAlreadyVotedResult'));

			if (hasVotedStr.charAt(0).toLowerCase() == 't') {
				this.getPollResult();
				return;
			}

			this._showQuestions();
		},

		_userHasVotedFailure: function(o) {
			_getHasVotedResultAjaxRequest = null;

			if (!alertOnFault(o.responseXML.documentElement)) {
				alert("HTTP error: " + o.status + ' ' + o.statusText);
			}
		},

		checkIfUserHasVoted:function(userGuid) {
			if (this._getHasVotedResultAjaxRequest != null) {
				YAHOO.util.Connect.abort(this._getHasVotedResultAjaxRequest);
				this._getHasVotedResultAjaxRequest = null;
			}

			var soapXMLStr = buildSOAPXMLStr('HasUserAlreadyVoted',
				'<userGuid>' + userGuid + '</userGuid>' +
				'<pollId>' + this._pollId + '</pollId>');

			YAHOO.util.Connect.setDefaultPostHeader('text/xml; charset=utf-8'); // SOAP 1.1
			YAHOO.util.Connect.initHeader('SOAPAction', '"' + _SOAP_namespace + 'HasUserAlreadyVoted"'); // SOAP 1.1
			//YAHOO.util.Connect.setDefaultPostHeader('application/soap+xml; charset=utf-8'); // SOAP 1.2

			this._getHasVotedResultAjaxRequest = YAHOO.util.Connect.asyncRequest('POST', SOAP_URL, poller_userHasVotedResultCallback, soapXMLStr);
		}

	}

	poller_userHasVotedResultCallback = {
		success: poller._userHasVotedSuccess,
		failure: poller._userHasVotedFailure,
		scope: poller
	}

	poller_getCurrentCallback = {
		success: poller._getCurrentSuccess,
		failure: poller._getCurrentFailure,
		scope: poller
	}

	poller_submitPollCallback = {
		success: poller._submitPollSuccess,
		failure: poller._getCurrentFailure, // reused
		scope: poller
	}
	
	poller_getPollResultCallback = {
		success: poller._getPollResultSuccess,
		failure: poller._getCurrentFailure, // reused
		scope: poller
	}
}
