var FAAPI_URL = "faapi.xml.php";
var SELF_URL = "fm.html"
var HANDLER_FUNCS = new Array();
var tags = new Array();
var selectedTags = new Array();
var selectedFIDs = new Array();
var items = new Array();
var feeds = new Array();
var collapsed = false;
var last_fetchquery = '';
var last_fetchtime = 0;
var tag_fids = new Array();
var fid_tags = new Array();
var initialized = false;
var displayedFIDs = new Array();

function faapi_ajaxReceiver(){
	if (req.readyState!=4) return false;
	if (req.status!=200){
		debugOut("uhoh... got:"+req.status);
		//debugOut(req.responseText);
		//debugOut(req.statusText);
		return false;
	}
	profile("Got response");
	var xmlobj = req.responseXML;
	var resultObjects = xmlobj.getElementsByTagName("result");
	if (resultObjects.length) faapi_handleResults(resultObjects);
}


function faapi_parseResultObject(obj){
//parse faapi result object
	var data = new Array();
	
	data["code"] = parseInt(getSingleNodeText(obj,"code"));
	data["method"] = getSingleNodeText(obj, "method");
	return data;
}


function faapi_addTagFIDAssoc(fid,tag){
//add fid<->tag mapping in global cache
	feeds["fid:"+fid]["tags"] = addToArray(tag, feeds["fid:"+fid]["tags"]);
	tag_fids[tag] = addToArray(fid, tag_fids[tag]);
	tags = addToArray(tag, tags);
}


function faapi_removeTagFIDAssoc(fid,tag){
//remove fid<->tag mapping in global cache
	feeds["fid:"+fid]["tags"] = removeFromArray(tag, feeds["fid:"+fid]["tags"]);
	tag_fids[tag] = removeFromArray(fid, tag_fids[tag]);
	if (countAssocArray(tag_fids[tag])==0) tags = removeFromArray(tag, tags);
}


function faapi_purgeFID(fid){
//delete fid from local cache
	var feed = feeds['fid:'+fid];
	if (!feed) return false;
	for(var i=0;i<feed['tags'].length;i++) faapi_removeTagFIDAssoc(fid, feed['tags'][i]);
	feeds = removeKeyFromArray('fid:'+fid,feeds);
	selectedFIDs = removeFromArray(fid, selectedFIDs);
}

function faapi_handleError(result, obj){
//handle error result, extract error num, msg and call display func
	var errorNode = getNodeChildByTag(obj, "error");
	if (!errorNode) return false;
	
	var errmsg = getChildNodeText(errorNode, "errmsg");
	var errnum = parseInt(getChildNodeText(errorNode, "errnum"));
	
	debugOut("Got Error: ("+errnum+") "+errmsg);
	disp_showError(result["method"], result["code"], errmsg);
}


function faapi_extractFeeds(dataNode){
//extract feed objects from result, and parse into js-array
	var feedNodes = dataNode.getElementsByTagName("feed");
	var newfeeds = new Array();
	
	for(var i=0;i<feedNodes.length;i++){
		var feed = new Array();
		var fid = getChildNodeText(feedNodes[i], "feedid");
		feed["fid"] = fid;
		feed["name"] = getChildNodeText(feedNodes[i], "site_name");
		feed["url"] = getChildNodeText(feedNodes[i], "web_url");
		feed["comments"] = getChildNodeText(feedNodes[i], "comments");
		feed["updated"] = getChildNodeText(feedNodes[i], "updated");
		feed["fetched"] = getChildNodeText(feedNodes[i], "fetched");
		feed["tags"] = new Array();
		var tagNodes = feedNodes[i].getElementsByTagName('tag');
		for(var ti=0;ti<tagNodes.length;ti++) feed['tags'].push(getNodeText(tagNodes[i]));
		newfeeds['fid:'+fid]=feed;
	}
	newfeeds.length = feedNodes.length;
	return newfeeds;
}


HANDLER_FUNCS["listFeedTags"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	var tagNodes = dataNode.getElementsByTagName("tag");
	
	for(var i=0;i<tagNodes.length;i++){
		tags[i] = getNodeText(tagNodes[i]);
	}
	
	disp_updateFTagList();
}


HANDLER_FUNCS["listFeeds"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	feeds = faapi_extractFeeds(dataNode);
}


