var TIPS_COOKIE = "tips";
var PICKS_COOKIE = "picks";
var MAX_FEED_TITLE_LENGTH = 40;
var MAX_TAB_TITLE_LENGTH = 25;
var MAX_TABS_VISIBLE = 2;
var userData = null;
var TAB_SCROLL_LEFT_ENABLED = "http://www.faceoff.com/images/rss/arrow_left.jpg";
var TAB_SCROLL_LEFT_DISABLED = "http://www.faceoff.com/images/rss/arrow_left_disabled.jpg";
var TAB_SCROLL_RIGHT_ENABLED = "http://www.faceoff.com/images/rss/arrow_right.jpg";
var TAB_SCROLL_RIGHT_DISABLED = "http://www.faceoff.com/images/rss/arrow_right_disabled.jpg";
var qs_processed = false;

function Coordinate(x, y) {
	this.x = x;
	this.y = y;
}

function Feed(id, title, ttl, headlines, url, isPreview) {
	this.id = id;
	this.title = title;
	this.ttl = ttl;
	this.headlines = headlines;
	this.url = url;
	this.isPreview = isPreview;

	var li = document.createElement("li");
	li.id = "feed_" + this.id;
	li.className = "feed";

	this.control = li;	
	this.content = "<i>Loading...</i>";
	this.isTop = false;

	// initialize feed content
	var html = "  <div class=\"feedtop\">\n";
	html += "    <div class=\"feedtitlebar\">\n";
	if ( this.url.length > 0 ) 
		html += "   <div class=\"title\"><a id=\"feedtitle_" + this.id + "\" href=\"" + this.url + "\" target=\"_blank\">" + (this.title.length > MAX_FEED_TITLE_LENGTH ? this.title.substring(0, MAX_FEED_TITLE_LENGTH) : this.title) + "</a></div>\n";
	else 
		html += "   <div class=\"title\" id=\"feedtitle_" + this.id + "\">" + (this.title.length > MAX_FEED_TITLE_LENGTH ? this.title.substring(0, MAX_FEED_TITLE_LENGTH) : this.title) + "</div>\n";
	if (!this.isPreview) {
		html += "   <div class=\"editbox\"><a id=\"openeditfeed_" + this.id + "\" href=\"javascript:void(0);\">edit</a></div>\n";
		html += "   <div class=\"closebox\"><a id=\"closeeditfeed_" + this.id + "\" href=\"javascript:void(0);\" onclick=\"userData.removeFeed(" + this.id + ", true);\">x</a></div>";
	}

	html += "    <div class=\"clear\">&nbsp;</div>\n";
	html += "   </div>\n";
	html += "   <div class=\"clear\">&nbsp;</div>\n";
	html += "  </div>\n";
	html += "  <div class=\"feedcontent\" id=\"feedcontent_" + this.id + "\">\n";
	html += "  </div>\n";
	html += "  <div class=\"feedbottom\"></div>\n";

	this.control.innerHTML = html;
}

Feed.prototype.setTitle = function(title) {
	this.title = title;
	var titleObj = $("feedtitle_" + this.id);
	titleObj.innerHTML = (this.title.length > MAX_FEED_TITLE_LENGTH ? this.title.substring(0, MAX_FEED_TITLE_LENGTH) : this.title);
}

Feed.prototype.add = function(col) {
	var parent = $(col);
	this.isTop = parent.childNodes.length < 2;
	parent.appendChild(this.control);
	this.render();
	
	// attach click event to open edit window link
	if (!this.isPreview) {

		this.retrieve();

		addEvent($("openeditfeed_" + this.id), "click", function(e) {
			var feed_id = getSourceElement(e).id.split("_")[1];
			var feed = userData.feeds[feed_id];
			if (feed == null)
				return;
			var ctl = $("editfeed");
			
			// open dialog at mouse coordinates
			var coord = getClickCoordinate(e);
			ctl.style.left = (coord.x - 200) + "px";
			ctl.style.top = coord.y + "px";
			ctl.style.visibility = "visible";
			ctl.style.zIndex = 10001;
			$("edit_feed_id").value = feed_id;
			$("edit_feed_title").value = feed.title;
			$("edit_feed_headlines").value = feed.headlines;
		});
		
		//create tooltip for edit  button
		var new_tooltip = document.createElement("div");
		new_tooltip.id = "openeditfeed_tooltip_" +this.id;
		new_tooltip.className = "tooltip";
		new_tooltip.style.display = "none";
		new_tooltip.innerHTML = "modify widget";
		var tooltipscontainer = $("tooltipscontainer");
		tooltipscontainer.appendChild(new_tooltip);
		Tooltip.add($("openeditfeed_" + this.id),$("openeditfeed_tooltip_" + this.id));

		//create tooltip for each close feed button
		var new_tooltip = document.createElement("div");
		new_tooltip.id = "closeeditfeed_tooltip_" +this.id;
		new_tooltip.className = "tooltip";
		new_tooltip.style.display = "none";
		new_tooltip.innerHTML = "close widget";
		var tooltipscontainer = $("tooltipscontainer");
		tooltipscontainer.appendChild(new_tooltip);
		Tooltip.add($("closeeditfeed_" + this.id),$("closeeditfeed_tooltip_" + this.id));


		// set up periodic refresh
		var id = this.id;
		this.interval = setInterval(function() {userData.feeds[id].retrieve();}, this.ttl * 1000 * 60);
	}
}

Feed.prototype.retrieve = function() {
	var id = this.id;
	RssCalls.loadFeed($F("instance_id"), userData.currentTabId, this.id, function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		var feed = userData.feeds[id];
		if (json_obj.error) 
			feed.content = "Sorry, there was a problem retrieving the feed.";
		else if (json_obj.unsupportedformat) 
			feed.content = "Sorry, this feed is in an unsupported format (" + json_obj.unsupportedformat + ").  We currently support RSS 1.0/RDF, RSS 2.0 and ATOM 1.0.";
		else if (json_obj.cookienotfound) {
			reloadPage();
			return;
		}
		else if (json_obj.feednotfound) {
			feed.remove(false);
			return;
		}
		else 
			feed.content = json_obj.content;
		feed.render();
	});
}

