/*
 * Rijkswaterstaat widget Reageer & Waardeer
 *
 * v7, 2010-06-16
 */

// addthis settings (must be top level)
var addthis_config = { 'ui_click': true, 'services_exclude': 'print,email', 'ui_language': 'nl', 'services_compact': 'plaxo,live,myspace,google,nujij,more' };
var addthis_localize = { 'share_caption': 'Deze pagina delen' };

(function (){
	// default textarea string
	var defaulttxt = '- Voer hier uw reactie in -';

	// max initial number of items to show
	var item_limit = 5;

	// textarea limits
	var maxmessagelength = 750;
	var maxnewlines = 15;

	// Google Friend Connect site id
	var GFCSiteId = '06651596394616172030';

	// hostname-dependent configuration for communication with App Engine services
	var remoteHosts = {'www.rws.nl': 'wenr-rws.appspot.com','staging.www-rws.intranet.rws.nl': 'wenr-rws.appspot.com','www.rijkswaterstaat.nl': 'wenr-rws.appspot.com','staging.www-rws.intranet.rijkswaterstaat.nl': 'wenr-rws.appspot.com','rws.nl': 'wenr-rws.appspot.com','rijkswaterstaat.nl': 'wenr-rws.appspot.com','localhost:8080': 'localhost:8080'};

	// globals
	var currentrating = 0;
	var pagedata = null;
	var remoteHost = null;
	var doc_id = null;

	// readCookie from http://www.quirksmode.org/js/cookies.html#script
	function readCookie(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];

			while (c.charAt(0) === ' ')
			{
				c = c.substring(1,c.length);
			}

			if (c.indexOf(nameEQ) === 0)
			{
				return c.substring(nameEQ.length,c.length);
			}
		}
		return null;
	}

	// pad string with zeros (prefix)
	function zeroPad(str, len)
	{
		var text = '' + str;

		while (text.length < len)
		{
			text = '0' + text;
		}

		return text;
	}

	// html encode
	function henc(str)
	{
		return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
	}

	// convert all newlines to <br /> tags
	function nl2br(str)
	{
		return str.replace(/(\r\n|\r|\n)/g,'<br />');
	}

	// build html for full widget
	function genUiHtml()
	{
		var buf = [];

		var uri = window.encodeURI(window.location.href);

		buf.push('<div class="pagestats">');
		buf.push('	<div class="bar">');
		buf.push('    <div class="left">Gemiddelde waardering:&nbsp;-</div>');
		buf.push('	</div>');
		buf.push('</div>');

		buf.push('<h2 class="noprint">Geef uw reactie/waardering</h2>');
		buf.push('<div class="session">');
		buf.push('	<div class="signedout bar">');
		buf.push('		<div>Om een reactie of waardering te geven, kunt u inloggen met Google, Twitter, Yahoo, AIM, Netlog of OpenID.</div>');
		buf.push('		<div class="fakebutton">Inloggen</div>');
		buf.push('	</div>');

		buf.push('	<div class="signedin bar">');
		buf.push('		<div class="bar">');
		buf.push('			<div class="name"></div>');
		buf.push('			<div class="gfclinks">');
		buf.push('				<a href="#settings" class="settings">Instellingen</a>');
		buf.push('				<a href="#signout" class="signout">Uitloggen</a>');
		buf.push('			</div>');
		buf.push('		</div>');

		buf.push('		<div class="newcomment">');
		buf.push('			<div class="newratinglabel">Uw beoordeling</div>');
		buf.push('			<div class="rating newrating">');

		for (var i = 1; i <= 5; i++)
		{
			buf.push('				<div class="star" title="' + i + '"></div>');
		}

		buf.push('			</div>');

		buf.push('          &nbsp;<div class="tawrap"><textarea></textarea></div>');

		buf.push('			<div class="charlimit">Max. '+maxmessagelength+' karakters</div>');

		buf.push('			<div class="fakebutton">Plaatsen</div>');
		buf.push('		</div>');

		buf.push('	</div>');

		buf.push('</div>');

		buf.push('<h2>Alle reacties en waarderingen</h2>');
		buf.push('<div class="comments">De reacties en waarderingen zijn nog niet geladen.</div>');

		return buf.join('');
	}

	// build html for bar with page statistics (average)
	function getStatsHtml(avg, count)
	{
		var ravg = Math.round(avg);
		var avgtext;
		var buf = [];

		if (isNaN(ravg))
		{
			avgtext = '-';
		}
		else
		{
			avgtext = avg.toFixed(1) + '/5';
		}

		buf.push('	<div class="left">Gemiddelde waardering ('+count+' stem'+((count == 1) ? '' : 'men')+'):&nbsp;'+avgtext+'</div>');
		buf.push('	<div class="rating">');

		for (var i = 1; i <= 5; i++)
		{
			buf.push('		<div class="star ' + ((i <= ravg) ? 'on' : '') + '" alt="' + i + '"></div>');
		}

		buf.push('	</div>');

		return buf.join('');
	}

	// build html for one item (comment + optional rating)
	function genItemHtml(item)
	{
		var buf = [];

		var ts = new Date(item.timestamp);

		buf.push('<div class="item">');

		if (item.emptied === false)
		{
			buf.push('	<a href="#' + item.author_id + '" class="profilelink"><img src="' + encodeURI(item.author_thumburl) + '" width="32" height="32" /></a>');
		}
		else
		{
			buf.push('	<img src="http://www.google.com/friendconnect/scs/images/NoPictureDark.png" width="32" height="32" />');
		}

		buf.push('	<div class="comment">');

		if (item.rating > 0)
		{
			buf.push('		<div class="rating bar">');

			for (var i = 1; i <= 5; i++)
			{
				buf.push('			<div class="star ' + ((i <= item.rating) ? 'on' : '') + '" alt="' + i + '"></div>');
			}

			buf.push('		</div>');

			buf.push('<p class="noprinthidden">Waardering: '+item.rating+'/5.</p>');
		}

		if (item.emptied === true)
		{
			buf.push('		<p><em>Deze reactie is verwijderd.</em></p>');
		}
		else if (item.text.length > 0)
		{
			buf.push('		<p>' + nl2br(henc(item.text)) + '</p>');
		}
		else
		{
			buf.push('		<p><em>Deze bezoeker heeft geen reactie achtergelaten.</em></p>');
		}

		buf.push('		<div class="meta bar">');
		buf.push('			' + zeroPad(ts.getDate(),2) + '-' + zeroPad(ts.getMonth()+1, 2) + '-' + ts.getFullYear() + ', ' + zeroPad(ts.getHours(), 2) + ':' + zeroPad(ts.getMinutes(), 2));

		if (item.emptied === false)
		{
			buf.push('			<a href="#' + item.author_id + '" class="profilelink">' + henc(item.author_name) + '</a>');
		}

		buf.push('		</div>');
		buf.push('	</div>');
		buf.push('</div>');

		return buf.join('');
	}

	// show all retrieved comments & ratings
	function updateView()
	{
		// reset ui
		$('#rwsratings .pagestats .bar').empty();
		$('#rwsratings .comments').empty();

		var comments = pagedata['comments'];

		if (comments && comments.length > 0)
		{
			var itemshtml = [];

			// generate html for items and calculate average
			for (var i = 0; i < comments.length; i++)
			{
				itemshtml.push(genItemHtml(comments[i]));
			}

			if (item_limit > 0 && pagedata['commentcount'] > item_limit)
			{
				itemshtml.push('<div class="item"><div class="comment"><a class="showmore" href="#more-items">&gt; Toon alle reacties en waarderingen</a></div></div>');
			}

			// place comments
			$('#rwsratings .comments').html(itemshtml.join(''));

			// handle showmore click event
			$('#rwsratings a.showmore').click(function(){
				item_limit = 0;
				loadItems();

				return false;
			});

			// apply styling fixes for first & last items
			$('#rwsratings .comments .item:first').css('margin-top', '0');
			$('#rwsratings .comments .item:last').css({'padding-bottom': '0', 'border-bottom': '0'});

			// set up event handler for clicks on picture or name
			$('#rwsratings .item .profilelink').click(function(){
				var href = this.href;
				var id = href.substring(href.indexOf('#') + 1);

				google.friendconnect.showMemberProfile(id);
				return false;
			});
		}
		else
		{
			// default placeholder
			$('#rwsratings .comments').html('Er zijn nog geen reacties of waarderingen gegeven.');
		}

		var ratingcount = pagedata['ratingcount'];
		var ratingtotal = pagedata['ratingtotal'];

		if (ratingcount > 0)
		{
			$('#rwsratings .pagestats .bar').html(getStatsHtml(ratingtotal / ratingcount, ratingcount));
		}
		else
		{
			$('#rwsratings .pagestats .bar').html('<div class="left">Gemiddelde waardering:&nbsp;-</div>');
		}
	}

	// disable all stars
	function resetNewRating()
	{
		$('#rwsratings .newrating .star').removeClass('on');
	}

	// show correct number of highlighted stars
	function setNewRating(value)
	{
		$('#rwsratings .newrating .star').each(
			function(idx){
				if (idx < value)
				{
					$(this).addClass('on');
				}
			}
		);
	}

	// reset form to default values
	function resetForm()
	{
		$('#rwsratings .newcomment textarea').val(defaulttxt);
		currentrating = 0;
		resetNewRating();
	}

	// disable form textarea & button
	function disableForm()
	{
		$('#rwsratings .newcomment textarea').attr('disabled', true);
		$('#rwsratings .newcomment .fakebutton').addClass('disabled waiting');
	}

	// enable form textarea & button
	function enableForm()
	{
		$('#rwsratings .newcomment textarea, #rwsratings .newcomment .fakebutton').attr('disabled', false);
		$('#rwsratings .newcomment .fakebutton').removeClass('disabled waiting');
	}

	// show warning message if comment length exceeds limit
	function checkForCharLimit(textarea)
	{
		var value = textarea.value;

		var warningvisible = $('#rwsratings .charlimit').hasClass('reached') && $('#rwsratings .newcomment .fakebutton').hasClass('disabled');

		if (value.length > maxmessagelength && !warningvisible)
		{
			$('#rwsratings .charlimit').addClass('reached');
			$('#rwsratings .newcomment .fakebutton').addClass('disabled');
		}
		else if (value.length <= maxmessagelength && warningvisible)
		{
			$('#rwsratings .charlimit').removeClass('reached');
			$('#rwsratings .newcomment .fakebutton').removeClass('disabled');
		}
	}

	// get items from server
	function loadItems()
	{
		$.ajax({
			'url': 'http://'+remoteHost+'/items',
			'data': {'doc_id': doc_id, 'rnd': new Date().valueOf(), 'item_limit': item_limit},
			'success': function(data){ pagedata = data; updateView(); },
			'dataType': 'jsonp'
		});
	}

	// show gadget UI and set up event handlers
	function initGadget()
	{
		$('#rwsratings').html(genUiHtml());
		$('#rwsratings').show();

		doc_id = $('#rwsratings').attr('class');

		// get items from server
		loadItems();

		// set up GFC event handlers
		$('#rwsratings .session .signedout .fakebutton').click(function(){
			google.friendconnect.requestSignIn();
		});

		$('#rwsratings .session .signedin .signout').click(function(){
			google.friendconnect.requestSignOut();
			return false;
		});

		$('#rwsratings .session .signedin .settings').click(function(){
			google.friendconnect.requestSettings();
			return false;
		});

		// set up folding event handlers
		$('#rwsratings h2').click(function(){
			$(this).toggleClass('folded');
			$(this).next('div').toggleClass('hidden');
		});

		// enable new rating mouseover effects
		$('#rwsratings .newrating').mouseleave(function(){
			resetNewRating();
			setNewRating(currentrating);
		});

		$('#rwsratings .newrating .star').hover(function(){
			setNewRating($(this).attr('title'));
		}, function(){
			resetNewRating();
		});

		$('#rwsratings .newrating .star').click(function(){
			var newrating = $(this).attr('title');

			// reset rating when user clicks again, else update current rating
			if (currentrating == newrating)
			{
				currentrating = 0;
			}
			else
			{
				currentrating = newrating;
			}
		});

		// set textarea to default placeholder text
		$('#rwsratings .newcomment textarea').val(defaulttxt);

		// empty textarea when user gives focus and the default text was visible
		$('#rwsratings .newcomment textarea').focus(function(){
			var curval = $(this).val();

			if (curval == defaulttxt)
			{
				$(this).val('');
			}
		});

		// place default text when user leaves textarea and no text was entered
		$('#rwsratings .newcomment textarea').blur(function(){
			var curval = $(this).val();

			if ($.trim(curval) == '')
			{
				$(this).val(defaulttxt);
			}
		});

		// check for character limit on keypresses
		$('#rwsratings .newcomment textarea').bind('keyup keydown keypress', function(){
			checkForCharLimit(this);
		});

		// set up submit event handler
		$('#rwsratings .newcomment .fakebutton').click(function(){
			if ($(this).hasClass('disabled'))
			{
				return;
			}

			var text = $('#rwsratings .newcomment textarea').val();

			// perform validation on user input
			if (text === defaulttxt && currentrating === 0)
			{
				alert('Het is verplicht om een reactie óf een waardering te geven.');
				return;
			}

			if (text.length > maxmessagelength)
			{
				alert('Uw reactie is langer dan het maximaal toegestane aantal tekens (' + maxmessagelength + ').');
				return;
			}

			var newlines = text.match(/(\r\n|\r|\n)/g);

			if (newlines !== null && newlines.length > maxnewlines)
			{
				alert('Uw reactie bevat meer dan het toegestane aantal nieuwe regels (' + maxnewlines + ').');
				return;
			}

			// prepare payload
			var data = {
				'fcauth': readCookie('fcauth' + GFCSiteId),
				'text': (text == defaulttxt) ? '' : text, // empty if default string was in textarea
				'rating': currentrating,
				'doc_id': doc_id,
				'doc_url': window.location.href,
				'doc_title': document.title
			};

			// disable form elements to prevent double submit
			disableForm();

			// send request
			$.ajax({
				'url': 'http://'+remoteHost+'/postcomment',
				'data': data,
				'dataType': 'jsonp',
				'timeout': 8000,
				'success': function(data){
					if (data !== null && typeof data == 'object')
					{
						// only reset form if we get a comment as reply
						resetForm();
						enableForm();

						pagedata['comments'].unshift(data);

						if (data['rating'] > 0)
						{
							pagedata['ratingcount']++;
							pagedata['ratingtotal'] += data['rating'];
						}

						// make sure user sees new message being added
						updateView();
					}
					else
					{
						alert('Er is een onbekende fout opgetreden tijdens het plaatsen van uw reactie. Probeert u het later opnieuw.');

						// enable form elements after error
						enableForm();
					}
				},
				'error': function(xhr, ts, et){
					if (ts === 'timeout')
					{
						alert('Uw bericht kan momenteel niet worden geplaatst vanwege een technische storing. Probeert u het later nog eens.');
					}
					else
					{
						try
						{
							if (xhr && xhr.status && xhr.status == 400 && xhr.responseText)
							{
								// handle custom errors generated by our backend
								alert(xhr.responseText);
							}
							else if (xhr && xhr.status && (xhr.status == 122 || xhr.status == 414))
							{
								// handle xhr errors with request
								alert('Uw reactie is te lang. Kort de tekst van uw reactie in voor u deze opnieuw probeert te versturen.');
							}
						}
						catch (err) {}
					}

					// enable form elements after error
					enableForm();
				}
			});
		});
	}

	// this function is called whenever the user logs in or out
	function refresh(securityToken) {
		// prepare payload
		var req = opensocial.newDataRequest();
		req.add(req.newFetchPersonRequest('VIEWER', {}), 'viewer');

		// send request
		req.send(function(data){
			if (data.get('viewer').getData()) {
				// we have a logged in user
				var viewer = data.get('viewer').getData();

				// update ui
				$('#rwsratings .session .signedin .name').html('Ingelogd als ' + viewer.getDisplayName());

				$('#rwsratings .session .signedout').hide();
				$('#rwsratings .session .signedin').show();
			}
			else
			{
				// no viewer object means no user. update ui.
				$('#rwsratings .session .signedout').show();
				$('#rwsratings .session .signedin').hide();
			}
		});
	}

	$(window).load(function(){
		// load settings for current environment
		remoteHost = remoteHosts[window.location.host];

		// initialize AddThis bar
		try
		{
			addthis.toolbox('.addthis_toolbox');
			$('.addthis_toolbox').show();
		}
		catch (e1) {}

		// initialize Google Friend Connect and widget
		try
		{
			google.friendconnect.container.initOpenSocialApi({'site': GFCSiteId, 'onload': refresh});
			initGadget();
		}
		catch (e2) {}
	});
}());