HANDLER_FUNCS["batchSubscribe"] = function(result,dataNode){
	profile("will handle "+result["method"]+" result, code="+result["code"]);
	
	var newfeeds = faapi_extractFeeds(dataNode);	//extract feed data
	var message = '';
	
	//go through new feeds
	for(var key in newfeeds){	
		//add to global feeds list
		feeds[key] = newfeeds[key];
		
		//add feed name to message
		message += newfeeds[key]["name"]+'<br />';

		//update fid<->tag mappings
		for(var ti=0;ti<feeds[key]['tags'].length;ti++){
			faapi_addTagFIDAssoc(feeds[key]['fid'],feeds[key]['tags'][ti]);
			debugOut("adding tag: "+feeds[key]['fid']+" -> "+feeds[key]['tags']+"("+feeds[key]['tags'].join(',')+')');
		}
	}
	
	//clear urls box
	setElementValue('addurl', '');
	
	//put together message
	if (newfeeds.length==0){
		message = 'No new feeds subscribed...';
	}else{
		message = 'The following feeds have been subscribed: <br />'+message;
	}
	
	//show message
	disp_showMessage(message);
	disp_showFeeds();
	//update tag<->feed associations
	//faapi_listTagFeedIDs();
}

HANDLER_FUNCS["unsubscribeFeedID"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	//hide message box, and refresh display
	hideElementID('msgbox');
	disp_showFeeds();
}

HANDLER_FUNCS["__server"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
}


HANDLER_FUNCS["fetchRecent"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	var itemNodes = dataNode.getElementsByTagName("item");
	var newItems = new Array();
	
	for(var i=0;i<itemNodes.length;i++){
		var item = faapi_parseItemXML(itemNodes[i]);
		newItems.push(item);
	}
	items = newItems;
	disp_updateEntries();
}


HANDLER_FUNCS["listFeedTagAssoc"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	var items = dataNode.getElementsByTagName("item");
	var tempfidtags = new Array();
	
	for(var i=0;i<items.length;i++){
		var fid = getChildNodeText(items[i], "fid");
		var tag = getChildNodeText(items[i], "tag");
		
		//if unknown feed ID, skip
		if (!feeds["fid:"+fid]) continue;
		
		//setup fid->tag mapping in temp array
		if (!tempfidtags["fid:"+fid]) tempfidtags["fid:"+fid] = new Array();
		tempfidtags["fid:"+fid].push(tag);
		
		//setup tag->fid mapping
		if (!tag_fids[tag]) tag_fids[tag] = new Array(fid);
		else tag_fids[tag].push(fid);
	}
	
	//overwite fid->tag mapping with values in temp array
	for(var fidkey in tempfidtags){
		if (!feeds[fidkey]) continue;
		feeds[fidkey]["tags"] = tempfidtags[fidkey];
	}
}

HANDLER_FUNCS["setFeedIDTags"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	var items = dataNode.getElementsByTagName("item");
	var tempfidtags = new Array();
	
	for(var i=0;i<items.length;i++){
		var fid = getChildNodeText(items[i], "fid");
		var tag = getChildNodeText(items[i], "tag");
		var op = getChildNodeText(items[i], "op");
		
		if (!feeds["fid:"+fid]) continue;
		
		//remove fid<->tag mapping
		if (op=="-"){
			faapi_removeTagFIDAssoc(fid,tag);
			//feeds["fid:"+fid]["tags"] = removeFromArray(tag, feeds["fid:"+fid]["tags"]);
			//tag_fids[tag] = removeFromArray(fid, tag_fids[tag]);
			//if (countAssocArray(tag_fids[tag])==0) tags = removeFromArray(tag, tags);
			
		//add fid<->tag mapping
		}else{
			faapi_addTagFIDAssoc(fid,tag);
			debugOut("tags:"+tags.join(','));
		}
	}
	
	//update feed tag browser column
	disp_updateFTagList();
	refresh();
}

HANDLER_FUNCS["listTagFeedIDs"] = function(result, dataNode){
	profile("will handle "+result["method"]+" result");
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	
	var fidNodes = dataNode.getElementsByTagName("fid");
	var fids = new Array();
	
	for(var i=0;i<fidNodes.length;i++){
		fids[i] = getNodeText(fidNodes[i]);
	}
	
	tag_fids[selectedTags.join(',')] = fids;
	disp_showFeeds();
}

HANDLER_FUNCS["login"] = function(result, dataNode){
	if (result["code"]<0){
		disp_showLoginScreen();
		faapi_handleError(result,dataNode);
	}else{
		disp_showMainScreen();
		if (!initialized) faapi_init();
	}
}

HANDLER_FUNCS["logout"] = function(result, dataNode){
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	document.location=SELF_URL;
	//init_vars();
	//disp_showLoginScreen();
}

HANDLER_FUNCS["markReadUpto"] = function(result, dataNode){
	if (result["code"]<0) return faapi_handleError(result,dataNode);
	last_fetchtime = 0;  //reset cache time
	fetchRecent(); //refresh
}

function faapi_parseItemXML(xml){
	var item = new Array();
	
	item["id"] = parseInt(getChildNodeText(xml, "itemid"));
	item["fid"] = parseInt(getChildNodeText(xml, "feedid"));
	item["title"] = getChildNodeText(xml, "item_title");
	item["url"] = getChildNodeText(xml, "item_url");
	item["text"] = getChildNodeText(xml, "item_text");
	item["date"] = getChildNodeText(xml, "created");
	item["tstamp"] = getChildNodeText(xml, "tstamp");
	return item;
}