Feed.prototype.render = function() {
	this.control.className = (this.isTop && userData.getTabIndex(userData.currentTabId) == 0 ? "feedorange" : "feed");
	$("feedcontent_" + this.id).innerHTML = this.content;
}

Feed.prototype.remove = function(send_req) {
	var col_id = this.control.parentNode.id;
	this.control.parentNode.removeChild(this.control);
	delete userData.feeds[this.id];
	userData.resetTopFeedsForColumn(col_id);
	if (send_req) {
		RssCalls.removeFeed($F("instance_id"), userData.currentTabId, this.id, function(req) {
			var response = req.responseText;
			var json_obj = response.parseJSON();
			if (json_obj.error)
				alert(json_obj.error);
			else if (json_obj.cookienotfound)
				reloadPage();
		});
	}
}

Feed.prototype.update = function() {
	var id = this.id
	RssCalls.editFeed($F("instance_id"), userData.currentTabId, this.id, this.title, this.headlines, function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}
		else if (json_obj.cookienotfound) {
			reloadPage();
			return;
		}
		else if (json_obj.feednotfound) {
			userData.feeds[id].remove(false);
			return;
		}
		userData.feeds[id].retrieve();
	});
}

function UserData(isLoggedIn, hasPicks) {
	this.isLoggedIn = isLoggedIn;
	this.showTips = Cookie.getCookieValue(TIPS_COOKIE) == null;
	this.currentTabId = null;
	this.startVisibleTabIndex = 1;
	this.currentTipIndex = 0;
	this.tabscontainer = $("tabcontent");
	this.feeds = new Object;

	// show picks or tips (or neither as the case may be)
	if (hasPicks && Cookie.getCookieValue(PICKS_COOKIE) == null) 
		$("pickscontainer").style.display = "block";
	else if (this.showTips && tips.length > 0) {
		$("tipscontent").innerHTML = tips[0];
		$("tipscontainer").style.display = "block";
	}
}

// add a new tab
UserData.prototype.addTab = function(id, name) {
	var children = this.tabscontainer.getElementsByTagName("div");
	//var children = this.tabscontainer.childNodes;
	var new_tab = document.createElement("div");
	new_tab.id = "tab_" + id;
	if (children.length == 0) { // first tab being added
		if (qs_processed)
			new_tab.className = "mycontenttab";
		else
			new_tab.className = "mycontenttab active";
		//new_tab.style.display = "block";
	}
	else {
		new_tab.className = "rsstab";

		// if this new tab will fall outside the visible range then hide it
		if (this.startVisibleTabIndex + MAX_TABS_VISIBLE < children.length + 1)
			new_tab.style.display = "none";
		//else 
		//	new_tab.style.display = "block";
	}
	new_tab.innerHTML = "<a href=\"javascript:void(0);\" id=\"clicktab_" + id + "\" onclick=\"userData.selectTab('" + id + "');\"><span>" + (name.length > MAX_TAB_TITLE_LENGTH ? name.substring(0, MAX_TAB_TITLE_LENGTH) : name) + "</span></a>";
	this.tabscontainer.appendChild(new_tab);

	//dynamically create a  tooltip for each tab, except the first tab
	if(children.length > 1) {
		var new_tooltip = document.createElement("div");
		new_tooltip.id = "edittab_tooltip_" + id;
		new_tooltip.className = "tooltip";
		new_tooltip.style.display = "none";
		new_tooltip.innerHTML = "Click to rename or remove";
		var tooltipscontainer = $("tooltipscontainer");
		tooltipscontainer.appendChild(new_tooltip);
		Tooltip.add($("clicktab_" + id),$("edittab_tooltip_" + id));
	}
	this.resetTabNavigator();
}

// allow title editing on a tab
UserData.prototype.editTab = function(id) {
	var tab = $("tab_" + id);
	var tab_name = (tab.innerText != undefined ? tab.innerText : tab.textContent);
	var obj = document.getElementById("edit_tab_" + id);
	tab.innerHTML = "<input type=\"hidden\" id=\"edit_old_tab_" + id + "\" value=\"" + tab_name + "\" /><input type=\"text\" class=\"edittab\" id=\"edit_tab_" + id + "\" cols=\"10\" maxlength=\"" + MAX_TAB_TITLE_LENGTH + "\" value=\"" + tab_name + "\" onkeydown=\"userData.updateTab(event)\"  /><a id=\"remove_tab_" + id + "\" href=\"javascript:void(0);\" onclick=\"userData.removeTab('" + id + "');\" class=\"deletetab\">x</a>";
	$("edit_tab_" + id).focus();
	Tooltip.add($("remove_tab_" + id), $("deletetab_tooltip"));
}

UserData.prototype.scrollTabLeft = function() {
	if ($("img_previous_tab").src == TAB_SCROLL_LEFT_ENABLED) {
		//var children = this.tabscontainer.getElementsByTagName("div");
		var children = this.tabscontainer.childNodes;
		if (this.startVisibleTabIndex + MAX_TABS_VISIBLE - 1 < children.length)
			children[this.startVisibleTabIndex + MAX_TABS_VISIBLE - 1].style.display = "none";
		this.startVisibleTabIndex = this.startVisibleTabIndex - 1;
		children[this.startVisibleTabIndex].style.display = "block";
		this.resetTabNavigator();
	}
}

