/*
 * Copyright 2000-2008 namics ag. All rights reserved.
 */

/**
 * TV.Program class.
 * 
 * @author Remo Brunschwiler, namics ag
 */

TV.Program = function() {
	this.channelWidth =178;
	this.chooserChannelHeight = 22;
	this.magnifierFactor = this.channelWidth / this.chooserChannelHeight;
	
	this.bindProgramEvents();
	
	this.atChangingChannels = false;
	this.atChangingFavorites = false;
};

/* ==========================================================
 * Binds the click event to add broadcasts from favorites.
 * ==========================================================
 */
TV.Program.prototype.addToFavorites = function () {	
	var that = this;
	
	// use event bubbling to catch the events (otherwise there are too many events)
	TV.$('#programwrapper, #overlay a.add_to_fav').livequery('click', function (e) {
		// check if the event has been sent from the correct target (is this event for me?)
		var $this = TV.$(e.target);
			
		// only cancel propagation (return false) it the event is an addToFavorite request
		if ($this.hasClass('add_to_fav')) {
			if (!that.atChangingFavorites) {
				that.atChangingFavorites = true;
				
				var broadcastId = $this.attr('id').substr(1);
				
				// ajax call to add slotId to the favoritebroadcasts cookie
				TV.$.getJSON(TV.CONSTANTS.SCRIPTS.ADD_BROADCAST + broadcastId + '?format=json', function(data){
					if (data.success == true) {
						// everything is ok
						
						if ($this.hasClass('overlay')) {
							// if it is in the overlay -> special treatment
							$this.removeClass('add_to_fav').addClass('remove_from_fav').html('Entfernen aus "Mein TV Programm"');
							
							TV.$('#gotodetail').show();
							
							var bId = ($this.attr('id')).substr(1);
							$this = TV.$('#b' + bId);
						}
						
						// add the selected class to the appropriate broadcast in the overview
						TV.$($this.parents('tr')[0]).addClass('programmselected');
						$this.removeClass('add_to_fav').addClass('remove_from_fav');
						
						// add one to the mytvprogram counter
						var $countMyTv = TV.$('#count_mytv');
						
						$countMyTv.text(parseInt($countMyTv.text()) + 1);
					}
					
					that.atChangingFavorites = false;
				});
			}
			
			return false;
		}
	});
};

/* ==========================================================
 * Binds the click event to remove broadcasts from favorites.
 * ==========================================================
 */
TV.Program.prototype.removeFromFavorites = function () {
	var that = this;
	
	// use event bubbling to catch the events (otherwise there are too many events)
	TV.$('#programwrapper, #overlay a.remove_from_fav').livequery('click', function (e) {	
		// check if the event has been sent from the correct target (is this event for me?)
		var $this = TV.$(e.target);
		
		// only cancel propagation (return false) it the event is a removeFromFavorite request
		if ($this.hasClass('remove_from_fav')) {
			if (!that.atChangingFavorites) {
				that.atChangingFavorites = true;
				
				var broadcastId = $this.attr('id');
				
				// ajax call to add slotId to the favoritebroadcasts cookie
				TV.$.getJSON(TV.CONSTANTS.SCRIPTS.REMOVE_BROADCAST + broadcastId + '?format=json', function(data){
					if (data.success == true) {
						// everything is ok
						if ($this.hasClass('overlay')) {
							// if it is in the overlay -> special treatment
							$this.removeClass('remove_from_fav').addClass('add_to_fav').html('Hinzufügen zu "Mein TV Programm"');
							
							TV.$('#gotodetail').hide();
							
							var bId = ($this.attr('id')).substr(1);
							$this = TV.$('#b' + bId);
						}
						
						// remove the selected class
						TV.$($this.parents('tr')[0]).removeClass('programmselected');
						$this.removeClass('remove_from_fav').addClass('add_to_fav');
						
						// add one to the mytvprogram counter
						var $countMyTv = TV.$('#count_mytv');
						
						$countMyTv.text(parseInt($countMyTv.text()) - 1);
					}
					
					that.atChangingFavorites = false;
				});
			}
			
			return false;
		}
	});
};

/* =========================================================
 * Displays previous or next broadcast in overlay
 * =========================================================
 */