function faapi_handleResults(resultObjects){
	for(var i=0;i<resultObjects.length;i++){
		var result = faapi_parseResultObject(resultObjects[i]);
		var dataNode = getNodeChildByTag(resultObjects[i], "data");
		
		profile("Got result: "+result["method"]+" "+result["code"]);
		//try{
			if (HANDLER_FUNCS[result["method"]])
				HANDLER_FUNCS[result["method"]](result, dataNode);
			else if (result["code"]<0)
				faapi_handleError(result, dataNode);
			else
				debugOut("No handler found for "+result["method"]);
		//}catch(e){
		//	debugOut("Exception: "+e.name+"-"+e.message);
		//}
	}
}

function faapi_login(username, password){
	var url=FAAPI_URL;
	var query="method=login&username="+username+"&password="+password;
	postXMLDoc(window, url, query, faapi_ajaxReceiver);
}

function faapi_init(){
	var url=FAAPI_URL+"?method=listFeedTags,listFeeds,listFeedTagAssoc,listTagFeedIDs&tags=";
	getXMLDoc(window, url, faapi_ajaxReceiver); 
	initialized = true;
	setInnerHTML('entryfiller', 'Loading Data... this may take a moment.');
}

function faapi_fetchRecent(p){
	var url=FAAPI_URL+"?method=fetchRecent";
	var now = getMS();
	
	if (p['fids']) url+='&fids='+p['fids'].join(',');
	url+='&tags='+p['tags'].join(',');
	url+='&limit='+p['limit'];
	if (p['since']) url+='&since='+p['since'];
	url+='&showdeleted='+p['showdeleted'];
	
	if (last_fetchquery==url && (now - last_fetchtime)<300000) return false;
	debugOut("Last fetched: "+last_fetchtime+" Now: "+now);
	last_fetchquery=url;
	last_fetchtime = getMS();

	getXMLDoc(window, url, faapi_ajaxReceiver);
	return true;
}

function faapi_batchSubscribe(urls,tags){
	var url=FAAPI_URL;
	var query="method=batchSubscribe&tags="+URLencode(tags);
	var urlstr='';
	
	for(var i=0;i<urls.length;i++) urls[i] = '"'+urls[i]+'"';
	query+='&urls='+URLencode(urls.join(','));
	debugOut(query);
	postXMLDoc(window, url, query, faapi_ajaxReceiver);
}

function faapi_unsubscribeFeedID(fid){
	var query="method=unsubscribeFeedID&fid="+fid;
	postXMLDoc(window, FAAPI_URL, query, faapi_ajaxReceiver);
	faapi_purgeFID(fid);
}

function faapi_listTagFeedIDs(){
	var url=FAAPI_URL+"?method=listFeeds,listTagFeedIDs&tags="+selectedTags.join(",");
	getXMLDoc(window, url, faapi_ajaxReceiver);
}

function faapi_setFeedComment(fid, comment){
	var url=FAAPI_URL;
	var query="method=setFeedComment&fid="+fid+"&comment="+comment;
	postXMLDoc(window, url, query, faapi_ajaxReceiver);
}

function faapi_setFeedIDTags(fid, tags){
	var query="method=setFeedIDTags&fid="+fid+"&tags="+tags;
	postXMLDoc(window, FAAPI_URL, query, faapi_ajaxReceiver);
}

function faapi_logout(){
	var url=FAAPI_URL+"?method=logout";
	getXMLDoc(window, url, faapi_ajaxReceiver);
}

function faapi_register(params){
	var url=FAAPI_URL;
	var query="method=register,login";
	query+="&username="+params["username"];
	query+="&password="+params["password"];
	query+="&password2="+params["password2"];
	query+="&email="+params["email"];
	query+="&first_name="+params["first_name"];
	query+="&last_name="+params["last_name"];
	postXMLDoc(window, url, query, faapi_ajaxReceiver);
}

function faapi_markReadUpto(fids,taglist,time){
	var url=FAAPI_URL;
	var query="method=markReadUpto";
	if (fids && fids.length>0) query+='&fids='+fids.join(',');
	if (taglist && taglist.length>0) query+='&tags='+taglist.join(',');
	query+='&timestamp='+time;
	debugOut(query);
	postXMLDoc(window, url, query, faapi_ajaxReceiver);
}