UserData.prototype.scrollTabRight = function() {
	if ($("img_next_tab").src == TAB_SCROLL_RIGHT_ENABLED) {
		//var children = this.tabscontainer.getElementsByTagName("div");
		var children = this.tabscontainer.childNodes;
		children[this.startVisibleTabIndex].style.display = "none";
		this.startVisibleTabIndex = this.startVisibleTabIndex + 1;
		children[this.startVisibleTabIndex + MAX_TABS_VISIBLE - 1].style.display = "block";
		this.resetTabNavigator();
	}
}

// cancel the title update for the currently active tab
UserData.prototype.cancelTab = function() {
	// clear any active edit controls
	var tab = $("tab_" + this.currentTabId);
	tab.innerHTML = "<a href=\"javascript:void(0);\" id=\"clicktab_" + this.currentTabId + "\" onclick=\"userData.editTab('" + this.currentTabId + "');\"><span>" + $F("edit_old_tab_" + this.currentTabId) + "</span></a>";
	Tooltip.add($("clicktab_" + this.currentTabId), $("edittab_tooltip_" + this.currentTabId));
}

// update the title for a tab
UserData.prototype.updateTab = function(e) {
	var key = typeof e != 'undefined' ? getKeyCode(e) : null;
	var do_update = false;
	if (key != null) {
		switch (key) {
			case 13: // ENTER key
				do_update = true;
				break;
			case 27: // ESC key
				this.cancelTab();
				break;
		}
	}
	else 
		do_update = true;

	if (do_update) {
		var obj = $("edit_tab_" + this.currentTabId);
		if (obj.value.replace(/\s/g,'').length == 0) {
			this.cancelTab();
			return;
		}
		RssCalls.updateTab($F("instance_id"), this.currentTabId, obj.value, function(req) {
			var response = req.responseText;
			var json_obj = response.parseJSON();
			if (json_obj.error)
				alert(json_obj.error);
			else if (json_obj.cookienotfound)
				reloadPage();
		});
		obj.parentNode.innerHTML = "<a href=\"javascript:void(0);\" id=\"clicktab_" + this.currentTabId + "\" onclick=\"return userData.editTab('" + this.currentTabId + "');\"><span>" + obj.value + "</span></a>";
		Tooltip.add($("clicktab_" + this.currentTabId), $("edittab_tooltip_" + this.currentTabId));
	}
}

// make a tab active
UserData.prototype.selectTab = function(id) {
	//var children = this.tabscontainer.getElementsByTagName("div");
	var children = this.tabscontainer.childNodes;

	// de-select previously active tab
	if (this.currentTabId != null) {
		var old_tab = $("tab_" + this.currentTabId);
		if (children[0].id == old_tab.id) 
			old_tab.className = "mycontenttab";
		else 
			old_tab.className = "rsstab";
		var old_tab_id = old_tab.id.split('_')[1];

		//check to see if tab is still in edit mode (IE hack)
		if(document.getElementById("edit_tab_" + old_tab_id))
		{
			userData.updateTab();
		}			
		old_tab.innerHTML = "<a href=\"javascript:void(0);\" id=\"clicktab_" + old_tab_id + "\" onclick=\"userData.selectTab('" + old_tab_id + "');\"><span>" +	 ( old_tab.innerText != undefined ? old_tab.innerText : old_tab.textContent ) + "</span></a>";

		if(children[0].id != old_tab.id)
			Tooltip.add($("clicktab_" + old_tab_id),$("edittab_tooltip_" + old_tab_id));
	}
	
	// select new tab
	var tab = $("tab_" + id);
	this.currentTabId = id;
	if (children[0].id == tab.id) {	// first tab cannot be edited or removed
		tab.className = "mycontenttab active";
		tab.innerHTML = "<a href=\"javascript:void(0);\"><span>" + ( tab.innerText != undefined ? tab.innerText : tab.textContent ) + "</span></a>";
	}
	else {
		tab.className = "rsstab active";
		tab.innerHTML = "<a href=\"javascript:void(0);\" id=\"clicktab_" + id + "\" onclick=\"return userData.editTab('" + id + "');\"><span>" + ( tab.innerText != undefined ? tab.innerText : tab.textContent ) + "</span></a>";
		Tooltip.add($("clicktab_" + id), $("edittab_tooltip_" + id));
	}
	
	this.clearFeeds();

	RssCalls.listFeeds($F("instance_id"), id, function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}
		else if (json_obj.cookienotfound) {
			reloadPage();
			return;
		}
		// add personalized feeds
		for (var i = 0; i < json_obj.feeds.length; i++) {
			var feed = new Feed(json_obj.feeds[i].id, json_obj.feeds[i].title, json_obj.feeds[i].ttl, json_obj.feeds[i].headlines, "", false);
			userData.feeds[feed.id] = feed;
			feed.add("col_" + json_obj.feeds[i].col);
		}
		userData.initializeDragDrop();

		// check if one of the feeds should have its edit dialog open (only happens on initial visit to page)
		if (!qs_processed) {
			var edit_val = Querystring.getValue("edit");
			if (edit_val.indexOf("feed") == 0) {
				edit_val = edit_val.substring(4);
				if (userData.feeds[edit_val] != null) {
					var ctl = $("editfeed");
					ctl.style.left = "250px";
					ctl.style.top = "350px";
					ctl.style.visibility = "visible";
					ctl.style.zIndex = 10001;
					$("edit_feed_id").value = userData.feeds[edit_val].id;
					$("edit_feed_title").value = userData.feeds[edit_val].title;
					$("edit_feed_headlines").value = userData.feeds[edit_val].headlines;
				}
			}
			qs_processed = true;
		}
	});
}

// remove a feed
UserData.prototype.removeFeed = function(id, send_req) {
	var feed = this.feeds[id];
	if ( confirm("Are you sure you want to remove the feed '" + feed.title + "'?") ) 
		feed.remove(true);

		//remove tootip divs
	var tooltipscontainer = $("tooltipscontainer");
	var remove_tip = $("openeditfeed_tooltip_" + id);
	var remove_tip2 = $("closeeditfeed_tooltip_" + id);
	tooltipscontainer.removeChild(remove_tip);
		tooltipscontainer.removeChild(remove_tip2);
}

