window.extend
({
	getHeight: function()
	{
		if (window.innerHeight) return window.innerHeight;
		else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
		else if (document.body) return document.body.clientHeight;
		else return 0;
	},
	
	getWidth: function()
	{
		if (window.innerWidth) return window.innerWidth;
		else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;
		else if (document.body) return document.body.clientWidth;
		else return 0;
	},
	
	is_mac: ((navigator.appVersion.indexOf("Mac") > -1) ? true : false)
});

Yomo = 
{
	GATEWAY : '/subscription.ajax.php',
	TRACKER : false,
	TEMP : {},
	DATA : {},
	LOG_DATA: [],
	IS_HOME : false,
	IS_TEMP : false,
	IS_READER : false,
	REQUEST_FAILURE : "Request failed, please try again",
	SUCCESS_DELAY: 3,
	FAILURE_DELAY: 5,
	qs : {},
	
	TIPS_DELAY: 3000,
	TIPS: 
	[
		['/includes/home-bundle.tip.php',false,520,360]
		
	],
	
	HEADER: 'header',
	PRIMARY_HEAD: 'subscription-ctrl',
	PRIMARY_BODY_CONTAINER: 'subscription',
	SECONDARY_PANE: 'secondary-pane',
	SECONDARY_NAV: 'nav',
	SECONDARY_HEAD: 'head',
	SECONDARY_BODY_CONTAINER: 'body-container',
	SECONDARY_BODY: 'body',
	
	COLLAPSED_UNBUNDLED : '/images/collapsed.gif',
	EXPANDED_UNBUNDLED : '/images/expanded.gif',
	
	COLLAPSED_UNSHARED : '/images/collapsed_unshared.gif',
	COLLAPSED_SHARED : '/images/collapsed_shared.gif',
	COLLAPSED_SUBSCRIBED : '/images/collapsed_unshared.gif',
	
	EXPANDED_UNSHARED : '/images/expanded_unshared.gif',
	EXPANDED_SHARED : '/images/expanded_shared.gif',
	EXPANDED_SUBSCRIBED : '/images/expanded_unshared.gif',
	
	BUNDLE_HOME_ACTIVE : '/images/house.png',
	BUNDLE_HOME_INACTIVE : '/images/house_inactive.png',

	BUNDLE_PUBLISHED_ACTIVE : '/images/share.gif',
	BUNDLE_PUBLISHED_INACTIVE : '/images/share_inactive.gif',
	
	getBundleData : function(bundle_id)
	{
		if ($chk(Yomo.DATA.bundles))
		{
			for (var i in Yomo.DATA.bundles)
			{
				var b = Yomo.DATA.bundles[i];
				if (b.bundle_id == bundle_id)
				{
					b.is_owner = b.owner == Yomo.DATA.user_id ? true : false ;
					b.is_private = b['private'] ? true : false ;
					return b;
				}
			}
		}
	},
	
	removeBundleData : function(obj)
	{
		if (obj.bundle_id)
		{
			if ($chk(Yomo.DATA.bundles))
			{
				for (var i in Yomo.DATA.bundles)
				{
					if(obj.bundle_id == Yomo.DATA.bundles[i].bundle_id)
					{
						delete Yomo.DATA.bundles[i];
						return true;
					}
				}
			}
		}
		
		return false;
	},
	
	getFeedData : function(obj)
	{
		// change this ... perfered input is object
		// fix, search and replace all uses using feed_id instead of object style

		if ($type(obj) != "object") obj = { feed_id: obj };

		if ($chk(Yomo.DATA.bundles))
		{
			for (var i in Yomo.DATA.bundles)
			{
				var b = Yomo.DATA.bundles[i];
				
				// if not the owner
				if (b.owner != Yomo.DATA.user_id) continue;
				
				if  (b.feeds)
				{
					var ocnt = b.feeds.length;
					for (var o=0; o<ocnt; o++)
					{
						var f = b.feeds[o];
						if (f.feed_id == obj.feed_id || f.xml_url == obj.xml_url)
						{
							f.unbundled = b.unbundled;
							return f;
						}
					}
				}
			}
		}
	},
	
	resize : function()
	{
		// temp-header
		if ($('temp-header')) var ths = $('temp-header').getSize();
		
		// header size
		var hs = $('header').getSize();
		
		// window size
		var ws = window.getSize();
		
		// height, 15 = margin + shadow-height
		var h = ws.size.y - (hs.size.y + (ths?ths.size.y:0) + 15);
		
		// setup
		$('primary-pane').setStyle('height',h);
		$('secondary-pane').setStyle('height',h);
		
		if ($('debug-pane')) $('debug-pane').setStyle('height',h-10);

		// secondary body position
		var sbp = $('body-container').getPosition();
		
		// secondary pane position
		var spp = $('secondary-pane').getPosition();
		
		// offset
		var offset = sbp.y-spp.y;

		// setup
		// -1 accounts for border height under heading
		$('body-container').setStyle('height',h-offset-1);
		
		// subscription position
		var sp = $('subscription').getPosition();
		
		// subscription size
		var ppp = $('primary-pane').getPosition();
		
		offset = sp.y-ppp.y;
		
		$('subscription').setStyle('height',h-offset);
		
		Yomo.fireEvent('resize');
	},
	
	sayHello : function()
	{
		var fx = new Fx.Style($('hello'), 'opacity', {duration: 1000, wait: false}).set(0);
		
		var t = $(Yomo.HEADER).getTop();
		
		$('hello').setStyles
		({
			'top' : (t+5) + 'px'
			, 'left' : 140 + 'px'
		});
		
		(function(){ fx.start(1); }).delay(5000);
		(function(){ fx.start(0); }).delay(30000);
	},

	/*
		Function: getParentWithClass
		Used to recursively try to find a parent with
		the given class name.
		
		Params:
		elem - HtmlNode : HTML elemenet
		className - String : Css class name
		
		Returns:
		Parent HtmlNode or false otherwise
		
		Author:
		Dimas Begunoff
	*/
	getParentWithClass : function(elem,className)
	{
		if ($(elem).getParent)
		{
			var p = $(elem).getParent();
			if (p.hasClass && p.hasClass(className)) return p;
			else return this.getParentWithClass(p,className);
		}
		
		return false;
	},
	
	validate : function(obj)
	{
		return this.validateForm(obj.form,obj.confirm);
	},
	
	showStatus : function(options)
	{
		// elem, success, message
		var fx = new Fx.Style(options.elem,'opacity',{duration: 500, wait: false, onStart: function(){ $(options.elem).setStyle('display','') }}).set(0);
		
		var src = !$chk(options.success) ? "loading" : (options.success ? "good" : "bad") ;
		
		$(options.elem).setHTML('<img src="images/status_'+ src +'.gif" align="absmiddle" width="16" height="16"/>&nbsp;&nbsp;' + options.message);
		fx.start(1);
	},
	
	hideStatus2 : function(elem)
	{
		// elem, success, message
		var fx = new Fx.Style(elem,'opacity',{duration: 500, wait: false, onComplete: function(){ $(elem).setStyle('display','none') }}).set(1);
		fx.start(0);
	},

	setStatus : function(msg,success,delay)
	{
		/*
			second arg is success instead of error so that
			by default everything comes in as an error unless
			stated otherwise, this makes spotting incorrect
			logic easier, ie: if programmer forgets to add
			the error flag
		*/
		
		if ($('yomo-status-inner'))
		{	
			// cancel hiding
			if ($defined(this.hideStatusDelay)) $clear(this.hideStatusDelay);
	
			// create effect
			if (!$defined(this.fx)) this.fx = new Fx.Style('yomo-status', 'opacity', {duration: 500, wait: false}).set(0);
			
			// status image to display
			var imgSrc = !$chk(success) ? "loading" : (success ? "good" : "bad") ;
			if (!$chk(delay)) delay = success ? 3 : 5 ;
	
			// set message and show
			$('yomo-status-inner').setHTML('<img src="/images/status_'+ imgSrc +'.gif" align="absmiddle" alt="" width="16" height="16" style="margin-right:5px;" />' + msg);
			this.fx.start(1);
			
			// delay hide
			if ($defined(success)) { this.hideStatusDelay = (function(){this.hideStatus()}).delay(delay*1000,this); }
		}
	},
	
	hideStatus : function()
	{
		this.fx.start(0);
	},
	
	load : function(url,obj)
	{
		var load_time = $time();
		
		var qs = this.parseQueryString(url.split('?').getLast());
		var container = $chk(qs.container) ? qs.container : this.SECONDARY_PANE ;
		
		if (obj && obj.event) 
		{
			new Event(obj.event).stop();
			delete obj.event;
		}
		
		if (obj && obj.container) 
		{
			container = obj.container;
			delete obj.container;
		}
		
		new Ajax(url,
		{
			method: "get"
			, evalScripts: 1
			, update: container
			, onComplete: function()
			{
				Yomo.setLinks();
				
				$(Yomo.SECONDARY_BODY_CONTAINER).scrollTop = 0;
				
				if (container != Yomo.SECONDARY_BODY_CONTAINER) Yomo.resize();
				
				url = url.indexOf('://') > -1 ? url.substr(url.indexOf('://')+3) : url ;
				url = url.substr(url.indexOf('/'));
				
				Yomo.debug({ label:url, start:load_time });
				
				Yomo.fireEvent('load',
				{
					url: url
				});
				
				Yomo.fireEvent('contentChange',
				{
					target: container
				});
			}
		}).request();
	},
	
	link_click : function(e)
	{
		new Event(e).stop();
		Yomo.load(this.href);
	},
	
	setLinks : function()
	{
		var links = $$('a.link');
		links.removeEvent('click',Yomo.link_click);
		links.addEvent('click',Yomo.link_click);
	},
	
	setNav : function (elem)
	{
		$('tabs').getElements('a').removeClass('active');
		if ($(elem)) $(elem).addClass('active');
	},
	
	parseQueryString : function(qs) 
	{
		var params = new Object();
		
		if (qs == null) qs=location.search.substr(1);
		if (qs.length == 0) return;
	
		// turn <plus> back to <space>
		// see: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1
		qs = qs.replace(/\+/g, ' ')
		var args = qs.split('&') // parse out name/value pairs separated via &
		
		// split out each name=value pair
		for (var i=0; i<args.length; i++) 
		{
			var value;
			var pair = args[i].split('=');
			var name = unescape(pair[0]);
	
			if (pair.length == 2) value = unescape(pair[1]);
			else value = name;
			
			params[name] = value;
		}
		
		this.qs = params;
		return params;
	},
	
	getResponse : function(r)
	{
		return $chk(r) ? Json.evaluate(r) : { success:0, message: this.REQUEST_FAILURE } ;
	},
	
	handleResponse : function(r)
	{
		var response;

		if (r !== null && 'object' == typeof(r))
		{
			response = r;
		}
		else
		{
			response = $chk(r) ? Json.evaluate(r) : { success:0, message: this.REQUEST_FAILURE } ;
		}
		
		// show status message
		if (response.message) this.setStatus(response.message,response.success);
		
		return response;
	},
	
	/* 
	getTimezoneOffset : function() 
	{
		// reference: http://www.csgnetwork.com/timezoneproginfo.html
		
		var rightNow = new Date();
		
		var date1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
		var date2 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0);
		
		var temp = date1.toGMTString();
		var date3 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
		
		var temp = date2.toGMTString();
		var date4 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
		
		var hoursDiffStdTime = (date1 - date3) / (1000 * 60 * 60);
		var hoursDiffDaylightTime = (date2 - date4) / (1000 * 60 * 60);
		
		if (hoursDiffDaylightTime == hoursDiffStdTime) return hoursDiffStdTime;
		else return hoursDiffStdTime;
	},
	*/
	
	isToday : function(ts)
	{
		if (ts)
		{
			var t = new Date(); // today
			
			var d = new Date();
			d.setTime(ts);
			
			if 
			(
				d.getDate() == t.getDate() &&
				d.getMonth() == t.getMonth() && 
				d.getFullYear() == t.getFullYear()
			) 
			{
				return true;
			}
		}
		
		return false;
	},
	
	// ts = a javascript timestamp (unix_timestamp * 1000)
	// javascript will do its own timezone conversion
	getDateString : function(ts)
	{
		if (ts)
		{
			var t = new Date(); // today
			
			var d = new Date();
			d.setTime(ts);
			
			var month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
			
			var h = d.getHours();
			var ampm = (h>11) ? 'PM' : 'AM' ;
			h = (h>12) ? h-12 : (!h?12:h) ;
			
			var m = d.getMinutes();
			m = (m>9) ? m : ('0'+m) ;
			
			var today = (d.getDate() == t.getDate() && d.getMonth() == t.getMonth() && d.getFullYear() == t.getFullYear()) ? 1 : 0 ;
			var full_date = (d.getMonth()+1) + '/' + d.getDate() + '/' + d.getYear().toString().substr(-2);
			
			return today ? (h + ':' + m + ' ' + ampm) : full_date ;
		}
		
		return '';
	},
	
	track : function(uri)
	{
		if (Yomo.TRACKER)
		{
			// console.log(uri?uri:location.pathname + ' (current-page)');
			Yomo.TRACKER._trackPageview(uri);
		}
	},
	
	tip : function(obj)
	{
		if (obj.event) new Event(obj.event).stop();
		Lightbox.open(Yomo.TIPS,obj.tip);
	},
	
	debug : function(obj)
	{
		if ($type(obj) == 'string') 
		{
			if ($('debug-pane')) $('debug-pane').innerHTML += obj + '<br/>';
			
			Yomo.log
			({
				label : obj.label
				, time: null
			});
		}
		else
		{
			var end = obj.end ? obj.end : $time();
			var time = $chk(obj.time) ? obj.time : ((end-obj.start)/1000) ;
			var html = '<span'+ (obj.color?' style="color:'+ obj.color +'"':'') +'>' + obj.label + ': </span><span style="color:#666;">' + time + '</span><br/>';
			if ($('debug-pane')) $('debug-pane').setHTML(html + $('debug-pane').innerHTML);
			
			Yomo.log
			({
				label : obj.label
				, time : time
			});
		}
	},
	
	log : function(obj,write)
	{
		if ($chk(obj)) 
		{
			//Yomo.LOG_DATA.push(obj);
		}
	},
	
	writeLog : function()
	{
		if (Yomo.LOG_DATA.length)
		{
			new Ajax('/request/log.php',
			{
				data: "json=" +  Json.toString(Yomo.LOG_DATA)
				, onComplete : function()
				{
					Yomo.LOG_DATA = [];
				}
			}).request();
		}
	}
}