TV.Program.prototype.navigateBroadcastsInOverlay = function() {
	TV.$('.overlay_browse').livequery('click', function() {
		var $this = TV.$(this);
		
		var bId = ($this.attr('href').split('#'))[1];
		
		if (bId != '') {
			// trigger the displayOverlay from the appropriate broadcast
			var $broadcast = TV.$(TV.$('#b' + bId).parent().parent());
			
			if ($broadcast.hasClass('broadcast')) {
				TV.$('#programchannels').triggerHandler('click', {
					'broadcastId': bId
				});
			}
			else {
				// sometimes the xml is not completely correct... so show the error message
				$error = TV.$('#overlayErrorMessage').clone();
				TV.$('#overlayBox').empty().append($error.children()).show();
			}
		}
		return false;
	});
};

/* =========================================================
 * Displays the overlay of a broadcast
 * =========================================================
 */
TV.Program.prototype.displayOverlay = function () {
	// use event bubbling to catch the events (otherwise there are too many events)
	// display the overlay
	TV.$('#programchannels').livequery('click', function (e, data) {
		// check if the event has been sent from the correct target (is this event for me?)
		var data = data || {};
		if (data.broadcastId) {
			var $target = TV.$('#b' + data.broadcastId).parent();
		}
		else {
			var $target = TV.$(e.target);
		}
		
		if(!$target.hasClass('add_to_fav') && !$target.hasClass('remove_from_fav') && !$target.hasClass('livestream') && $target.get(0).tagName.toLowerCase() != 'div') {
			// the event is a displayOverlay request
			var $broadcast;
			
			if ($target.hasClass('broadcast')) {
				$broadcast = $target;
			}
			else {
				$broadcast = TV.$($target.parents('tr').get(0));
			}
			
			if ($broadcast.hasClass('broadcast')) {
				// show transparent layer
				var $programwrapper = TV.$('#programwrapper');
				TV.$('#overlayWrapper').css({
					'width': $programwrapper.width(),
					'height': $programwrapper.height()
				}).show();
				
				// show loader
				var $loader = TV.$('#overlayLoadingMessage');
				TV.$('#overlayBox').empty().html($loader.html()).show()
				
				// get the broadcast id
				var broadcastId = TV.$('td.left a', $broadcast).attr('id').substr(1);
				
				TV.$.get(TV.CONSTANTS.SCRIPTS.GET_OVERLAY + broadcastId + '?format=html', null, function(data, textStatus){
					if (textStatus == 'success') {
						TV.$('#overlayBox').empty().append(data).show();
					}
					else {
						$error = TV.$('#overlayErrorMessage').clone();
						TV.$('#overlayBox').empty().append($error.children()).show();
					}
				}, 'html');
			}
			
			return false;
		}
	});
	
	// prevent that any clicks on the overlay hides the overlay
	
	TV.$('#overlayBox').livequery('click', function (e) {
		e.stopPropagation();
	});
};

/* =========================================================
 * Hides the overlay
 * =========================================================
 */
TV.Program.prototype.hideOverlay = function(){
	// hide the overlay
	TV.$('.overlay_close').livequery('click', function(){
		TV.$('#overlayBox').hide();
		TV.$('#overlayWrapper').hide();
		
		return false;
	});
};

/* ==========================================================
 * Binds the click event to remove a channel.
 * ==========================================================
 */
TV.Program.prototype.removeChannel = function () {
	var that = this;
	
	TV.$('.channel_close').livequery('click', function () {
		
		if (!that.atChangingChannels) {
			that.atChangingChannels = true;
			
			var channelId = TV.$(this).attr('id').substr(6);
			
			// ajax call to remove channelid from cookie
			TV.$.getJSON(TV.CONSTANTS.SCRIPTS.REMOVE_CHANNEL + channelId + '?format=json', function(data){
				if (data.success == true) {
					
					// remove blocks
					for (i = 4; i < 30; i += 2) {
						var blockId = 'block' + i + '-' + (i + 2) + '_';
						
						TV.$('#' + blockId + channelId).remove();
					}
					
					// remove header and show add icon
					TV.$('#b25_' + channelId).remove();
					TV.$('#logo_' + channelId).remove();
					TV.$('#empty_' + channelId).parent().show();
					
					// makes the scrollers smaller
					that.resizeScrollers('downsize');
					
					// rebind slider 
					that.slideToChannel();
					
					// scroll to adding list
					TV.$('#empty_channel_add').trigger('click');
				}
				
				that.atChangingChannels = false;
			});
		}
		
		return false;
	});
};