// reset which feeds are highlighted
UserData.prototype.resetTopFeedsForColumn = function(col_id) {
	var col = $(col_id);
	var items = col.getElementsByTagName("li");
	var index = 0;
	for ( var j = 0; j < items.length; j++ ) {
		if ( items[j].id != "feeditem" ) {
			var feed = this.feeds[items[j].id.substring(5)];
			if(feed)
			{
				var old_is_top = feed.isTop;
				if ( index < 2 ) 
					feed.isTop = true;
				else
					feed.isTop = false;
				if ( old_is_top != feed.isTop )  // only re-render if the feed is now or is no longer among the top 2 for its column
					feed.render();
				
				index++;
			}
		}
	}
}

// get the index of a tab among all tabs
UserData.prototype.getTabIndex = function(id) {
	//var children = this.tabscontainer.getElementsByTagName("div");
	var children = this.tabscontainer.childNodes;
	var index = -1;
	for (var i = 0; i < children.length; i++) {
		if (children[i].id == "tab_" + id) {
			index = i;
			break;
		}
	}
	return index;
}

UserData.prototype.resetTabNavigator = function() {

	var tabnavigation = $("scroll_container");

	tabnavigation.innerHTML = "<a href=\"javascript:void(0);\" id=\"scrollPrev\" onclick=\"userData.scrollTabLeft();\"><img id=\"img_previous_tab\"  border=\"0\" /></a>&nbsp;&nbsp;<a href=\"javascript:void(0);\" id=\"scrollNext\" onclick=\"userData.scrollTabRight();\"><img id=\"img_next_tab\" border=\"0\" /></a>";

	// left scroller
	if (this.startVisibleTabIndex == 1)
		$("img_previous_tab").src = TAB_SCROLL_LEFT_DISABLED;
	else
	{
		$("img_previous_tab").src = TAB_SCROLL_LEFT_ENABLED;
		Tooltip.add($("scrollPrev"),$("scrollPrev_tooltip"));
	}

	// right scroller
	//if (this.startVisibleTabIndex + MAX_TABS_VISIBLE >= this.tabscontainer.getElementsByTagName("div").length)
	if (this.startVisibleTabIndex + MAX_TABS_VISIBLE >= this.tabscontainer.childNodes.length)
		$("img_next_tab").src = TAB_SCROLL_RIGHT_DISABLED;
	else
	{
		$("img_next_tab").src = TAB_SCROLL_RIGHT_ENABLED;
		Tooltip.add($("scrollNext"),$("scrollNext_tooltip"));
	}
}

// remove a tab
UserData.prototype.removeTab = function(id) {
	var remove_tab = $("tab_" + id);
	var index = this.getTabIndex(id);
	this.tabscontainer.removeChild(remove_tab);
	this.currentTabId = null;
	//var children = this.tabscontainer.getElementsByTagName("div");
	var children = this.tabscontainer.childNodes;
	this.selectTab(children[index - 1].id.split('_')[1]);
	if (children.length == 1) {
		this.startVisibleTabIndex = 1;	// deleted last non-static tab
	}
	else {
		for (var i = this.startVisibleTabIndex; i <= MAX_TABS_VISIBLE && i < children.length; i++) {
			children[i].style.display = "block";
		}
	}

	//remove tootip div
	var tooltipscontainer = $("tooltipscontainer");
	var remove_tip = $("edittab_tooltip_" + id);
	tooltipscontainer.removeChild(remove_tip);

	this.resetTabNavigator();
	RssCalls.removeTab($F("instance_id"), id, function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error)
			alert(json_obj.error);
		else if (json_obj.cookienotfound)
			reloadPage();
	});
}

UserData.prototype.revertDefaultTab = function() {
	RssCalls.revertDefaultTab($F("instance_id"), function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) 
			alert(json_obj.error);
		else if (json_obj.cookienotfound)
			reloadPage();
		else {
			// if the default tab is the current tab then reload the feeds
			if (userData.getTabIndex(userData.currentTabId) == 0) {
				userData.selectTab(userData.currentTabId);
			}
			else {
				alert("'" + (userData.tabscontainer.childNodes[0].innerText != undefined ? userData.tabscontainer.childNodes[0].innerText : userData.tabscontainer.childNodes[0].textContent) + "' tab has been reverted");
			}
		}
	});
}

UserData.prototype.closePicks = function() {
	$("pickscontainer").style.display = "none";
	Cookie.setSessionCookie(PICKS_COOKIE, "false");
	if (this.showTips  &&  tips.length > 0) {
		$("tipscontent").innerHTML = tips[0];
		$("tipscontainer").style.display = "block";
	}
}

UserData.prototype.closeTips = function() {
	$("tipscontainer").style.display = "none";
	Cookie.setSessionCookie(TIPS_COOKIE, "false");
}

UserData.prototype.nextTip = function() {
	if (this.currentTipIndex == tips.length - 1)
		this.currentTipIndex = 0;
	else
		this.currentTipIndex++;
	$("tipscontent").innerHTML = tips[this.currentTipIndex];
}

UserData.prototype.previousTip = function() {
	if (this.currentTipIndex == 0)
		this.currentTipIndex = tips.length - 1;
	else 
		this.currentTipIndex--;
	$("tipscontent").innerHTML = tips[this.currentTipIndex];
}

UserData.prototype.clearFeeds = function() {
	for (var i = 0; i < 2; i++) {
		var col = $("col_" + i);
		while (col.childNodes.length > 0) {
			if (this.feeds[col.childNodes[col.childNodes.length - 1].id.split("_")[1]].interval != null)
				clearInterval(this.feeds[col.childNodes[col.childNodes.length - 1].id.split("_")[1]].interval);
			delete this.feeds[col.childNodes[col.childNodes.length - 1].id.split("_")[1]];
			col.removeChild(col.childNodes[col.childNodes.length -1]);
		}
	}
}

