/*
	base.js
	Primary javascript for IM-like sites.
*/

$(function() {
	// Select/toggle main menu items.
	// PONDER: can be removed?
	$("#mainmenu > li").click(function(ev) 
	{
		var me= $(this), sel= $('#mainmenu > li.active');
		sel.removeClass('active');
		
		// NOTE: can't compare jquery object directly, but you can compare 
		// the DOM objects they're attached to.
		if(me[0] != sel[0])
			me.addClass('active');
	});
	
	initPopupMenus();
	initBanner();
	initGalleries();
	initVideos();
	initGoogleMaps();

	//# TODO: Goto and play video on anchor.
	if(document.location.hash)
	{
		//# if vbox-id:
			//# goto anchor and play
		document.location.hash= document.location.hash;
		
		//# if gallery-anchor:
			//# goto gallery viewport and select gallery item.
	}
});


//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------

/* =UTILITY
---------------------------------------------------------------------------- */

// NOTE: the way console.log works is apparently very browser specific. 
// Firefox: console.log.apply(this, args), but only if Firebug's open.
// IE: console.log is object, not function, so apply doesn't work.
// Safari: ???
// Opera: ???
// Because of the various potential problems, wrapping it in an exception block.
function log(format, args)
{
	try
	{
		console.log.apply(this, arguments);
	}
	catch(err) {}
}

// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery
String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
    if (m == "{{") { return "{"; }
    if (m == "}}") { return "}"; }
    return args[n];
  });
};

//! Check for flash availability.
/*!
	@return	true if flash is available, otherwise false.
	@note	Requires swfobject.
*/
function hasFlash()
{
	var flash= swfobject.getFlashPlayerVersion();
	return (flash && flash.major);
}

//! Joins an object's key-value pairs together based on an sprintf-like formatstring.
/*!
	@param format	Format string. Use "%k" for keys and "%v" for values.
	@param obj		Object whose members to join.
	@param glue		Separator between items.
*/
function kvjoin2(format, obj, glue)
{
	var a= [];
	for(i in obj)
		a.push(format.replace("%k", i).replace("%v", obj[i]));
		
	return a.join(glue);
	
}

/* =DRIVERS
---------------------------------------------------------------------------- */

//! Add popupmenus' handlers for touchscreen versions.
function initPopupMenus()
{
	if($('.menu-popup').length == 0)
		return;
		
	// Enable popup / disable old popups.
	$('.menu-popup .parent').bind("touchstart", function(e) {
		$(this).siblings('.hovered').find('.sub').css('display', 'none');
		$(this).siblings('.hovered').removeClass('hovered');
		
		$(this).addClass('hovered');
		$(this).children('.sub').css('display', 'block');
		e.stopPropagation();
	});
	
	// Global disabler of sub-menus
	$(document).bind("touchstart", function(e) {
		$('.hovered').children('.sub').css('display', 'none');
		$('.hovered').removeClass('hovered');
	});
}

//! Prepare the banner for animations.
function initBanner()
{
	var banner= { 
		$this: $('#banner'), 
		$list: null, 
		$bar: $('#banner-bar'),
		$pager: null,
		active: ($.cookie ? $.cookie('banner') != 0 : 1)
	};

	banner.$list= $('.img-cycle', banner.$this);
	if(banner.$list.length == 0)
		return;

	var opts= {
		fx:'fade',
		timeout:4000, 
		speed:1000,
		pause:1
	};
	var json= $('._opts', banner.$this).text();
	$.extend(opts, $.parseJSON(json));

	$('._opts', banner.$this).remove();
	
	// --- Construct actual banner ---
	banner.$list.wrap('<div id="banner-main">');
	var $nav= $('#banner-nav', banner.$this);

	if(opts.pager)
	{
		$nav.append('<div id="pager-holder"><div id="pager-nav"></div></div>');
		opts.pager= '#pager-nav';
		opts.pauseOnPagerHover= 1;
	}
	if(opts.nav)
	{
		$nav.prepend('<div id="cycle-left" class="cycle-nav"> <a>L</a></div>');
		$nav.append('<div id="cycle-right" class="cycle-nav"> <a>R</a></div>');
		$('#banner-main').addClass('nav');
		opts.next= '#cycle-right';
		opts.prev= '#cycle-left';
	}
	
	// --- Actual init ---
	banner.$list.cycle(opts);
	if(!banner.active)
	{
		banner.$this.hide();
		banner.$bar.addClass('up');
		banner.$list.cycle('pause');
	}

	// --- Handlers ---
	banner.$bar.click(function() {
		var $me= $(this);
		banner.active ^= 1;
		if($.cookie)
			$.cookie('banner', banner.active, {expires: 365});
		banner.active ? $me.removeClass('up') : $me.addClass('up');

		banner.$this.slideToggle("slow", function() {
			banner.$list.cycle(banner.active ? 'resume' : 'pause');
		});
	});
}

function initGoogleMaps()
{
	$('.gmap').each(function(i, el) {
		var obj= $.parseJSON($('._opts', $(el)).text());
		gmapInsert(el, obj); 
	});
}

//! Prepare video buttons and elements.
function initVideos()
{
	$('.vbox').each(function(i, el) {
		var $me= $(el), videoId= 'video-' + i;
		
		$('.preview', $me)
			.wrap('<span id="'+ videoId+ '" />')
			.after('<span class="play-icon" />')
			.parent()
			.wrap('<a />');
			//.wrap('<a href="#' + videoId + '" />');

		$me.click(function(e) {
			$me.unbind('click');
			var opts= $.parseJSON($('._opts', $me).text());
			videoInsert(videoId, opts);
		});
	});
}