function faapi_getCachedTagFIDs(tags){
	var result = new Array();
	
	//if no tags, return all fids
	if (!tags || tags.length==0){
		for(var fid in feeds){
			result.push(feeds[fid]["fid"]);
		}
		debugOut('getCachedTagFIDs ret:'+result.join(','));
		return result;
	}
	
	//return unique fids in given tags
	for(var t=0; t<tags.length;t++){
		var tag = tags[t];
		for(var i=0; i<tag_fids[tag].length; i++){
			var fid = tag_fids[tag][i];
			result = addToArray(fid, result);
		}
	}
	
	return result;
}


//---------------------------
//   DISPLAY FUNCTIONS
//---------------------------
var contentDivs = ["entriesarea","feedsarea"];
var tabIDs = {"entriesarea":"viewertab", "feedsarea":"managertab"}
var curmode = "entries";
var browsershown = true;

function sortFeedIDsByName(fids){
	var names = new Array();
	var name_fid = new Array();
	var result = new Array();
		
	//create array of site names, and name->id lookups
	for(var i=0;i<fids.length;i++){
		var fid = fids[i];
		var feed = feeds["fid:"+fid];
		if (!feed) debugOut("missing fid:"+fid);
		var name = feed["name"].toLowerCase();
		names.push(name);
		name_fid[name] = fid;
	}
	
	//sort names (alphabetically)
	names.sort();
	
	//compose sorted fid list
	for(var i=0;i<names.length;i++){
		var name = names[i];
		var fid = name_fid[name];
		result.push(fid);
	}
	
	return result;
}

function disp_showRegisterScreen(){
	hideElementID("authtools");
	hideElementID("mainarea");
	hideElementID("tabbar");
	hideElementID("loginbox");
	showElementID("pubtools");
	showElementID("regbox");
}

function disp_showLoginScreen(){
	hideElementID("authtools");
	hideElementID("mainarea");
	hideElementID("tabbar");
	hideElementID("regbox");
	showElementID("pubtools");
	showElementID("loginbox");
}

function disp_showMainScreen(){
	showElementID("authtools");
	showElementID("mainarea");
	showElementID("tabbar");
	hideElementID("regbox");
	hideElementID("pubtools");
	hideElementID("loginbox");
	hideElementID("errorbox");
}

function disp_switchContentDiv(newid){
	for (var i=0;i<contentDivs.length;i++){
		var elem = getElement(window, contentDivs[i]);
		if (!elem) continue;
		
		//is it the new active area?
		if (contentDivs[i]==newid){
			//show div
			elem.style.display = "";
			
			//make corresponding tab active
			setElementIDClass(tabIDs[contentDivs[i]], "activetab");
			
		//not active area
		}else{
			//hide div
			elem.style.display = "none";

			//make corresponding tab inactive
			setElementIDClass(tabIDs[contentDivs[i]], "inactivetab");
		}
	}
}

function disp_showError(method, code, message){
	var html='';
	
	if (method) html+='<b>Method:</b> '+method;
	if (code) html+='&nbsp;&nbsp;<b>Code:</b> '+code+'<br />';
	if (message) html+='<b>Message:</b><br />'+message;
	
	showElementID("errorbox");
	setInnerHTML("errormsgdiv", html);
}

function disp_showMessage(message){
	showElementID('msgbox');
	setInnerHTML('msgdiv', message);
}

function disp_formTagCheckboxes(checktags){
	html='';
	debugOut("checktags:"+checktags.join(','));
	for(var i=0;i<tags.length;i++){
		html+='<span class="nobr" style="padding-left:10px"><label>';
		html+='<input type="checkbox" name="feedtagcb" value="'+i+'" '+(isInArray(tags[i],checktags)?'CHECKED':'')+' />'+tags[i];
		html+='</label></span>';
	}
	html+='<span class="nobr" style="padding-left:10px"><label>';
	html+='<input type="checkbox" name="feedtagcb" value="-1" />';
	html+='New:</label><input type="text" name="feedtagnew" id="feedtagnew"></span>';
	return html;
}

function disp_updateFTagList(){
	var tbElem = getElement(window, "tagsbrowser");
	var html='';
	
	//display feed tag (category)list
	if (tags.length>0){
		tbElem.options.length = 0;
		appendOption(tbElem, '', 'All', (selectedTags.length==0));
		for(var i=0;i<tags.length;i++){
			appendOption(tbElem, i, tags[i], isInArray(tags[i], selectedTags));
		}
		tbElem.size=6;
	}else if (browsershown){
		//hide browser entirely
		toggleBrowser(1);
	}
	
	//update add form
	var cbaareaElem = getElement(window, "feedtagcbs");
	html=disp_formTagCheckboxes([]);
	cbaareaElem.innerHTML=html;
}