UserData.prototype.initializeDragDrop = function() {
	Position.includeScrollOffsets = true;
	Sortable.create("col_0", {dropOnEmpty:true,handle:'title',containment:["col_0","col_1"],constraint:false,scroll:window,highlight:true,onUpdate:doUpdateOrder });
	Sortable.create("col_1", {dropOnEmpty:true,handle:'title',containment:["col_0","col_1"],constraint:false,scroll:window,highlight:true,onUpdate:doUpdateOrder });
}

UserData.prototype.addPackagePanelPicks = function() {
	var chks = document.getElementsByClassName("package_panel_checkbox", $("package_panel_picksrows"));
	var package_ids = new Array();
	for (var i = 0; i < chks.length; i++) {
		if (chks[i].checked) {
			package_ids.push(chks[i].value);
			chks[i].checked = false;
		}
	}
	if (package_ids.length == 0) 
		alert("Please select one or more Content Tabs.");
	else {
		RssCalls.addPackages($F("instance_id"), package_ids.join(","), function(req) {
			var response = req.responseText;
			var json_obj = response.parseJSON();
			if (json_obj.error)	{
				alert(json_obj.error);
				return;
			}
			else if (json_obj.cookienotfound) {
				reloadPage();
				return;
			}
			// add tabs
			for (var i = 0; i < json_obj.tabs.length; i++) {
				userData.addTab(json_obj.tabs[i].id, json_obj.tabs[i].name);
			}
		});
	}
}

UserData.prototype.addPicks = function() {
	var chks = document.getElementsByClassName("pick_checkbox", $("picksrows"));
	var package_ids = new Array();
	for (var i = 0; i < chks.length; i++) {
		if (chks[i].checked) {
			package_ids.push(chks[i].value);
			chks[i].checked = false;
		}
	}
	if (package_ids.length == 0) 
		alert("Please select one or more Content Tabs.");
	else {
		RssCalls.addPackages($F("instance_id"), package_ids.join(","), function(req) {
			var response = req.responseText;
			var json_obj = response.parseJSON();
			if (json_obj.error)	{
				alert(json_obj.error);
				return;
			}
			else if (json_obj.cookienotfound) {
				reloadPage();
				return;
			}
			// add tabs
			for (var i = 0; i < json_obj.tabs.length; i++) {
				userData.addTab(json_obj.tabs[i].id, json_obj.tabs[i].name);
			}
		});
	}
}

UserData.prototype.closeEditFeed = function() {
	$("editfeed").style.visibility = "hidden";
}

UserData.prototype.saveEditFeed = function() {
	var feed = this.feeds[$F("edit_feed_id")];
	var title = $F("edit_feed_title");
	var headlines = $F("edit_feed_headlines");
	if ( title.length == 0 ) {
		alert("You must enter a title for the feed.");
		return;
	}
	this.closeEditFeed();
	feed.setTitle(title);
	feed.headlines = headlines;
	feed.update();
}

UserData.prototype.openFindContent = function() {
	$("package_panel").style.display = "block";
	$("site_search_panel").style.display = "none";
	$("external_feed_panel").style.display = "none";
	$("select_content_panel").style.display = "none";	
	$("preview_col_0").innerHTML = "";
	$("preview_col_1").innerHTML = "";

	$("site_search_keyword").value = "";

	var chks = document.getElementsByClassName("package_panel_checkbox", $("package_panel_picksrows"));
	for (var i = 0; i < chks.length; i++) 
		chks[i].checked = false;

	$("content_browser").style.zIndex = 10001;
	$("content_browser").style.display = "block";
}

UserData.prototype.openSelectContent = function(preselect_packs) {
	$("package_panel").style.display = "none";
	$("site_search_panel").style.display = "none";
	$("external_feed_panel").style.display = "none";
	$("add_content_selections").style.visibility = "hidden";
	$("package_thumbnail_view").innerHTML = "";
	$("package_list_view").innerHTML = "";
	$("step1").innerHTML = "";
	$("step3").innerHTML = "";

	// load step 1
	RssCalls.getStep1($F("instance_id"), function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}
		var html = "<div class=\"sourcerow\">\n";
		html += "  <input type=\"radio\" class=\"radiotext\" name=\"content_type\" value=\"contenttabs\" onclick=\"userData.selectStep1();\" /><span>Content Tabs</span>\n";
		html += "</div>\n";

		for (var i = 0; i < json_obj.steps.length; i++) {
			html += "<div class=\"sourcerow\">\n";
			html += "  <input type=\"radio\" class=\"radiotext\" name=\"content_type\" value=\"" + json_obj.steps[i].id + "\" onclick=\"userData.selectStep1();\" /><span>" + json_obj.steps[i].title + "</span>\n";
			html += "</div>\n";
		}

		$("step1").innerHTML = html;

		// for possible use based on user choices
		userData.worldNewsFeeds = json_obj.premium_feeds;
		userData.packages = json_obj.packages;

		$("select_content_panel").style.display = "block";
		$("content_browser").style.zIndex = 10001;
		$("content_browser").style.display = "block";

		if (preselect_packs) 
			document.getElementsByClassName("radiotext", $("step1"))[0].checked = true;
		else
			document.getElementsByClassName("radiotext", $("step1"))[1].checked = true;

		userData.selectStep1();
	});
}