$extend(Yomo,new Events('noinit'));

Yomo.parseQueryString();

//Yomo.writeLog.periodical(10000,Yomo); // 10 sec

Yomo.addEvent('contentChange',function(obj)
{
	// on change reinitialize events for inner elements
	if (obj.target == this.SECONDARY_PANE)
	{
		// remove any existing scroll event/handler
		$(this.SECONDARY_BODY_CONTAINER).removeEvents('scroll');
		
		// add scroll event/handler
		$(this.SECONDARY_BODY_CONTAINER).addEvent('scroll',function(e)
		{
			
			var info = $(Yomo.SECONDARY_BODY_CONTAINER).getSize();
			//console.log(info);
			if ((info.scrollSize.y-(info.size.y+info.scroll.y)) <= (info.size.y/2))
			//if ((info.size.y+info.scroll.y) > (info.scrollSize.y*.20))
			{
				// Yomo.TEMP.scroll_bottom used to fire one event when in the bottom scroll area
				if (!Yomo.TEMP.scroll_bottom)
				{
					//console.log('check-3');
					//console.log(info);
					Yomo.TEMP.scroll_bottom = true;
					Yomo.fireEvent('scrollEnd');
				}
			}
			else
			{
				Yomo.TEMP.scroll_bottom = false;
			}
		});
	}
});

/*

	Change log:
	
	3/13/2008 - DRB
	- added log and writeLog functions
	
	2/14/2008 - DRB
	- check for $chk(Yomo.DATA.bundles) instead of just Yomo.DATA.bundles

*/