function disp_updateEntries(){
	var areaElem = getElement(window, "entries");
	var html='';
	var contentStyle=(collapsed?'style="display:none"':'');
	var hideStyle=(collapsed?'':'style="display:none"');
	
	//make sure entries area is visible
	disp_switchContentDiv("entriesarea");
	curmode = "entries";
	
	//reset array of displayed FIDs
	displayedFIDs = new Array();
	
	//if no items, just show filler
	if (items.length==0){
		hideElementID("entries");
		showElementID("entryfiller");
		setInnerHTML('entryfiller', 'No items to display...');
		return;
	}
	
	//hide filler
	hideElementID("entryfiller");
	showElementID("entries");

    debugOut('have '+items.length);

	//crank out html for items
	for(var i=0;i<items.length;i++){
		var fid = items[i]["fid"];
		var feed = feeds["fid:"+fid];
		var divHTML = "\n"+'<div class="entry" id="entry'+fid+'">';
		if (items[i]["title"].length==0) items[i]["title"] = "&lt;&lt;Untitled&gt;&gt;";
		if (!feed) continue;
		if (!feed.url) continue;

		//title
		divHTML+='<div class="entrytitle">';
		divHTML+='<a href="'+items[i]["url"]+'" class="titlelink">'+items[i]["title"]+'</a>';
		divHTML+='</div>';
		
		//tools
		divHTML+='<div class="entrytools">';
		divHTML+='&nbsp;<a href="javascript:showContent('+i+');" class="miniwidget" '+hideStyle+' id="showlink'+i+'">show</a>';
		divHTML+='&nbsp;<a href="javascript:collapseContent('+i+');" class="miniwidget" '+contentStyle+' id="collapselink'+i+'">collapse</a>';
		divHTML+='&nbsp;|&nbsp;';
		divHTML+='<a class="miniwidget" href="javascript:doDeleteItem('+i+');" id="deletelink'+i+'">delete</a>';
		divHTML+='&nbsp;|&nbsp;';
		divHTML+='<span id="entrytool'+i+'" style="display:none">';
		divHTML+='<span id="entrytoolsel'+i+'"></span>';
		divHTML+='<a class="miniwidget" href="javascript:toggleToolPalette(\'entrytool\','+i+');">&gt;&gt;edit</a>';
		divHTML+='</span>';
		divHTML+='<a class="miniwidget" href="javascript:toggleToolPalette(\'entrytool\','+i+');" id="entrytoollnk'+i+'">&lt;&lt;edit</a>';
		divHTML+='</div>';
		
		//date, site name
		divHTML+='<div class="entrydate">'+items[i]["date"]+'</div>';
		divHTML+='<div class="feedname"><a href="'+feed["url"]+'" id="feedname">'+feed["name"]+'</a></div>';
		
		//content
		divHTML+='<div class="entrycontent" '+contentStyle+' id="econtent'+i+'">';
		divHTML+=items[i]["text"];
		divHTML+='</div>';
		divHTML+='</div>'+"\n";
		
		html+=divHTML;
		displayedFIDs = addToArray(fid, displayedFIDs);
	}
	
	//stick 'em in there...
	areaElem.innerHTML = html;
	profile("display done");
}

function disp_showFeedList(fids){
	var html='';
	var feedsElem = getElement(window, "feeds");
	
	//if no fids, show filler
	if (fids.length==0){
		showElementID("feedsfiller");
		return;
	}
	
	//make sure filler is gone
	hideElementID("feedsfiller");
	
	//display feeds!
	for(var i=0;i<fids.length;i++){
		var fid = fids[i];
		var feed = feeds["fid:"+fid];
		if (selectedFIDs.length>0 && !isInArray(fid, selectedFIDs)) continue;
		
		html += '<div class="entry">';
		html += '  <div class="feeditem">';
		html += '    <a href="'+feed["url"]+'" id="feedname">'+feed["name"]+'</a>';
		html += '    <span id="fdcmnt'+fid+'">'+feed["comments"]+'</span>';
		html += '  </div>';
		
		//feed item tools
		html += '  <div id="fdtools'+fid+'" class="fditemtool">';
		
			//edit palette toggler
			html += '    <a class="miniwidget" href="javascript:toggleToolPalette(\'editfdid\', '+fid+');" id="editfdidlnk'+fid+'">&lt;&lt;edit</a>';
		
			//edit palette
			html += '    <span id="editfdid'+fid+'" style="display:none">';
			html += '    <span id="editfdidsel'+fid+'"></span>';
			html += '    <a class="miniwidget"  href="javascript:toggleToolPalette(\'editfdid\', '+fid+');">&gt;&gt;edit</a>';
			html += '    </span>';		
		html += '  </div>';
		
		//tag check box area
		html += '  <div id="ftagcbarea'+fid+'"></div>';
			
		//mod dates
		html += '  <div class="feeddate'+fid+'" style="display:none">';
			html += '    <span class="nobr"><span id="fupdatelabel">Updated:</span><span id="fupdated">'+feed["updated"]+'</span></span>';
			html += '    <span class="nobr"><span id="ffetchedlabel">Cached:</span><span id="ffetched">'+feed["fetched"]+'</span></span>';
		html += '  </div>';
		html += '</div>';
	}
	
	feedsElem.innerHTML = html;
}

