/**
 * Room competition operations, used on:
 * - competition details page (bydesign.room_competition.views.room_competition_details
 * - room details page (bydesign.room.room_detail)
 * - profile room details page (bydesign.account.profile_room_detail)
 */

myDeco.room_competition = {

	loginUrl: myDeco.urls.userLogin+'?next='+document.location.href,
	ajaxUrls: myDeco.urls.room_competition,

	room_id: undefined, // set in the room details page
	entry_ids: undefined, // set in the room details page
	competition_id: undefined, // set in the competition details page
	has_template: false, // set in the competition details page

	/**
	 * Utility function to handle ajax failures
	 */
	handleAjaxFailure: function(source, response) {
		console.log('Error : room_competition.js : myDeco.room_competition.'+source+' ajax failure (HTTP '+response.status+' : '+response.responseText+')');
		myDeco.popupForms.alert('An unexpected error occurred.  Please try again.');
	},

	/**
	 * Global init, which will call the initRoomPage method for room details pages,
	 * or the initCompetitionPage method for competition details pages.
	 */
	init: function()
	{
		if (typeof(this.room_id) != 'undefined') {
			this.initRoomPage();
		}
		if (typeof(this.competition_id) != 'undefined') {
			this.initCompetitionPage();
		}
	},

	/**
	 * Init method for room details pages.
	 * By default, if the room is part of a competition, the vote block is shown.
	 * If user is not logged in, clicking on vote buttons will take him to login page.
	 * If user is logged in:
	 *   - if user is not room owner, then we leave the block so he can vote
	 *   - if user is room owner, we hide that block, and make ajax request to get
	 *   the available competitions instead and display them. On room detail page,
	 *   if user is room owner and room run in competition, we also hide block's parentNode(see site-3815)
	 * Then, voting or entering a competition will make ajax request and display the result.
	 */
	initRoomPage: function()
	{
		var obj = this;
		this.entry_ids.each(function(item) {
			var e = $('vote-'+item);
			if (e) {
				if (!myDeco.username) {
					e.href = obj.loginUrl;
				} else {
					e.observe('click', obj.voteForEntry.bindAsEventListener(obj, item));
				}
			}
		});
		if (this.room_owner == myDeco.username)
		{
			if ($('competition-vote')) {
				$('competition-vote').hide();
			}
			if ($('competition-entry')) {
				this.getAvailableCompetitions();
			}
		}
	},

	/**
	 * Ajax onSuccess handler for voting.
	 * Result is displayed, replacing the vote button.
	 */
	showVoteResult: function(response)
	{
		var result = response.responseText.evalJSON();
		var tk = $('thankyou-'+result.entry_id);
		$('vote-'+result.entry_id).hide();
		if (!result.success) {
			tk.addClassName('error');
			tk.update(result.error);
		}
		tk.show();
	},

	/**
	 * Click handler for voting button.
	 * Triggers ajax request.
	 */
	voteForEntry: function(event, entry_id) {
		event.stop();
		new Ajax.Request(this.ajaxUrls.vote_ajax, {
			parameters: {'entry_id':entry_id},
			onSuccess: this.showVoteResult.bind(this),
			onFailure: this.handleAjaxFailure.bind(this, 'voteForEntry')
		});
	},

	/**
	 * Ajax onSuccess handler for getting available competitions.
	 * A new block showing them is displayed. Voting block is hidden.
	 */
	showAvailableCompetitions: function(response)
	{
		var result = response.responseText.evalJSON();
		if (result.success && result.entry_block.length) {
			var entry_block  = $('competition-entry');
			var entry_parent = entry_block.up('.room-detail-competition-block')
			entry_block.update(result.entry_block);
			entry_block.show();
			if (this.room_owner == myDeco.username && entry_block.empty() && entry_parent){
				entry_parent.hide();
			}
		}
		myDeco.formControls.submitButtons.init();
		var obj = this;
		result.competition_ids.each(function(competition_id) {
			var e = $('entry-form-'+competition_id);
			e.observe('submit', obj.enterCompetitionWithRoom.bindAsEventListener(obj, competition_id));
		});
	},

	/**
	 * Retrieval of available competitions a room can enter,
	 * used when the user looking at the room details page is the room owner.
	 */
	getAvailableCompetitions: function() {
		new Ajax.Request(this.ajaxUrls.available_competitions_ajax, {
			parameters: {'room_id':this.room_id},
			onSuccess: this.showAvailableCompetitions.bind(this),
			onFailure: this.handleAjaxFailure.bind(this, 'getAvailableCompetitions')
		});
	},

	/**
	 * Ajax onSuccess handler for entering competition.
	 * Result is displayed, replacing the enter button.
	 */
	showEntryResult: function(response)
	{
		var result = response.responseText.evalJSON();
		var er = $('error-'+result.competition_id);
		if (!result.success) {
			var er = $('error-'+result.competition_id);
			er.update(result.error).show();
		}
		else {
			er.hide();
			$('entry-form-'+result.competition_id).hide();
			var gl = $('goodluck-'+result.competition_id);
			gl.select('a.force-cache-miss').each(function(item){myDeco.addCacheMissParam(item);});
			gl.show();
		}
	},

		/**
		 * Submit handler for small competition form button.
		 * Tries to recognize postcode/adress via myDeco.location2coords.
		 * Then sends form data in any case via AJAX by calling
		 * object method _enterCompetitionWithRoom().
		 */
		enterCompetitionWithRoom: function(event, competition_id) {
			event.stop();
			var obj = myDeco.room_competition,
				form = $('entry-form-'+competition_id);
			// We'll try to recognize postcode/adress and will send form data in any case
			if (form['postcode']) {
				myDeco.location2coords(form['postcode'].getValue(),
					function(coords){
						obj._enterCompetitionWithRoom(competition_id, coords);
					},
					function(error){
						console.log('myDeco.room_competition.enterCompetitionWithRoom:',error);
						obj._enterCompetitionWithRoom(competition_id);
					}
				);
			} else {
				obj._enterCompetitionWithRoom(competition_id);
			}
		},
		/**
		 * Callback for location2coords, gets competition_id
		 * and coords from location2coords. Then sends form data
		 * via AJAX.
		 */
		_enterCompetitionWithRoom: function(competition_id, coords){
			var obj = myDeco.room_competition,
				form = $('entry-form-'+competition_id);
			if (coords){
				form['coords'].value = coords[0]+','+coords[1];
			}
			new Ajax.Request(obj.ajaxUrls.entry_ajax, {
				parameters: Object.extend(form.serialize(true),
					{'room':obj.room_id, 'competition':competition_id }
				),
				onSuccess: obj.showEntryResult.bind(obj),
				onFailure: obj.handleAjaxFailure.bind(obj, 'entry'),
				onComplete: function() {
					myDeco.formControls.submitButtons.enable(form);
				}
			});
		},

	/**
	 * Processes Ajax requests to login and registration services.
	 * Handles error processing. Shows competition entry form on
	 * successfull registration or login. Reassigns button's
	 * click event to competition entry form showing handler.
	 *
	 * @param {Event} e Event instance
	 * @param {Element} loginBlock Login/registration form dialog
	 * @param {Element} button "Enter" button element
	 */
	loginOrRegister: function(e, loginBlock, button) {
		e.stop();
		var form = e.element(),
		self = this;
		// Calling login or registration web service
		new Ajax.Request(form.readAttribute('action'), {
			'method': 'post',
			'parameters': form.serialize(true),
			'onSuccess': function(transport) {
				// Initializing user data
				myDeco.user.setUserData();
				myDeco.user.init();
				loginBlock.hide();
				// Reassigning event handler
				button.stopObserving('click');
				button.observe('click', self.getEntryForm.bindAsEventListener(self));
				// Calling competition entry form
				self.getEntryForm();
			},
			'onFailure': function(transport) {
				var response = transport.responseText.evalJSON();
				// Hiding all error blocks
				form.select('.error').invoke('hide');
				if (typeof response.error.message == 'object') {
					// If errors are attached to fields - process accordingly
					$H(response.error.message)._each(function(error) {
						var field = form.down('#id_'+error.key+'_new_error');
						if (field) {
							field.update(error.value).show();
						}
					});
				} else {
					form.down('.error').update(response.error.message).show();
				}
			},
			onComplete: function() {
				myDeco.formControls.submitButtons.enable(form);
			}
		});
	},


	/**
	 * Shows login/register form dialog. Attaches submit handlers
	 * to login and register forms.
	 *
	 * @param {Event} e Event instance
	 */
	showLoginForm: function(e) {
		e.stop();
		var competitionLoginBlock = $('competition-login-div'),
		button = e.element();
		if (competitionLoginBlock) {
			competitionLoginBlock.show();
			competitionLoginBlock.down('#competition-login').observe('submit', this.loginOrRegister.bindAsEventListener(this, competitionLoginBlock, button));
			competitionLoginBlock.down('#competition-register').observe('submit', this.loginOrRegister.bindAsEventListener(this, competitionLoginBlock, button));
			competitionLoginBlock.down('.close').observe('click', function(e) {
				e.stop();
				competitionLoginBlock.hide();
			});
		}
	},
	reloadPage: function() {
		window.location.href = myDeco.addCacheMissParam(window.location.href);
	},
	/**
	 * Init method for competition details pages.
	 * If a logged in user wants to enter the competition from that page,
	 * an entry form is retrieved by AJAX and displayed. It lets user either use room tools
	 * to create a new one, or pick up one of its existing rooms.
	 * Entry form submission is also done using AJAX.
	 * Logged out users are shown login/register form.
	 */
	initCompetitionPage: function()
	{
		var self = this;
		$$('#get-started-now, #be-the-first').invoke('observe','click', function(e){
			if (!myDeco.username) {
				self.showLoginForm(e);
			} else {
				self.getEntryForm(e);
			}
		});
		if ($('tab-entries-on-a-map-container')) { myDeco.room_competition.geo.init(); }

		var showAllButton = $('show-all-entries');
		if (showAllButton) {
			showAllButton.observe('click', this.showAllEntries);
		}
		// observe model editor
		$$('body').invoke('observe', 'modeleditor:compenter', self.reloadPage.bindAsEventListener(self));
	},


	/**
	 * Handler for use this room button on entry form.
	 * Triggers ajax request.
	 */
	useThisRoom: function(event) {
		var form = event.findElement('FORM');
		event.stop();
		return form.request({
			onSuccess: function(response) {
				var result = response.responseText.evalJSON();
				var er = $('entry-error');
				if (!result.success) {
					er.update(result.error);
					er.show();
				} else {
					form.select('.submit-button').invoke('hide');
					er.hide();
					var gl = $('goodluck');
					gl.show();
				}
			},
			onFailure: this.handleAjaxFailure.bind(this, 'useThisRoom'),
			onComplete: function() {
				myDeco.formControls.submitButtons.enable(form);
			}
		});
	},

		/**
		* Submits competition entry form relying on its type
		*/
		submitEntry: function(e){
			var form = e.findElement('FORM');
			e.stop();
			if (form.id=="upload-photo-form") {
				setTimeout(function(){form.submit();}, 50);
			} else {
				this.useThisRoom(e);
			}
		},

	/**
	 * Called by hidden iframe on photo uploading.
	 * Displays error on form or success message.
	 */
	uploadPhotoResult: function(success,error) {
		var er = $('upload-photo-error');
		if (!success) {
			er.update(error);
			er.show();
			myDeco.formControls.submitButtons.enable();
		} else {
			try {
				var s=s_gi(s_account);
				s.pageName=s_pagename+'[Ajax]';
				s.prop3=s_pagetype+'[Ajax]';
				s.prop8='room_photo';
				s.t();
			}
			catch (e) { }
			$('competition-entry-div').hide();
			window.setTimeout(function(){window.location.href = myDeco.addCacheMissParam(window.location.href);},1000)
		}
	},

	/**
	 * Click handler for close button on entry form.
	 * Hides the entry form.
	 */
	closeEntryForm: function(event) {
		event.stop();
		$('competition-entry-div').hide();
	},

	/**
	 * Ajax onSuccess handler for getting the entry form for a logged in user.
	 * Form is shown. Room tools popups links are initialized.
	 */
	showEntryForm: function(response)
	{
		var result = response.responseText.evalJSON();
		if (result.success) {
			var form_div = $('competition-entry-div');
			form_div.update(result.form_block);
			form_div.show();
			form_div.select('form').invoke('observe', 'submit', this.getCoords.bind(this));
			$('close-entry-form').observe('click', this.closeEntryForm.bindAsEventListener(this));
			$$('a.create-and-enter').invoke('observe', 'click', function(e) {
				e.stop();
				var el = e.findElement('a');
				switchToolState(e, 'enterCompetition', el.rel, el);
				$('competition-entry-div').hide();
			});
			myDeco.fileInputs.init();
			myDeco.formControls.submitButtons.init();
			// adjust div height if larger than body
			var gap = $('body').getHeight() - form_div.cumulativeOffset().top - form_div.getHeight();
			if (gap < 20) {
				form_div.setStyle({ height: form_div.getHeight() - 30 + gap - 20 + 'px' });
				var scroller = $('competition-entry-scroll');
				scroller.setStyle({ height: scroller.getHeight() - 30 + gap - 20 + 'px' });
			}
		}
	},

	/**
	 * Click handler to get the entry form.
	 * Triggers ajax request.
	 */
	getEntryForm: function(event) {
		if (event) {
			event.stop();
		}
		if (!myDeco.room_competition.has_template) {
			new Ajax.Request(this.ajaxUrls.entry_form_ajax, {
				parameters: {'competition_id':this.competition_id},
				onSuccess: this.showEntryForm.bind(this),
				onFailure: this.handleAjaxFailure.bind(this, 'getEntryForm')
			});
	    } else {
			var link = $('get-started-now');
			switchToolState(event, 'enterCompetition', link.rel, link);
	    }
	},
	/**
	 * Submit callback, gets coordinates of postcode, if postcode and coords
	 * fields are present in form.
	 */
	getCoords: function(e){
		var self = this,
			form = e.element();
		e.stop();
		if (!form['coords'] || !form['postcode'] || !form['postcode'].getValue()) {
			this.submitEntry(e);
			return;
		}
		myDeco.location2coords(form['postcode'].getValue(),
			function(coords){
				form['coords'].value = coords[0]+','+coords[1];
				self.submitEntry(e);
			},
			function(error){
				console.log('myDeco.room_competition.enterCompetitionWithRoom:',error);
				self.submitEntry(e);
			}
		);
	},

	/**
	 * Show all competition entries block.
	 *
	 * @param {Event} event Event instance
	 */
	showAllEntries: function(event) {
		event.stop();
		event.element().hide();
		$('competition-entries').appear();
	}
}