/* ==========================================================
 * If a channel is added or removed, the size of the scrollers
 * must be resized. This function does these. 
 * @param	{ string }	'enlarge' for increase size for a channel
 *						'downsize' for making smaller 
 * ==========================================================
 */
TV.Program.prototype.resizeScrollers = function(operation) {
	/* program scroller (width) & channel scroller (height) */
	var iWidth 	= TV.$('#programscroller').width();
	// var numLogos = TV.$('.logo', '#selectchannelsscroller').length + 1;
	var iHeight = TV.$('#selectchannelsscroller').height();
	var tableWidth = TV.$('#programchannels').width();
	
	if (operation == 'enlarge') {
		iWidth += this.channelWidth;
		tableWidth += this.channelWidth;
		iHeight += this.chooserChannelHeight;
		
	}
	else {
		iWidth -= this.channelWidth;
		tableWidth -= this.channelWidth;
		iHeight -= this.chooserChannelHeight;
	}

	iWidth = iWidth + 'px';
	tableWidth = tableWidth + 'px';
	iHeight = iHeight + 'px';
	
	
	TV.$('#selectchannelsscroller').css('height', iHeight);
	TV.$('#programscroller').css('width', iWidth);
	TV.$('#programchannels').css('width', tableWidth);
};

/* ==========================================================
 * Binds the click event to add a channel.
 * ==========================================================
 */
TV.Program.prototype.addChannel = function () {
	var that = this;
	
	TV.$('.channel_add').livequery('click', function () {
		if (!that.atChangingChannels) {
			that.atChangingChannels = true;
			
			// show loading message
			TV.$('#loading').show();
			
			var channelId = TV.$(this).attr('id').substr(6);
			var date =  TV.$(this).attr('date');
			
			// ajax call to add channelid tocookie and add the channel to the overview
			TV.$.ajax({
				timeout: 10000,
				url: TV.CONSTANTS.SCRIPTS.ADD_CHANNEL + channelId + '?date=' + date + '&format=html',
				dataType: 'html',
				error: function(){
					TV.$('#loading').hide();
					that.atChangingChannels = false;
				},
				success: function(data){
					// add logo to the magnifier						
					$data = TV.$(data);
					
					// makes the scrollers bigger
					that.resizeScrollers('enlarge');
					
					TV.$('#logos').append(TV.$('#logo_' + channelId, $data));
					
					// add blocks
					for(var j = 28; j > 2; j -= 2) {
						var blockId = 'block' + j + '-' + (j + 2) + '_';
						var blockToId = blockId + 'layout';
						
						TV.$('#' + blockToId).before(TV.$('#' + blockId + channelId, $data));
					}
					
					// hide channel from the adding list
					TV.$('#empty_' + channelId).parent().hide();
					
					// paste header
					TV.$('#b25_layout').before(TV.$('#b25_' + channelId, $data));
					
					// rebind draggable events
					that.sortChannels();
					
					// rebind slider 
					that.slideToChannel();
					
					// scroll to adding list
					TV.$('#empty_channel_add').trigger('click');
					
					// hide loading message
					TV.$('#loading').hide();
					
					that.atChangingChannels = false;
				}
			});
		}
		
		return false;
	});
};

/* ==========================================================
 * Scroll to the channel adding list
 * ==========================================================
 */
TV.Program.prototype.scrollToChannelList = function() {
	TV.$('#empty_channel_add').unbind('click').click(function () {
		var $wrapper = TV.$('#programwrapper');
		var $scroller = TV.$('#programscroller');
		var width = $scroller.width();
	
		/* scroll to the channellist */
		$wrapper.scrollLeft(width);
	
		return false;
	});
};
	