UserData.prototype.selectStep1 = function() {
	var opts = document.getElementsByClassName("radiotext", $("step1"));
	var val = null;
	for (var i = 0; i < opts.length; i++) {
		if (opts[i].checked) {
			val = opts[i].value;
			break;
		}
	}
	if (val != null) {
		if (val == "contenttabs") {
			$("select_content_non_package").style.display = "none";
			$("add_content_selections").style.visibility = "visible";

			// load package thumbnail view
			if ($("package_thumbnail_view").innerHTML.length == 0) {
				
				var thumb_html = "";
				var list_html = "";

				for (var i = 0; i < this.packages.length; i++) {

					thumb_html += "<div class=\"widgetrow\">\n";
					thumb_html += "  <div class=\"contentbox contentbox02\">\n";
					thumb_html += "    <div class=\"contentboxcopy\">\n";
					thumb_html += "      <div class=\"smallimage\">\n";
					thumb_html += "        <span>\n";
					thumb_html += "          <img alt=\"\" src=\"" + (this.packages[i].has_image ? "scripts/reader/packageimage.aspx?id=" + this.packages[i].id : "images/feedtab2.gif") + "\" border=\"0\">\n";
					thumb_html += "        </span>\n";
					thumb_html += "      </div>\n";
					thumb_html += "      <h4>\n";
					thumb_html += "        <input type=\"checkbox\" value=\"" + this.packages[i].id + "\" class=\"package_checkbox\" />\n";
					thumb_html += "        <span>" + this.packages[i].title + "</span>\n";
					thumb_html += "      </h4>\n";
					thumb_html += "      <p class=\"first\">\n";
					thumb_html += this.packages[i].description + "\n";
					thumb_html += "      </p>\n";
					thumb_html += "    </div>\n";
					thumb_html += "  </div>\n";
					thumb_html += "  <div class=\"clear\">&nbsp;</div>\n";
					thumb_html += "</div>\n";
					thumb_html += "<div class=\"clear\">&nbsp;</div>\n";

					list_html += "<div class=\"widgetrow\">\n";
					list_html += "  <div class=\"contentbox contentbox02\">\n";
					list_html += "    <div class=\"contentboxcopy\">\n";
					list_html += "      <h4>\n";
					list_html += "        <input type=\"checkbox\" value=\"" + this.packages[i].id + "\" class=\"package_checkbox\" />\n";
					list_html += "        <span>" + this.packages[i].title + "</span>\n";
					list_html += "      </h4>\n";
					list_html += "    </div>\n";
					list_html += "  </div>\n";
					list_html += "  <div class=\"clear\">&nbsp;</div>\n";
					list_html += "</div>\n";
					list_html += "<div class=\"clear\">&nbsp;</div>\n";
				}

				$("package_thumbnail_view").innerHTML = thumb_html;
				$("package_list_view").innerHTML = list_html;
			}

			$("select_content_tab_thumbnail").style.display = "block";
			$("select_content_tab_listview").style.display = "none";
			$("select_content_package").style.display = "block";
		}
		else {
			$("select_content_package").style.display = "none";
			$("add_content_selections").style.visibility = "hidden";

			// load step2
			RssCalls.getStep2(val, function(req) {
				var response = req.responseText;
				var json_obj = response.parseJSON();
				if (json_obj.error)	{
					alert(json_obj.error);
					return;
				}
				var ctl = $("step2");
				ctl.options.length = 0;
				for (var i = 0; i < json_obj.steps.length; i++) {
					var opt = document.createElement("option");
					opt.value = json_obj.steps[i].id;
					opt.text = json_obj.steps[i].title;
					try {
						ctl.add(opt, null); // standards compliant; doesn't work in IE
					}
					catch(ex) {
						ctl.add(opt); // IE only
					}
				}

				$("step3").innerHTML = "";
				$("select_content_non_package").style.display = "block";
			});
		}
	}
}

UserData.prototype.showPackageThumbnailView = function() {
	$("select_content_tab_thumbnail").style.display = "block";
	$("select_content_tab_listview").style.display = "none";
}

UserData.prototype.showPackageListView = function() {
	$("select_content_tab_thumbnail").style.display = "none";
	$("select_content_tab_listview").style.display = "block";
}

UserData.prototype.selectStep2 = function() {
	if ($("step2").selectedIndex == - 1) {
		alert("Please select one of the content options");
		return;
	}
	if ($("step2").value != "") {
		// load step3
		RssCalls.getStep3($("step2").value, function(req) {
			var response = req.responseText;
			var json_obj = response.parseJSON();
			if (json_obj.error)	{
				alert(json_obj.error);
				return;
			}
			$("step3").innerHTML = "";
			var html = "";

			for (var i = 0; i < json_obj.steps.length; i++) {
				html += "<input  type=\"checkbox\" class=\"checktext\" value=\"" + json_obj.steps[i].feed_id + "\" " + (userData.feeds[json_obj.steps[i].feed_id] != null ? "checked disabled" : "") + " />" + json_obj.steps[i].title + "<br />\n";
			}

			$("step3").innerHTML = html;
			$("add_content_selections").style.visibility = "visible";
		});
	}
}

