/**
 * @copyright ©2011 Spinitron All rights reserved.
 */
'';
/*global $, lteIE6, showinfo */
(function () {
	'use strict';

	var 
		boxwidth				// s, m and l box widths
			= {'s': 245, 'm' : 345}, 
		shadmargin 
			= {'top': 9, 'right': 14, 'bottom': 18, 'left': 14},
		arrow 
			= {top: {'ns': 26, 's': 114, 'n': 153}, 'height': 36, 'center': 48},
		timer = false,			// hover timer, 900ms
		$lastshow = false,		// last show table row mouse entered
		lastshowrect = {},		// rectangle of that row
		$openshow = false,		// row of the open info box, false if none
		openrect = {},			// rectangle of that row
		rztimer = false,
		ncols = 2,

	catclick = function () {
		var cat = $(this).attr('id');
		$('.schedule .schedshow').removeClass('hilite');
		if (cat !== 'xcancelcat')
			$('.schedule .schedshow.' + cat).addClass('hilite');
	},

	infoboxopen = function (x, y, left, html, sizearg) {

		var boxsel = '#InfoBox',				// selector for the outer containing div
			$box = $(boxsel),					// the outer containing div
			boxsize = 'm',						// 's' or 'm' box width. default is 'm'
			boxtop, boxleft, boxheight, midbot,	// $div's rectangle offsets
			arrowclass, arrowtop,				// arrow span's class & top offset wrt $box
			viewtop = $(window).scrollTop(),	// viewport rectangle offsets
			viewbot = viewtop + $(window).height(),
			viewleft = $(window).scrollLeft(),
			viewright = viewleft + $(window).width();

		// boxsel must contain a block with class="content". put html in that
		$(boxsel+' .content').empty().html(html);
		// set display:block so it and its descendents are layed out with dimensions
		$box.css({display: 'block', visibility: 'hidden'}).removeClass().addClass(boxsize);
		
		if ((sizearg && sizearg === 's')
			|| ((!sizearg || sizearg === 'auto') && $box.width()/$box.height() > 1.6)
		) {
			boxsize = 's';
			$box.removeClass().addClass(boxsize);
			$('.transp').trigger('onpropertychange');
		} else {
			boxsize = 'm';
		}

		boxheight = $box.height(); // of the outer container
		// 1st try: center box vertically on y 
		boxtop = y - Math.round(boxheight/2); 
		arrowclass = 'ns'; // ◀ or ▶ arrow. sprite class sets clip and horizontal offset
		arrowtop = y - boxtop - arrow.top[arrowclass]; // arrow sprite vertical offset 
		if ( boxtop + shadmargin.top < viewtop )
		// on 1st try, top of roundrect was above viewport top
		{
			// reposition box so roundrect top is at viewport top
			boxtop = viewtop - shadmargin.top; 
			// assume corner radius == shadmargin.top
			if ( y - Math.round(arrow.height/2) < boxtop + 2*shadmargin.top )
				// can't slide ◀ ▶ arrow high enough on side of roundrect. use ◥ or ◤ instead
				arrowclass = 'n'; // sprite class. sets clip and horizontal offset
			arrowtop = Math.max(y - boxtop - arrow.top[arrowclass], // sprite vertical offset
				2*shadmargin.top - arrow.top[arrowclass]); // but not too high
		}
		else
		{
			// midbot is bottom of boxsel+'-mid' relative to outer box
			midbot = $(boxsel+'-top').height() + $(boxsel+'-mid').height();
			// assume corner radius == shadmargin.top and assume boxsel+'-bot' has 
			// no vertical straights, only corner rounds
			if ( boxtop + midbot + shadmargin.top > viewbot )
			// on 1st try, bottom of roundrect was below viewport bottom 
			{
				// reposition box so roundrect bottom is at viewport bottom
				boxtop = viewbot - midbot - shadmargin.top;
				// assume boxsel+'-bot' has no vertical straights, only corner rounds
				if ( y + Math.round(arrow.height/2) > boxtop + midbot ) 
					// can't slide ◀ ▶ arrow low enough on side of roundrect. use ◢ or ◣ instead
					arrowclass = 's'; // sprite class. sets clip and horizontal offset
				arrowtop = Math.min(y - boxtop - arrow.top[arrowclass],  // sprite vertical offset
					midbot - arrow.top[arrowclass]); // but not too low
			}
		}
		boxleft = left // container box horizontal offset
			? x + ( arrow.center - Math.round(1.5*shadmargin.left) )
			: x - ( boxwidth[boxsize] + arrow.center - Math.round(1.5*shadmargin.left) );
		arrowclass += left ? 'w' : 'e'; // complete sprite class string, east/west
		$(boxsel+'-arrow').removeClass().addClass(arrowclass).css('top', arrowtop); //
		$(boxsel).css({top: boxtop, left: boxleft, visibility: 'visible'}).show();
	},

	infoboxhide = function () {
		$('#InfoBox').hide();
		$openshow = false;
		openrect = {};
	},

	showclick = function () {
		var $showobj = $(this),
			viewtop = $(window).scrollTop(),
			viewleft = $(window).scrollLeft(),
			sinfo, days, djnames = [], lastdj, imagestring = '',
			$elem, offset, left, x, y, html, i, n;
		if ($showobj.length
			&& !(sinfo = $showobj.attr('id')) 
			|| !(sinfo = (sinfo.match(/^showid(\d+)$/) || [0,false])[1]) 
			|| !(sinfo = showinfo[sinfo])
		) {
			return true;
		}
		if ( $showobj.is('tbody.day tr') ) {
			if ( $showobj.closest('td.scheduleColumn').is('.left') ) {
				left = true;
				$elem = $showobj.children('td.schedshow').last();
				offset = $elem.offset();
				x = offset.left + $elem.width();
			} else {
				left = false;
				$elem = $showobj.children('td.schedshow').first();
				offset = $elem.offset();
				x = offset.left;
			}
		} else if ( $showobj.is('div.schedshow') ) {
			$elem = $showobj;
			offset = $elem.offset();
			if ( offset.left < viewleft + 0.45*$(window).width() ) {
				left = true;
				x = offset.left + $elem.width() - 8;
			} else {
				left = false;
				x = offset.left + 8;
			}
		}
		y = offset.top + Math.round($elem.height() / 2);
		if ( y - viewtop < 5 
			 || viewtop + $(window).height() - y < 8 ) {
			infoboxhide();
			return true;
		}
		if ( !sinfo.weekdays.match(/,/) ) {
			days = {'Sun':'Sunday', 
				'Mon':'Monday', 
				'Tue':'Tuesday', 
				'Wed':'Wednesday', 
				'Thu':'Thursday', 
				'Fri':'Friday', 
				'Sat':'Saturday'}[sinfo.weekdays] + 's';
		} else {
			days = sinfo.weekdays.replace(/,/g, ', ');
		}
		if ( sinfo.simg )
			imagestring = sinfo.simg;
		if ( sinfo.djnames && sinfo.djnames.length ) {
			for ( i in sinfo.djnames )
				djnames.push('<b>' + sinfo.djnames[i] + '</b>');
			lastdj = djnames.pop();
			djnames = djnames.length
				? djnames.join(', ') + ' and ' + lastdj
				: lastdj;
			n = 0;
			if ( !imagestring.length && sinfo.djimgs )
				for ( i in sinfo.djimgs ) {
					imagestring += sinfo.djimgs[i];
					if ( ++n >= 2 ) break;
				}
		}
		if ( imagestring )
			imagestring = '<p class="imgs">' + imagestring + '</p>';
		html = 
			'<h1>' + sinfo.showname + '</h1>'
			+ imagestring
			+ (djnames.length ? '<p class="first">With ' + djnames + '</p>' : '')
			+ '<p>' + sinfo.ptime + ' ' + days + '</p>'
			+ (sinfo.stext ? '<p>' + sinfo.stext + '</p>' : '')
			+ (imagestring ? '<p class="clear"></p>' : '');
		infoboxopen(x, y, left, html, lteIE6 ? 'm' : 'auto');
		$openshow = $showobj;
		openrect = $lastshow.offset();
		openrect.width = $lastshow.width();
		openrect.height = $lastshow.height();
	},

	entershow = function () {
		// if mouse enters a show row, remember it and its rect
		if ($lastshow !== $(this)) {
			$lastshow = $(this);
			lastshowrect = $lastshow.offset();
			lastshowrect.width = $lastshow.width();
			lastshowrect.height = $lastshow.height();
		}
	},

	mouseinrect = function (e, rect) {
		// is the mouse position in event e inside rect?  
		var x = e.pageX, y = e.pageY;	
		return rect.left <= x && x <= rect.left + rect.width
			&& rect.top  <= y && y <= rect.top  + rect.height;
	},

	hover = function (e) {
		// mouse stopped moving somewhere
		if ($lastshow // we know which row rect was last entered
			&& mouseinrect(e, lastshowrect) // is mouse still there?
			// and either there's no info box open or the wrong one is open 
			&& (!$openshow || $openshow.attr('id') !== $lastshow.attr('id'))
		) {
			$lastshow.click();
		}
	},

	move = function (e) {
		// (re)set the hover timer
		if ( timer )
			window.clearTimeout(timer);
		timer = window.setTimeout(
			function () { 
				hover(e); 
			}, 
			900
		);
		// if mouse exits the open infobox's rect, close the box
		if ( !mouseinrect(e, openrect) )
			infoboxhide();
	},

	schedcols = function () {
		var avail = $('#right').width();
		if (ncols === 2 && avail/3 > 340) {
			ncols = 3;
			$('<td id="ScheduleCol3" class="scheduleColumn right"><table cellspacing="0" class="schedule list"></table></td>')
				.appendTo('#ScheduleRow');
			$('#ScheduleCol2 tbody.dnum5').detach().appendTo('#ScheduleCol3 table.schedule.list');
			$('#ScheduleCol2 tbody.dnum6').detach().appendTo('#ScheduleCol3 table.schedule.list');
			$('#ScheduleCol1 tbody.dnum3').detach().prependTo('#ScheduleCol2 table.schedule.list');
		} else if (ncols === 3 && avail/3 < 320) {
			ncols = 2;
			$('#ScheduleCol2 tbody.dnum3').detach().appendTo('#ScheduleCol1 table.schedule.list');
			$('#ScheduleCol3 tbody.dnum5').detach().appendTo('#ScheduleCol2 table.schedule.list');
			$('#ScheduleCol3 tbody.dnum6').detach().appendTo('#ScheduleCol2 table.schedule.list');
			$('#ScheduleCol3').remove();
		}
	},

	resize = function () {
		// (re)set the resize timer
		if (rztimer) {
			window.clearTimeout(rztimer);
		}
		rztimer = window.setTimeout(
			function () {
				schedcols();
			},
			500
		);
	};

	$(document).ready(function(){
		infoboxhide();
		schedcols();
		$('#catselector a').click(catclick);
		$('table.schedule tr, div.schedshow')
			.click(showclick).mouseenter(entershow).attr('title', '');
		$(document).bind('mousemove mouseleave', move);
		$(window).resize(resize);
	});

}());