TV.Program.prototype.fixTableHead = function () {
	var $channelHead = TV.$('#channelhead');
	var $emptyChannel = TV.$('#empty_channel');
	var $programWrapper = TV.$('#programwrapper');
	var $magnifier = TV.$('#magnifier');
	var timeout = null;
	var that = this;
	
	$programWrapper.unbind('scroll').bind('scroll', function (e) {
		e.stopPropagation();
		if (!TV.Program.atSliding) {
			if (timeout != null) {
				clearTimeout(timeout);
			}
			
			timeout = setTimeout(function(){
				if (!TV.Program.atSliding) {
					var scrollTop = $programWrapper.scrollTop();
					$channelHead.css('top', scrollTop);
					$emptyChannel.css('top', scrollTop);
					$magnifier.animate({
						'top': $programWrapper.scrollLeft() * (1 / that.magnifierFactor)
					}, 10);
				}
			}, 400);
		}
	});
};

/* ==========================================================
 * Make magnifier logos sortable
 * ==========================================================
 */
TV.Program.prototype.sortChannels = function () {
	TV.$('#logos').sortable('destroy').sortable({
		items: '.logo',
		opacity: 0.8,
		delay: '0',
		axis: 'y',
		revert: false,
		containment: 'parent',
		update: function(e, ui){
			// serialize the reordered list in the format "channelids[]=<channelnumber>&channelids[]=<channelnumber>"
			var channelIds = TV.$(this).sortable('serialize', { key : 'channelids', expression : '.+[_](.+)'});
			
			// ajax call to reorder channelids in cookie
			TV.$.getJSON(TV.CONSTANTS.SCRIPTS.REORDER_CHANNELS + '?format=json&' + channelIds, 
				function (data) {
					if (data.success == true) {
						// everything ok
						var prev = false;
						// reorder the columns
						// the draggable object 
						// -> because the ui.helper is a clone of the logo-object, we must select the correct one from the DOM
						var tmpId = ui.helper.attr('id');
						var $draggable = TV.$('#' + tmpId);
						
						// the droppable object
						var $droppable = $draggable.next('.logo');
						
						// if the droppable was the last entry in the list -> get the previous node
						if (typeof $droppable.get(0) == 'undefined') {
							$droppable = $draggable.prev('.logo');
							prev = true;
						}
						
						// move the content of the draggable to the correct position
						var dropId	= $droppable.attr('id').split('_')[1];
						var dragId	= $draggable.attr('id').split('_')[1];
				
						// if the order has changed -> change blocks and headers (logos)
						if (dropId != dragId) {
							// change headers (logo)
							var $draggableHeader = TV.$('#b25_'+dragId);
							var $droppableHeader = TV.$('#b25_'+dropId);
							
							if (prev) {
								TV.$('#b25_layout').before($draggableHeader);
							}
							else {
								$droppableHeader.before($draggableHeader);
							}
							
							// change blocks (content)
							var j = 30;
							do {
								var i = j - 2;
								
								var blockStartId = i;
								var blockEndId = i + 2;
								
								var blockId = 'block' + blockStartId + '-' + blockEndId + '_';
								
								var blockFromId = blockId + dragId;
								var blockToId = blockId + dropId;
								
								if (prev) {
									TV.$('#' + blockId + 'layout').before(TV.$('#' + blockFromId));
								}
								else {
									TV.$('#' + blockToId).before(TV.$('#' + blockFromId));
								}
								j -= 2;
							}
							while (j > 4); 
						}
					}
				}
			);
		}
	});	
};

/* ==========================================================
 * Make the logos clickable
 * ==========================================================
 */
TV.Program.prototype.jumpToChannel = function () {
	var that = this;
	var $magnifier = TV.$('#magnifier');
	
	TV.$('#logos .logo').each(function () {
		TV.$(this).bind('click', function () {
				that.dragMagnifier((TV.$(this).offset()['top'] - TV.$('#selectchannelsscroller').offset()['top'] - 3) * that.magnifierFactor);
				return false;
		});
	});
};


/* =========================================================
 * Makes the fullscreen mode opens in a new window
 * =========================================================
 */
TV.Program.prototype.openFullscreenMode = function () {
	TV.$('#fullscreen').unbind('click').click(function () {
		var link = TV.$(this).attr('href');
		window.open(link, "Vollbildansicht", "menubar=no, location=no, status=no, toolbar=no, scrollbars=1, resizable=yes");
		return false;
	});
};


/* =========================================================
 * Make the clicks on the time scrolls to the appropriate block
 * =========================================================
 */