UserData.prototype.addContentSelections = function() {
	var opts = document.getElementsByClassName("radiotext", $("step1"));
	var val = null;
	for (var i = 0; i < opts.length; i++) {
		if (opts[i].checked) {
			val = opts[i].value;
			break;
		}
	}
	if (val != null) {
		if (val == "contenttabs") {
			var chks = null;
			if ($("select_content_tab_thumbnail").style.display == "block") 
				chks = document.getElementsByClassName("package_checkbox", $("package_thumbnail_view"));
			else
				chks = document.getElementsByClassName("package_checkbox", $("package_list_view"));

			var package_ids = new Array();
			for (var i = 0; i < chks.length; i++) {
				if (chks[i].checked) {
					package_ids.push(chks[i].value);
					chks[i].checked = false;
					chks[i].disabled = true;
				}
			}
			if (package_ids.length == 0)
				alert("Please select one or more Content Tabs.");
			else {
				RssCalls.addPackages($F("instance_id"), package_ids.join(","), function(req) {
					var response = req.responseText;
					var json_obj = response.parseJSON();
					if (json_obj.error)	{
						alert(json_obj.error);
						return;
					}
					else if (json_obj.cookienotfound) {
						reloadPage();
						return;
					}
					// add tabs
					for (var i = 0; i < json_obj.tabs.length; i++) {
						userData.addTab(json_obj.tabs[i].id, json_obj.tabs[i].name);
					}
				});
			}
		}
		else {
			var chks = document.getElementsByClassName("checktext", $("step3"));
			var feed_ids = new Array();
			for (var i = 0; i < chks.length; i++) {
				if (chks[i].checked && chks[i].disabled == false) {
					feed_ids.push(chks[i].value);
					chks[i].disabled = true;
				}
			}

			if (feed_ids.length == 0) 
				alert("Please select one or more Topics.");
			else {
				RssCalls.addFeeds($F("instance_id"), this.currentTabId, feed_ids.join(","), function(req) {
					var response = req.responseText;
					var json_obj = response.parseJSON();
					if (json_obj.error) {
						alert(json_obj.error);
						return;
					}
					else if (json_obj.cookienotfound) {
						reloadPage();
						return;
					}

					// add feeds
					for (var i = 0; i < json_obj.feeds.length; i++) {
						var feed = new Feed(json_obj.feeds[i].id, json_obj.feeds[i].title, json_obj.feeds[i].ttl, json_obj.feeds[i].headlines, "", false);
						userData.feeds[feed.id] = feed;
						feed.add("col_0");
					}
					userData.initializeDragDrop();
				});
			}
		}
	}
}

UserData.prototype.closeContentBrowser = function() {
	$("content_browser").style.display = "none";
}

UserData.prototype.showSiteSearchPreview1 = function() {
	$("site_search_added").style.visibility = "hidden";
	$("site_search_add").style.visibility = "hidden";
	$("preview_col_0").innerHTML = "";
	if ($F("site_search_keyword").length == 0) {
		alert("Please enter a topic or keyword");
		return;
	}
	RssCalls.showSiteSearchPreview($F("site_search_keyword"), function(req) {
		$("preview_col_0").innerHTML = "";
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert("Sorry, there was a problem retrieving the feed.");
			return;
		}
		else if (json_obj.unsupportedformat) { 
			alert("Sorry, this feed is in an unsupported format (" + json_obj.unsupportedformat + ").  We currently support RSS 1.0/RDF, RSS 2.0 and ATOM 1.0.");
			return;
		}

		$("package_panel").style.display = "none";
		$("site_search_keyword2").value = $F("site_search_keyword");
		$("site_search_add").style.visibility = "visible";
		$("site_search_panel").style.display = "block";

		var feed = new Feed("feedpreview", json_obj.title, 10, 5, "", true);
		feed.content = json_obj.content;
		feed.add("preview_col_0");
	});
}

UserData.prototype.showSiteSearchPreview2 = function() {
	$("site_search_added").style.visibility = "hidden";
	$("site_search_add").style.visibility = "hidden";
	$("preview_col_0").innerHTML = "";
	if ($F("site_search_keyword2").length == 0) {
		alert("Please enter a topic or keyword");
		return;
	}
	RssCalls.showSiteSearchPreview($F("site_search_keyword2"), function(req) {
		$("preview_col_0").innerHTML;
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert("Sorry, there was a problem retrieving the feed.");
			return;
		}
		else if (json_obj.unsupportedformat) { 
			alert("Sorry, this feed is in an unsupported format (" + json_obj.unsupportedformat + ").  We currently support RSS 1.0/RDF, RSS 2.0 and ATOM 1.0.");
			return;
		}

		$("site_search_add").style.visibility = "visible";
		
		var feed = new Feed("feedpreview", json_obj.title, 10, 5, "", true);
		feed.content = json_obj.content;
		feed.add("preview_col_0");
	});
}

UserData.prototype.showPackagePanel = function() {
	$("site_search_keyword").value = $F("site_search_keyword2");
	$("site_search_panel").style.display = "none";
	$("package_panel").style.display = "block";
}

UserData.prototype.addSiteSearch = function() {
	if ($F("site_search_keyword2").length == 0) {
		alert("Please enter a topic or keyword");
		return;
	}
	RssCalls.addSiteSearch($F("instance_id"), this.currentTabId, $F("site_search_keyword2"), function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}
		else if (json_obj.cookienotfound) {
			reloadPage();
			return;
		}

		$("site_search_added").style.visibility = "visible";
		$("site_search_keyword2").value = "";

		var feed = new Feed(json_obj.feed_id, json_obj.title, json_obj.ttl, json_obj.headlines, "", false);
		userData.feeds[feed.id] = feed;
		feed.add("col_" + 0);
		userData.initializeDragDrop();
	});
}

UserData.prototype.showExternalFeedPanel = function() {
	$("package_panel").style.display = "none";
	$("site_search_panel").style.display = "none";
	$("external_feed_url").value = "";
	$("preview_col_1").innerHTML = "";
	$("external_url_added").style.visibility = "hidden";
	$("external_url_add").style.visibility = "hidden";
	$("external_feed_panel").style.display = "block";
}

UserData.prototype.showExternalPreview = function() {
	$("external_url_added").style.visibility = "hidden";
	$("external_url_add").style.visibility = "hidden";
	$("preview_col_1").innerHTML = "";
	if ($F("external_feed_url").length == 0) {
		alert("Please enter a valid url");
		return;
	}
	RssCalls.showExternalPreview($F("external_feed_url"), function(req) {
		$("preview_col_1").innerHTML = "";
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert("Sorry, there was a problem retrieving the feed.");
			return;
		}
		else if (json_obj.unsupportedformat) { 
			alert("Sorry, this feed is in an unsupported format (" + json_obj.unsupportedformat + ").  We currently support RSS 1.0/RDF, RSS 2.0 and ATOM 1.0.");
			return;
		}

		$("external_url_add").style.visibility = "visible";

		var feed = new Feed("feedpreview", json_obj.title, 10, 5, "", true);
		feed.content = json_obj.content;
		feed.add("preview_col_1");
	});
}