//! Prepare gallery of images and videos.
function initGalleries()
{
	//# NOTE: since $thumbs has multiple entries, $ul will too.
	//# OBviously, this is not what was indended, so just using the 
	//# first will have to do for now.
	var $thumbs= $('#gallery').find('.gallery-ithumb, .gallery-vthumb');
	var $ul= $thumbs.closest('ul').eq(0), $main= $ul.parent();
	
	// --- Prep thumbs ---
	var sumWidth= 0;
	if($thumbs.length > 0)
	{
		$thumbs.each(function(i, el) {
			var $me= $(el);
			sumWidth += $me.outerWidth(true);
			$me.click(function() { galSelect($me); });
		});
		galSelect($thumbs.eq(0));
	}
	
	// Special prep for vthumbs.
	$thumbs.filter('.gallery-vthumb').find('a').append('<span class="play-icon"></span>');
	
	$ul.width(sumWidth);
	
	// --- Add nav-elements if container is too small ---
	var docWidth= $ul.width(), viewWidth= $main.width();
	if(viewWidth < docWidth)
	{
		$right= $('<div class="slider-nav-right"> </div>').insertAfter($main);
		$right.click(function() {
			var newX= $ul.position().left - viewWidth;
			if(newX+docWidth < viewWidth)
				newX= viewWidth - docWidth;

			$ul.animate({ 'left':newX }, 'slow');
		});
		
		$left= $('<div class="slider-nav-left"> </div>').insertAfter($main);
		$left.click(function() {
			var newX= $ul.position().left + viewWidth;
			if(newX > 0)
				newX= 0;
			$ul.animate({ 'left':newX }, 'slow');
		});
	}
	else		// --- Or center it ---
		$ul.css('left', (viewWidth-docWidth)/2);
}

// ----------------------------------------------------------------------------

//! Select an image or video item in a gallery
function galSelect($sel)
{
	var opts= $.parseJSON($('._opts', $sel).text());
	var $gallery= $sel.closest('.gallery');
	
	// Switch active item and show it.
	$gallery.find('.active').removeClass('active');
	$sel.find('a').addClass('active');
	var thumbClass= $sel.attr('class');
	if(thumbClass == 'gallery-vthumb')
	{
		$gallery.find('.view').html('<object id="vplayer"> </object>');
		videoInsert('vplayer', opts);
	}
	else
		
		$gallery.find('.view').html(
			'<img src="' + opts.src + '" alt="">'
		);
		/*# This centers, but now the image inside won't always fit :(
		$gallery.find('.view').html(
			'<table class="tcenter tmiddle"><tr><td>' + 
			'<img src="' + opts.src + '" alt="">' + 
			'</td></tr></table>'
		);
		*/
}

//! Prepare google-map items.
function gmapInsert(el, opts)
{
	if(opts.id)
		el.id= opts.id;
	if(opts.height)
		el.style.height= opts.height;
	if(opts.width)
		el.style.width= opts.width;

	if(!opts.zoom)
		opts.zoom= 8;
	if(opts.center)
		opts.center= new google.maps.LatLng(opts.center[0], opts.center[1]);
	opts.mapTypeId= google.maps.MapTypeId.ROADMAP;
	
	var map= new google.maps.Map(el, opts);
	for(i in opts.markers)
	{
		var marker= opts.markers[i];
		if(!marker.pos)
			continue;
		
		marker.position= new google.maps.LatLng(marker.pos[0], marker.pos[1]);
		marker.map= map;
		
		// --- complex icon ---
		if(marker.iconx) 
		{
			var icon= marker.iconx;
			var src, size, org, anchor;
			src= icon.src;
			if(icon.size)
				size= new google.maps.Size(icon.size[0], icon.size[1]);
			if(icon.org)
				org= new google.maps.Point(icon.org[0], icon.org[1]);
			if(icon.anchor)
				anchor= new google.maps.Point(icon.anchor[0], icon.anchor[1]);

			marker.icon= new google.maps.MarkerImage(src, size, org, anchor);
		}
		
		var mk= new google.maps.Marker(marker);
		
		if(marker.info)
		{
			var content= $("<div/>").html(marker.info).html();
			var info= new google.maps.InfoWindow({ 
				content: content
			});
			google.maps.event.addListener(mk, 'click', function() {
				info.open(map, this);
			});
		}
	}
}

function videoInsert(id, opts)
{	
	var HOST_URL= location.protocol + "//" + location.host;
	var PLAYER_URL= HOST_URL + "/mediaplayer";

	var url= opts.src;
	var width= (opts.width ? opts.width : "100%");
	var	height= (opts.height ? opts.height : "100%");
	
	if(hasFlash())		// --- JW-player stuff ---
	{
		var player= PLAYER_URL + "/player.swf";
			var flashvars= {
			file: encodeURIComponent(url), 
			width: encodeURIComponent(width), 
			height: encodeURIComponent(height),
			skin: encodeURIComponent(PLAYER_URL + "/modieus.swf"), 
			controlbar: "over",
			autostart:true
		};

		var params= {
			allowfullscreen: true, 
			allowscriptaccess: "always", 
			wmode: "opaque"
		};
		
		var res= swfobject.embedSWF(player, id, width, height, "9.0.0", "",
			flashvars, params);
	}
	else				// --- QT player ---
		$('#' + id).html(QT_GenerateOBJECTText(url, width, height, '', 'scale', 'aspect'));
}

function swfInsert(src, objID, width, height, flashvars)
{
	var params = {
		menu: "false",
		scale: "noScale",
		salign: "t",
		allowFullscreen: "true",
		allowScriptAccess: "always",
		bgcolor: "#FFFFFF"
	};
	var attributes = {
		id:"banner-obj"
	};
	swfobject.embedSWF(src, objID, width, height, "9.0.0", "expressInstall.swf", 
		flashvars, params, attributes);
}


// EOF