TV.Program.prototype.scrollToTime = function () {
	TV.$('.totime').unbind('click').click(function () { 
		var $time = TV.$(this);
		var $scrollTarget = TV.$($time.attr('href'));
		
		var $wrapper = TV.$('#programwrapper');
		var posY = ($scrollTarget.offset()['top'] - TV.$('#programscroller').offset()['top']) - 27;
		$wrapper.scrollTop(posY);
		
		return false;
	});
	
	// jump to the actual time
	TV.$('#actualTime').trigger('click');
};

/* ==========================================================
 * Makes the magnifier slideable and being controlled from 
 * the scrollbar.
 * ==========================================================
 */
TV.Program.prototype.slideToChannel = function(){
	var that = this;
	
	// solves conflict between slider and scrollbar (only one can be processed)
	TV.Program.atSliding = false;
		
	TV.$("#magnifier").draggable('destroy').draggable({
		containment: "parent",
		opacity: 0.5,
		axis: "vertically",
		start: function() {
			TV.Program.atSliding = true;
		},
		stop: function() {
			TV.Program.atSliding = false;
		},
		drag: function(e, ui) { 
			var y = ui.position.top * that.magnifierFactor;
			that.dragMagnifier(y);
		}
	});
};

TV.Program.prototype.dragMagnifier = function(y) {
	var $programWrapper = TV.$('#programwrapper');
	if (y > 0) {
		$programWrapper.scrollLeft(y);
	} else {
		$programWrapper.scrollLeft(0);
	}
	
};

TV.Program.prototype.scrollChannelSelector = function () { 
	var $channelScroller = TV.$("#selectchannelsscroller");
	var $channelSelector = TV.$("#selectchannels");
	var $arrowUp = TV.$("#scrollerarrowup");
	var $arrowDown = TV.$("#scrollerarrowdown");
	
	// init
	var channelScrollerHeight	= $channelScroller.height();
	var channelSelectorHeight	= $channelSelector.height();	
	var channelScrollerTop = parseInt($channelScroller.css("top"));
		
	if (channelSelectorHeight - channelScrollerTop < channelScrollerHeight) {
		$arrowDown.css("background-position", "0 0");
	}
	
	// scroll down
	$arrowDown.unbind('click').click(function() {
		var channelScrollerHeight	= $channelScroller.height();
		var channelSelectorHeight	= $channelSelector.height();
		
		var channelScrollerTop = parseInt($channelScroller.css("top"));
		
		if (channelSelectorHeight - channelScrollerTop < channelScrollerHeight) {
			var scrollTop = channelScrollerTop - 88; //sprunghöhe: 4 logos
			$channelScroller.css('top', scrollTop +'px');
			$arrowDown.css("background-position","0 0");
			$arrowUp.css("background-position","0 0");
		} 
		else 
		{
			$arrowDown.css("background-position","0 -50px");
		}
		
		return false;
	});
	
	// scroll up
	$arrowUp.unbind('click').click(function() {
		var channelScrollerTop = parseInt($channelScroller.css("top"));
		
		if (channelScrollerTop < 25) {
			var scrollTop = channelScrollerTop + 88; 
			$channelScroller.css('top', scrollTop +'px');
			$arrowUp.css("background-position","0 0")
			$arrowDown.css("background-position","0 0");
		} 
		else 
		{
			$arrowUp.css("background-position","0 -50px");
		}
		
		return false;
	});
};

/* ==========================================================
 * Displays the cookie message if needed
 * ==========================================================
 */
TV.Program.prototype.checkCookieStatus = function(){
	if(!document.cookie) {
		TV.$('#cookiestatus').css('display', 'block');
	}	
};


// static variable used from several methods
TV.Program.atSliding = false;

/* ==========================================================
 * Binds the events
 * ==========================================================
 */
TV.Program.prototype.bindProgramEvents = function () {
	var that = this;
	TV.$(document).ready(function () {
		that.checkCookieStatus();
		that.displayOverlay();
		that.navigateBroadcastsInOverlay();
		that.hideOverlay();
		that.addToFavorites();
		that.removeFromFavorites();
		that.addChannel();
		that.removeChannel();
		that.fixTableHead();
		that.jumpToChannel();
		that.sortChannels();
		that.scrollToChannelList();
		that.openFullscreenMode();
		that.scrollToTime();
		that.slideToChannel();
		that.scrollChannelSelector();
	});
};