UserData.prototype.addExternalUrl = function() {
	if ($F("external_feed_url").length == 0) {
		alert("Please enter a valid url");
		return;
	}
	RssCalls.addExternalUrl($F("instance_id"), this.currentTabId, $F("external_feed_url"), function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}
		else if (json_obj.cookienotfound) {
			reloadPage();
			return;
		}

		$("external_url_added").style.visibility = "visible";
		$("external_feed_url").value = "";

		var feed = new Feed(json_obj.feed_id, json_obj.title, json_obj.ttl, json_obj.headlines, "", false);
		userData.feeds[feed.id] = feed;
		feed.add("col_" + 0);
		userData.initializeDragDrop();
	});
}

function checkWarning() {
	if (userData != null && !userData.isLoggedIn)
		alert("Your custom content will be saved on this computer.  If you want access from any computer you must log in.");
}

function loadUserData() {
	addEvent(document.getElementsByTagName("body")[0], "click", function(e) {
		if (userData != null) {
			var srcObj = getSourceElement(e);
			
			if (userData.currentTabId != null && $("edit_tab_" + userData.currentTabId) != null && !hasParent(srcObj, "tab_" + userData.currentTabId)) {
				// if user editing a tab title, save their update if click outside of tab
				userData.updateTab();
			}
			else if ($("editfeed").style.visibility == "visible" && !(srcObj.id && srcObj.id.indexOf("openeditfeed_") == 0) && !hasParent(srcObj, "editfeed")) {
				// if user editing feed properties, close edit dialog if click outside of dialog
				userData.closeEditFeed();
			}
			else if ($("content_browser").style.display == "block" && srcObj.id != "content_opener" && !hasParent(srcObj, "content_browser")) {
				// if user selecting content, close content browser if click outside of dialog
				userData.closeContentBrowser();
			}
		}

	});
		
	RssCalls.loadUserData($F("instance_id"), function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error) {
			alert(json_obj.error);
			return;
		}

		userData = new UserData(json_obj.isLoggedIn, json_obj.packages.length > 0);
		
		// add tabs
		for (var i = 0; i < json_obj.tabs.length; i++) {
			userData.addTab(json_obj.tabs[i].id, json_obj.tabs[i].name);
		}

		// add packages in rows of 3 to editor's picks
		var html = "";
		for (var i = 0; i <json_obj.packages.length; i++) {
			html += "  <div class=\"packcol\">\n";
			html += "    <input type=\"checkbox\" value=\"" + json_obj.packages[i].id + "\" class=\"pick_checkbox\">\n";
			html += "    <span>" + json_obj.packages[i].title + "</span>\n";
			html += "  </div>\n";
			if ((i + 1) % 3 == 0)
				html += "  <div class=\"clear\"></div>\n";
		}
		$("picksrows").innerHTML = html;

		// add packages in rows of 2 to select content dialog
		html = "<div class=\"packsrow\">\n";
		for (var i = 0; i < json_obj.packages.length; i++) {
			html += "  <div class=\"packcol\">\n";
			html += "    <input type=\"checkbox\" value=\"" + json_obj.packages[i].id + "\" class=\"package_panel_checkbox\">\n";
			html += "    <span>" + json_obj.packages[i].title + "</span>\n";
			html += "  </div>\n";
			if ((i + 1) % 2 == 0)
				html += "  <div class=\"clear\"></div>\n";
		}
		html += "</div>";
		$("package_panel_picksrows").innerHTML = html;

		$("loadingfeeds").style.visibility = "hidden";
		$("phasetwocontainer").style.visibility = "visible";

		// select first tab
		userData.selectTab(json_obj.tabs[0].id);

		if (Querystring.getValue("do") == "create")
			userData.openFindContent();
	});
}

function addEvent(el, evname, func) {
	if (el.attachEvent)							// IE
		el.attachEvent("on" + evname, func);
	else if (el.addEventListener)				// Gecko / W3C
		el.addEventListener(evname, func, true);
	else 
		el["on" + evname] = func;
}

// checks if the specified object is a child of an element with the given parent_id
function hasParent(obj, parent_id) {
	while(obj.parentNode) {
		if (obj == $(parent_id)) 
			return true;
		obj = obj.parentNode;
	}
	return false;
}

function reloadPage() {
	alert("Sorry, your personalized feed settings are not available.  Please wait while the page is reloaded.");
	document.location.reload(true);
}

// this can potentially get called twice, once per column (to-do: eliminate redundant call)
function doUpdateOrder(col_id) {
	if (userData.getTabIndex(userData.currentTabId) == 0) {
		userData.resetTopFeedsForColumn("col_0");
		userData.resetTopFeedsForColumn("col_1");
	}
	RssCalls.editPosition($F("instance_id"), userData.currentTabId, "col0(" + Sortable.sequence("col_0") + "):col1(" + Sortable.sequence("col_1") + ")", function(req) {
		var response = req.responseText;
		var json_obj = response.parseJSON();
		if (json_obj.error)
			alert(json_obj.error);
		else if (json_obj.cookienotfound)
			reloadPage();
	});
}

function getSourceElement(e) {
	if (!e) e = event;
	return e.target || e.srcElement;
}

function getClickCoordinate(e) {
	var posx = 0;
	var posy = 0;
	
	if (!e) e = event;
	if (e.pageX || e.pageY) {
		posx = e.pageX;
		posy = e.pageY;
	}
	else if (e.clientX || e.clientY) {
		posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
		posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}

	var c = new Coordinate(posx, posy);
	return c;
}

function getKeyCode(e) {
	if (!e) e = event;
	return e.which || e.keyCode;
}

function cancelEvent(evt) {
	if ( evt && evt.stopPropagation )
		evt.stopPropagation();
	else if ( window.event )
		window.event.cancelBubble = true;
}