function disp_showFeeds(){
	var fids = faapi_getCachedTagFIDs(selectedTags);
	fids = sortFeedIDsByName(fids);
	if (curmode=="feeds") disp_showFeedList(fids);
	disp_updateFeedBrowser(fids);
}

function disp_showFeedsFID(fids){
	//sort
	fids = sortFeedIDsByName(fids);

	if (curmode=="feeds") disp_showFeedList(fids);
	disp_updateFeedBrowser(fids);
}


function disp_updateFeedBrowser(fids){
	var fbElem = getElement(window, "feedsbrowser");
	
	//construct select
	fbElem.options.length=0;
	appendOption(fbElem, '', 'All', (selectedFIDs.length==0));
	for(var i=0;i<fids.length;i++){
		var fid = fids[i];
		var feed = feeds["fid:"+fid];
		appendOption(fbElem, fid, feed["name"], isInArray(fid,selectedFIDs));
	}
	if (fids.length>0) fbElem.size=6;
}

function disp_formEntryHTML(item){
	
}


//---------------------------
//   EVENT HANDLER FUNCTIONS
//---------------------------

function loginClicked(){
//Handle "login" button click.  Extract username and password,
//make sure they're there, and pass to faapi caller func
	var uElem = getElement(window, "loginusername");
	var pElem = getElement(window, "loginpassword");
	var username = uElem.value;
	var password = pElem.value;
	
	if (username.length==0){
		alert("Please enter user name");
		return false;
	}
	if (password.length==0){
		alert("Please enter password");
		return false;
	}
	
	//alert("Log in as: "+username+":"+password);
	faapi_login(username, password);
	
	setInnerHTML("toolblurb", username+"'s feed muncher!");
}


function registerClicked(){
//Handle "register" button click.  perform basic checks
//and pass to faapi caller func
	var p = new Array();
	p["first_name"] = getElementValue("regfname");
	p["last_name"] = getElementValue("reglname");
	p["email"] = getElementValue("regemail");
	p["username"] = getElementValue("regusername");
	p["password"] = getElementValue("regpassword");
	p["password2"] = getElementValue("regpassword2");
	
	if (p["username"].length==0){
		alert("Please enter user name");
		return false;
	}
	if (p["password"].length==0){
		alert("Please enter password");
		return false;
	}
	if (p["password"]!=p["password2"]){
		alert("Password mismatch.  Make sure you enter the same passwords for \"Password\" and \"Confirm Password\" fields");
		return false;
	}
	
	//alert("Log in as: "+username+":"+password);
	faapi_register(p);
	
	//setInnerHTML("toolblurb", username+"'s feed muncher!");
}



function logoutClicked(){
//login link clicked... just call faapi caller
	faapi_logout();
}

function fetchRecent(){
	var p = new Array();
	var query='method=fetchRecent';
	
	//set fids and tags
	if (selectedFIDs.length>0) p["fids"] = selectedFIDs;
	p["tags"] = selectedTags;
	
	//set fetch num limit
	p["limit"] = getElementValue('dispnumtxt');
	
	//check n {days|hours|weeks} since field
	var numsince = getElementValue('sincenumtext');
	if (numsince) p['since'] = numsince+' '+getElementValue('timescalesel');
	
	//check "show deleted" checkbox
	var cb = getElement(window, 'showdeletedcb');
	p['showdeleted'] = (cb.checked?'1':'0');
		
	return faapi_fetchRecent(p);
}

function refreshItems(){
//wrapper for fetchRecent caller, the faapi handler will do the rest
	if (fetchRecent()){
		hideElementID('entries');
		setInnerHTML('entryfiller', 'Fetching items...');
		showElementID('entryfiller');
	}
}

function refresh(){
	if (curmode=="entries") showItems();
	else if (curmode=="feeds") showFeeds();
}

function showItems(){
//Main entry point for switching from feed management
//screen to aggregator screen
	disp_switchContentDiv("entriesarea");
	curmode = "entries";
	refreshItems();
}


function showFeeds(){
//Main entry point for switching from aggregator screen to
//feed management screen

	disp_switchContentDiv("feedsarea");
	curmode = "feeds";
	if (feeds.length==0) faapi_listTagFeedIDs();
	else disp_showFeeds();
}