addLoadEvent(myDeco.room_competition.init.bind(myDeco.room_competition));

myDeco.room_competition.geo = {
	markers: [],
	map: null,
	current_location: null,
	init: function(){
		var obj = myDeco.room_competition.geo,
			tabs = myDeco.tabs.tabSwitcherCollection.getSwitcherById('competition-tab-switcher');
		tabs.addCallback(obj.tabCallback);
	},
	initMapView: function(){
		if (!$('competition-map') && !GMap2 && !ExtLargeMapControl && !ExtInfoWindow) { return; }
		if (!GBrowserIsCompatible()) {
			myDeco.popupForms.alert('Sorry, your browser is not yet supported to use this tool.');
			return;
		}
		$('postcode-form').observe('submit', function(){ obj.refineMapView(); });
		var obj = myDeco.room_competition.geo;
		obj.map = new GMap2(document.getElementById("competition-map"));
		obj.map.getMapTypes().each(function(map_type){
			map_type.getMaximumResolution = function(){ return 11; }
		});
		obj.map.setCenter(new GLatLng(54.5, -4.5), 6);
		obj.map.addControl(new GMapTypeControl());
		obj.map.addControl(new ExtLargeMapControl());
		obj.map.enableScrollWheelZoom();
	},
	tabCallback: function(tab){
		var obj = myDeco.room_competition.geo;
		if (tab.getContainer().id == 'tab-entries-on-a-map-container') { obj.showMapView(); }
	},
	showMapView: function() {
		var obj = myDeco.room_competition.geo;
		if (!obj.map) { obj.initMapView(); }
		new Ajax.Request(myDeco.urls.room_competition.geo_entries_ajax, {
			method: 'get',
			parameters: {'competition_id': myDeco.room_competition.competition_id},
			onSuccess: obj.addMarkers,
			onFailure: myDeco.room_competition.handleAjaxFailure.bind(this, 'useThisRoom')
		});
	},
	refineMapView: function(){
		var obj = myDeco.room_competition.geo,
			postcode = $('postcode').getValue();
		if (!postcode) { return false; }
		$('postcode').removeClassName('error');
		myDeco.location2coords(postcode, function(coord){
			var obj = myDeco.room_competition.geo,
				center = new GLatLng(coord[0],coord[1]),
				icon = new GIcon(G_DEFAULT_ICON);
			obj.map.setCenter(center);
			if (obj.homeMarker) { obj.map.removeOverlay(obj.homeMarker); }
			icon.image = myDeco.settings.STATIC_URL + 'img/geo/markers/home.png';
			icon.shadow = null;
			icon.iconSize = new GSize(34, 34);
			icon.iconAnchor = new GPoint(17, 34);
			icon.infoWindowAnchor = new GPoint(15, 12);
			obj.homeMarker = new GMarker(center, {icon: icon});
			obj.homeMarker.showInfo = function(){
				this.openExtInfoWindow(obj.map, 'geo-home',
					'<div class="geo-info-window-wrap">You are here</div>',
					{ beakOffset: -1, paddingX: 110, paddingY: 110 }
				);
			};
			GEvent.addListener(obj.homeMarker, "click", function() { this.showInfo(); });
			obj.map.addOverlay(obj.homeMarker);
			var sorted_markers = obj.markers.sortBy(function(marker){
				return marker.getLatLng().distanceFrom(center);
			});
			var bounds = new GLatLngBounds();
			bounds.extend(center);
			sorted_markers.each(function(marker, i){
				if (i < 5) { bounds.extend(marker.getLatLng()); }
			});
			obj.map.setCenter(bounds.getCenter());
			obj.map.setZoom(obj.map.getBoundsZoomLevel(bounds));
		}, function(){
			$('postcode').addClassName('error');
		});
		return true;
	},
	addMarkers: function(transport){
		var obj = myDeco.room_competition.geo,
			result = transport.responseText.evalJSON(),
			bounds = new GLatLngBounds();
		obj.markers.each(function(marker){
			obj.map.removeOverlay(marker);
		});
		if (result.success) {
			result.rooms.each(function(room, i){
				var icon = new GIcon(G_DEFAULT_ICON);
				icon.shadow = myDeco.settings.STATIC_URL + 'img/geo/markers/shadow50.png';
				icon.image = myDeco.settings.STATIC_URL + 'img/geo/markers/red-dot.png';
				icon.infoWindowAnchor = new GPoint(7, 2);
				room.coords = room.coords.split(',');
				room.coords = new GLatLng(room.coords[0], room.coords[1]);
				bounds.extend(room.coords);
				var marker = new GMarker(room.coords, {icon: icon});
				marker.showInfo = function(){
					this.openExtInfoWindow(obj.map, 'geo-entity',
						'<div class="geo-info-window-wrap">'+
							'<div class="room-competition-thumb" style="background-image:url('+room.thumbnail+')">'+
								'<a href="'+room.url+'" title="'+room.name+'"></a>'+
							'</div>'+
							'<h3><a class="c2" href="'+room.url+'">'+room.name+'</a></h3>'+
							'<p>Created by <a href="/people/'+room.author+'/summary/">'+room.author+'</a></p>'+
						'</div>',
						{ beakOffset: -1, paddingX: 110, paddingY: 110 }
					);
				}
				GEvent.addListener(marker, "click", function() { this.showInfo(); });
				obj.map.addOverlay(marker);
				obj.markers[i] = marker;
			});
			if (!obj.refineMapView()) {
				obj.map.setCenter(bounds.getCenter());
				obj.map.setZoom(obj.map.getBoundsZoomLevel(bounds));
			}
		}
	}
}