function toggleToolPalette(id, n){
//Handle clicks to tool palette togglers. 
//Display action menu and hide original link.
	var spanname = id+n;
	var selspan = id+'sel'+n;
	var linkname = id+'lnk'+n;
	var html='';
	if (id=="entrytool"){
		html += '<select onChange="fdAction(\'entrytool\','+n+');" id="fdacts'+n+'">';
		html += '<option value="">select action...</option>';
		html += '<option value="mf">mark all in feed as read</option>';
		html += '<option value="ma">mark all shown as read</option>';
		html += '<option value="tb">tag and bookmark</option>';
		html += '<option value="dl">delete</option>';
		html += '</select>';
	}else if (id=='editfdid'){
		html += '<select onChange="fdAction(\'editfdid\','+n+');" id="fdacts'+n+'">';
		html += '<option value="">select action...</option>';
		html += '<option value="ec">edit comments</option>';
		html += '<option value="et">edit categories</option>';
		html += '<option value="sm">show modified</option>';
		html += '<option value="os">open site</option>';
		html += '<option value="us">unsubscribe feed</option>';
		html += '</select>';
	}
	toggleElementDisplay(spanname);
	toggleElementDisplay(linkname);
	setInnerHTML(selspan, html);
}


function fdAction(id,n){
//Handle selections in the feed action menu
    var elem = getElement(window, "fdacts"+n);
    if (!elem) return false;
    
    switch(elem.value){
    	case 'ec': showFCEdit(n); break;
    	case 'et': showFTEdit(n); break;
    	case 'mf': faapi_markReadUpto([items[n]["fid"]], false, items[n]["tstamp"]); break;
    	case 'ma': faapi_markReadUpto(displayedFIDs, false, items[n]["tstamp"]); break;
    	case 'us': unsubscribeFeedID(n); break;
    }
    
	//collapse edit palette
	toggleToolPalette(id, n);
	
}

function showFTEdit(fid){
//Handle "edit categories" action in feeds list (FT=Feed Tag)
	var divElem = getElement(window, "ftagcbarea"+fid);
	if (!divElem) debugOut("no elem in showFTEdit()");
	var html='';
	
	html+='<form name="ftagcbform'+fid+'"><br />';
	html+=disp_formTagCheckboxes(feeds["fid:"+fid]["tags"]);
	html+='<input type="button" onClick="doFTEdit('+fid+')" value="update">';
	html+='<input type="button" onClick="setInnerHTML(\'ftagcbarea'+fid+'\',\'\');" value="cancel">';
	html+='</form>';
	setInnerHTML("ftagcbarea"+fid, html);
}


function doFTEdit(fid){
//Handle "update" click in feed tag/category editing form
	var theform = eval("document.ftagcbform"+fid);
	if (!theform) debugOut("NO form in doFTEdit()");
	var newtags = new Array();
	
	//extract selected tags
	for(var i=0;i<theform.elements.length;i++){
		var element =theform.elements[i];
		if (element.name=='feedtagcb'&&element.checked){
			if (element.value>=0)
				newtags.push(tags[element.value]);
			else if (element.value==-1 && theform.feedtagnew.value){
				newtags.push(theform.feedtagnew.value);
			}
		}
	}

	//make faapi call	
	faapi_setFeedIDTags(fid, newtags.join(','));
	
	//destroy checkbox area
	setInnerHTML("ftagcbarea"+fid, '');
}


function showFCEdit(fid){
//Handle "edit comment" action in feeds list
//change comment into a text box and show "save|cancel" links
	var elem = getElement(window, "fdcmnt"+fid);
	if (!elem) return false;
	var curval = elem.innerHTML;
	var html = '';

	//show edit box
	html = '<input type="text" id="fcedittxt'+fid+'" value="'+curval+'" />';
	html+= '<a href="javascript:saveFComment('+fid+');" class="miniwidget">save</a>';
	html+= '|<a href="javascript:saveFComment('+fid+');" class="miniwidget">cancel</a>';
	elem.innerHTML = html;
}


function unsubscribeFeedID(fid){
	disp_showMessage('Unsubscribing '+feeds['fid:'+fid]["name"]);
	faapi_unsubscribeFeedID(fid);
}


function cancelFComment(fid){
//Handle click to "cancel" link in feed comment editing screen
	var feed = feeds['fid:'+fid];
	if (!feed) return false;
	
	setInnerHTML("fdcmnt"+fid, feed["comments"]);
}


function saveFComment(fid){
//Respond to clicks on "save" link in comment editing screen
//Changes textbox into a normal display, and if contents were
//changed, makes faapi call and updates local cache
	var elem = getElement(window, "fdcmnt"+fid);
	if (!elem) return false;
	var inputElem = getElement(window, "fcedittxt"+fid);
	if (!inputElem) return false;
	var comment = inputElem.value;
	
	//set comment text to new value
	elem.innerHTML = comment;
	
	//comment modified?
	if (feeds["fid:"+fid]["comments"] != comment){
		//make FAAPI call to server
		faapi_setFeedComment(fid, comment);
	
		//update local cache
		feeds["fid:"+fid]["comments"] = comment;
	}
}


function tagsBrowserChanged(){
//Handle change to the tags select box of the browser
//Update the feeds column of the browser, as well
//as the main content area
	var tbElem = getElement(window, "tagsbrowser");
	
	selectedFIDs.length = 0;
	selectedTags.length = 0;
	for(var i=0;i<tbElem.options.length;i++){
		if (tbElem.options[i].selected && tbElem.options[i].value!=''){
			selectedTags = addToArray(tags[tbElem.options[i].value], selectedTags);
		}
	}
	
	//change feeds in browser from cache
	disp_showFeedsFID(faapi_getCachedTagFIDs(selectedTags));

	//update main display area
	if (curmode=="entries") refreshItems();
	else if (curmode=="feeds") showFeeds();
}


function feedsBrowserChanged(){
//Handle changes to the feeds select box of the browser
//If specific items were selected, add feed IDs to 
//global array (selectedFIDs)
	var fbElem = getElement(window, "feedsbrowser");
	
	
	selectedFIDs.length=0;
	for(var i=0;i<fbElem.options.length;i++){
		if (fbElem.options[i].selected && fbElem.options[i].value!=''){
			debugOut("Adding: "+fbElem.options[i].value);
			selectedFIDs = addToArray(fbElem.options[i].value, selectedFIDs);
		}
	}

	//update main display area
	if (curmode=="entries") refreshItems();
	else if (curmode=="feeds") showFeeds();
}


function doAddNewFeed(){
//Handle clicks to "Subscribe" button in "Subscribe Feed/Site" form
//Detect which tag checkboxes are clicked in, split contents of the URLs
//textarea into an array, pass to faapi caller
	var theform = document.addfeedform;
	if (!theform) debugOut("couldn't get form");
	var newtags = new Array();
	var urls = '';
	
	for(var i=0;i<theform.elements.length;i++){
		var element =theform.elements[i];
		if (element.name=='feedtagcb'&&element.checked){
			if (element.value>=0)
				newtags.push(tags[element.value]);
			else if (element.value==-1 && theform.feedtagnew.value){
				newtags.push(theform.feedtagnew.value);
			}
		}
		if (element.name=='addurl'&&element.value){
			urls = element.value;
			//element.value='';
		}
	}
	
	var addurls = urls.split("\n");
	if (addurls.length>0){
		disp_showMessage('Subscribing... this may take a few moments.');
		faapi_batchSubscribe(addurls,newtags.join(','));
	}
	//debugOut("got "+addurls.length+" URLs and "+newtags.length+" tags");
}


function showContent(i){
//Show contents of i-th post of aggregator screen, 
//hide the "show" link, and show the "collapse" link
	showElementID("econtent"+i);
	hideElementID("showlink"+i);
	showElementID("collapselink"+i);
}


function collapseContent(i){
//Hide contents of i-th post of aggregator screen, 
//show the "show" link, and hide the "collapse" link
	hideElementID("econtent"+i);
	showElementID("showlink"+i);
	hideElementID("collapselink"+i);
}


function toggleEntryCollapse(){
//Collapse or show all posts, and toggle link
	var newval = (collapsed?"":"none");
	var newshow = (collapsed?"none":"");
	
	for(var i=0;i<items.length;i++){
		setElementDisplay("econtent"+i, newval);
		setElementDisplay("showlink"+i, newshow);
		setElementDisplay("collapselink"+i, newval);
	}
	
	collapsed = !collapsed;
	
	setInnerHTML("collapseAllLink", (collapsed?"Expand All":"Collapse All"));
}


function toggleBrowser(n){
//show/hide browser, and change text of toggle link appropriately
	var divElem = getElement(window, "browserdiv"+n);
	if (!divElem) return;
	var curval = divElem.style.display;
	var newval = (curval==""?"none":"");
	
	divElem.style.display=newval;
	if (newval==""){
		browsershown = false;
		setInnerHTML("togglebrowser1","Hide Browser");
		setInnerHTML("togglebrowser2","Hide Browser");
	}else{
		browsershown = true;
		setInnerHTML("togglebrowser1","Show Browser");
		setInnerHTML("togglebrowser2","Show Browser");
	}
	
	return;
}

function init_vars(){
	tags = new Array();
	selectedTags = new Array();
	selectedFIDs = new Array();
	items = new Array();
	feeds = new Array();
	collapsed = false;
	last_fetchquery = '';
	last_fetchtime = 0;
	tag_fids = new Array();
	fid_tags = new Array();
	initialized = false;
	
	setInnerHTML('entries', '');
	setInnerHTML('feeds', '');
}

function init(){
    var sess = getCookie('faapi_session_id');
	if (sess) faapi_login('','');
	disp_switchContentDiv("entriesarea");
    disp_showLoginScreen();
	curmode = "entries";
}

