/**
* file: WizardWidget.js
* @author Richard Assar, Daniel Winterstein
*/

// TODO refactor -- DBW
// Move more html into templates.
// Break out long nested sections
// TODO Document assumptions re what the server will send to activate stuff. -- DBW

loadTemplates("/static/code/widgets/WizardWidgets.html");

function ajaxifyReportWizard() {
	console.log("ajaxify ReportWizard...");

	$("a.ReportWizard").not(".ajaxed").not(".noajax").each(function() {		
		// BEGIN PREDEFINED STAGES //
		var predefinedStages = {
			"puppet" : {
				'prompt' : "Select a puppet",
				'description' : "Select a puppet",
				'init' : function() {
					puppetSelectElement.val('');	// TODO - :disabled CSS selector should probably be used in place of setting opacity
					puppetSelectElement.css('opacity', '');
					puppetSelectElement.removeAttr("disabled");
				},				
				'uninit' : function() {
					puppetSelectElement.css('opacity', 0.5);
					puppetSelectElement.attr("disabled", "disabled");
				},
				"params" : function() {
					var puppet = puppetSelectElement.val();
					
					if(puppet.length > 0) {					
						return {
							'puppet' : puppetSelectElement.val()
						};
					} else {
						return;
					}
				}
			},

			"tagSet" : {			
				'prompt' : "Select the tag set to filter on",
				'description' : "",
				'init' : function() {
					tagSetFilterElement.css('opacity', '');
					tagSetFilterElement.find('.active').removeClass('active');
				},				
				'uninit' : function() {
					tagSetFilterElement.css('opacity', 0.5);
				},
				"params" : function() {
					return {
						'tagset' : tagSetFilterElement.find(".active").attr("name")
					};
				}
			},		

			"period" : {
				'prompt' : "Select a date range",			
				'description' : "Select a date range from the highlighted filter below",
				'shouldSkip' : function() {
					return urlVars.start !== undefined && urlVars.end !== undefined;						
				},
				'init' : function() {	
					dateFieldsElement.css('opacity', '');
	
					startDateFieldElement.val('');
					endDateFieldElement.val('');

					startDateFieldElement.removeAttr("disabled");
					endDateFieldElement.removeAttr("disabled");
				},
				'uninit' : function() {							
					dateFieldsElement.css('opacity', 0.5);

					startDateFieldElement.attr("disabled", "disabled");
					endDateFieldElement.attr("disabled", "disabled");
				},
				"params" : function() {
					return {
						'start' : startDateFieldElement.val(),
						'end' : endDateFieldElement.val()
					};
				}		
			},

			"generate" : {
				'prompt' : "Generate the report",			
				'description' : "You are now ready to generate the report",				
				'init' : function() {
					generateButtonElement
						.removeAttr("disabled")
						.css('z-index', 2);
			
					wizardOverlayElement.fadeTo(250, 0.75);

					wizardElement.addClass("final");
				},
				'uninit' : function() {
					generateButtonElement
						.attr("disabled", "disabled")
						.css('z-index', '');

					wizardOverlayElement.fadeOut()

					wizardElement.removeClass("final");
				}			
			}
		};
		// END PREDEFINED STAGES //
	
		var reportAnchor = $(this);
		
		reportAnchor.addClass("ajaxed");

		// Open/close
		reportAnchor.click(function() {	
			if($(this).hasClass("open")) {
				$(this).removeClass("open");

				close();
			} else {
				$(this).addClass("open");

				open();
			}
		
			return false;
		});

		// Add wizard
		var wizardElement = $("<div>").addClass("ReportWizard").addClass("Wizard").hide();	

		wizardElement.append("<p>In order to create a report you must complete the following steps:</p>");
		
		$("#main .Wizards").append(wizardElement);

		// Create the stages array
		var stages = new Array();

		// Create the enabled stages object
		var enabledStages = new Object();

		// Define curret stage index
		var currentStage = 0;

		// Get required/specified stags
		var stagesAttr = $(this).attr("stages").split(",");
		var specifiedStages = stagesAttr;

		// Populate the stages array from predefinedStages[specifiedStage] over specifiedStage/s/
		_.each(specifiedStages, function(stage) {
			var isOptional = false;
			
			if(stage.substr(0, 1) == '[') {
				isOptional = true;

				stage = stage.substr(1, stage.length - 2);
			}
		
			var aStage = predefinedStages[stage];

			aStage.name = stage;
			aStage.isOptional = isOptional;
			
			stages.push(aStage);
			
			enabledStages[stage] = true;
		});

		// Add the final stage.
		stages.push(predefinedStages["generate"]);			
			
		// Extend/swizzle the first stage init functions to include showOverlay()

		// Add stages
		var stagesListElement = $("<ol>").addClass("stages");

		_.each(stages, function(stage, index) {
			var stageElement = $("<li>")
				.text(stage.prompt + (stage.isOptional ? ' (optional)' : ''));

			if(index == currentStage) {
				stageElement.addClass("current");
			}
		
			stagesListElement.append(stageElement);
		});

		var stagePromptElements = stagesListElement.find("li");
		
		wizardElement.append(stagesListElement);
		
		// Add puppet select to the wizard (if stage is enabled)
		if(enabledStages["puppet"]) {
			var puppetSelectElement = $("<select>");

			puppetSelectElement.append(
				$("<option>")
					.attr("value", "")
					.text("Please select a puppet...")
			);
			
			_.each(Creole.puppets, function(puppet) {
				puppetSelectElement.append(
					$("<option>")
						.attr("value", puppet.xid)
						.text(puppet.name)
				);
			});
			
			// if the current user is a puppet, include as an option
			if (Creole.user.isPuppet) {
				puppetSelectElement.append(
					$("<option>" + Creole.user.name + "</option>").attr("value", Creole.user.xid)					
				);
			}

			puppetSelectElement.change(function() {
				nextStage();
			});

			wizardElement.append(puppetSelectElement);	
		}

		// Add tagset picker to the wizard (if stage is enabled)
		if(enabledStages["tagSet"]) {
			var tagSetFilterElement = $("<ul>").addClass("tagset");

			function tagSetClick() {
				if(stages[currentStage].name == "tagSet") {
					$(this).addClass("active");
			
					nextStage();
				}

				return false;	
			};

			// Append "Search" tagSet
			tagSetFilterElement.append(
				$("<li>").append(
					$("<a>")
						.attr("href", "#")
						.attr("name", "search")
						.text("Search")
						.click(tagSetClick)
				)						
			);	
				
			_.each(Creole.tagSets, function(tagSet) {
				tagSetFilterElement.append(
					$("<li>").append(
						$("<a>")
							.attr("href", "#")
							.attr("name", tagSet.name)
							.text(tagSet.name)
							.click(tagSetClick)
					)						
				);			
			});
		
			wizardElement.append(tagSetFilterElement);						
		}

		// Add date fields, if period stage is enabled
		if(enabledStages["period"]) {
			var dateFieldsElement = $("<div>")
				.addClass("dateFields")
				.css("opacity", 0.5);

			// Start
			var startDateLabelElement = $("<label>");			
			var startDateFieldElement = $("<input>")
				.attr("disabled", "disabled")			
				.addClass("DateField");

			startDateLabelElement.append($("<span>").text("from"));
			startDateLabelElement.append(startDateFieldElement);

			dateFieldsElement.append(startDateLabelElement);
			
			// End
			var endDateLabelElement = $("<label>");			
			var endDateFieldElement = $("<input>")
				.attr("disabled", "disabled")
				.addClass("DateField");

			endDateLabelElement.append($("<span>").text("to"));
			endDateLabelElement.append(endDateFieldElement);

			dateFieldsElement.append(endDateLabelElement);		

			// Canned dates
			var options = {};

			options['1 day'] = 60 * 60 * 24;
			options['1 week'] = options['1 day'] * 7;
			options['2 weeks'] = options['1 week'] * 2;
			options['1 month'] = options['1 day'] * 30;

			for(var label in options) {
				dateFieldsElement.append(
					$("<a>")
						.attr("href", "#")
						.text(label)
						.click(function() {
							var deltaTime = options[$(this).text()];

							startDateFieldElement.val(
								PHPJS.date("d/m/Y H:i O", new Date().getTime() / 1000 - deltaTime)
							);

							endDateFieldElement.val(
								PHPJS.date("d/m/Y H:i O", new Date().getTime() / 1000)
							);

							nextStage();

							return false;
						})
				);
			}

			// Populate with values from DateFilter, if exists	
			startDateFieldElement.val(urlVars.start);
			endDateFieldElement.val(urlVars.end);

			// Append datefields to wizard
			wizardElement.append(dateFieldsElement);

			// Ajaxify the dateFields
			ajaxifyDateFields();

			// Attach an onClose callback
			dateFieldsElement.find("input.DateField")
				.dateTimeInput({
					"onClose" : function(event) {				
						if(startDateFieldElement.val().replace(/^\W+/, '') != '' && endDateFieldElement.val().replace(/^\W+/, '') != '') {
							nextStage();
						}
					}
				});
		}

		// Footer content (buttons/description)
		var footerElement = $("<div>").addClass("footer");	
		
		// Add back "button"
		var backButtonElement = $("<button>")
			.html("&laquo; Go back a step")		
			.addClass("shiny large back") 
			.click(function() {
				prevStage();

				return false;
			});

		footerElement.append(backButtonElement);

		// Add "skip this step" button
		var skipButtonElement = $("<button>")
			.html("Skip this step &raquo;&raquo;")		
			.addClass("shiny large skip") 
			.attr("disabled", "disabled")
			.click(function() {	
				nextStage();

				return false;
			});

		footerElement.append(skipButtonElement);

		// Add description text @deprecated
		var descriptionElement = $("<p>")
			.addClass("description")
			.text(stages[currentStage].description)
			.hide();

		footerElement.append(descriptionElement);

		// Add generate button
		var generateButtonElement = $("<button>")
			.text("Generate report")
			.addClass("shiny large generate")
			.attr("disabled", "disabled")
			.click(function() {				
				var searchFormElement = $(".SearchBar form");

				var params;

				if(searchFormElement.length > 0) {			
					params = searchFormElement.serializeObject(); 
				}
				
				params = $.extend(params, {
					'action' : reportAnchor.attr("action")
				});
				
				// Add parameters from all enabled stages
				_.each(enabledStages, function(_true, stage) {
					params = $.extend(params, predefinedStages[stage].params());
				});

				// Additional params supplied in ReportWizard anchor
				var reportAnchorParams = getUrlVars(reportAnchor.attr("href"));

				params = $.extend(params, reportAnchorParams);

				// Build query string and redirect		
				window.location = '/report-generate?' + $.param(params);
			});
			
		footerElement.append(generateButtonElement);

		// Append the footer element
		wizardElement.append(footerElement);

		// Add overlay to filter
		var overlayElements = new Array();
		
		_.each($("#main .filters, #aboutTweep"), function(element) {
			var overlayElement = $("<div>")
				.addClass("overlay")
				.hide();

			overlayElements.push(overlayElement);		
			
			$(element).append(overlayElement);		
		});

		// Add overlay to wizard
		var wizardOverlayElement = $("<div>")
			.addClass("overlay")
			.hide();
		
		wizardElement.append(wizardOverlayElement);

		// Show overlay
		function showOverlay() {
			_.each(overlayElements, function(overlayElement) {
				overlayElement.stop().fadeTo(250, 0.75);
			});
		};

		// Hide overlay
		function hideOverlay() {
			_.each(overlayElements, function(overlayElement) {
				overlayElement.stop().fadeOut(250);
			});
		};
		
		// Open
		function open() {													
			// Set stage to 0
			if(!setStage(0)) { // If stage0 to be skipped...
				nextStage(); // Move on.
			};			

			wizardElement.slideToggle();

			showOverlay();
		};

		// Close
		function close() {
			stages[currentStage].uninit();

			wizardElement.slideToggle();

			hideOverlay();
		};

		// Set stage
		function setStage(stage) {			
			// Update the stage > arrows > highlight > ...
			$(stagePromptElements[currentStage]).removeClass("current");
			$(stagePromptElements[stage]).addClass("current");

			// Uninitialise the current stage
			stages[currentStage].uninit();

			// Set the current stage value
			currentStage = stage;

			// Add/remove disabled attr to backButton
			if(currentStage == 0) {
				backButtonElement.attr("disabled", "disabled");
			} else {
				backButtonElement.removeAttr("disabled");
			}

			// Is the stage optional	
			if(stages[currentStage].isOptional) {
				// Enable the skip button.
				skipButtonElement.removeAttr("disabled");
			} else {
				// If not disable it.
				skipButtonElement.attr("disabled", "disabled");
			}
				
			// If we should skip the current stage
			if(stages[currentStage].shouldSkip !== undefined && stages[currentStage].shouldSkip()) {
				return false; // Skip it.
			} else { // Otherwise			
				// Init the new stage
				stages[currentStage].init();

				// Update the description text
				descriptionElement.text(stages[currentStage].description);	

				return true;
			}		
		};

		// Next stage
		function nextStage() {	
			assert(currentStage < stages.length, "currentStage out of bounds");
							
			while(true) { 
				console.log("reportWizard", currentStage); 
							
				if(setStage(currentStage + 1)) break; 
				
				if(currentStage >= stages.length - 1) break; 								
			};

			// Following code handles display of back button, ensures that there is a non-skipped stage from [0, currentStage)
			var allPreviousStagesSkipped = true;

			for(var i = 0; i < currentStage; i++) {
				if(stages[i].shouldSkip === undefined || !stages[i].shouldSkip()) {
					allPreviousStagesSkipped = false;
				}
			}

			if(allPreviousStagesSkipped) { 
				backButtonElement.attr("disabled", "disabled");
			}
		};		

		// Prev stage
		function prevStage() {
			assert(currentStage > 0, "currentStage out of bounds");					
				
			while(true) { 
				console.log("reportWizard", currentStage); 

				if(setStage(currentStage - 1)) break;
							
				if(currentStage <= 0) break; 				
			};
		};			
	});

	console.log("... ajaxify ReportWizard done.");
};

console.log("registering ajaxify ReportWizard...");

ajaxifyFunctions.push(ajaxifyReportWizard);

$(ajaxifyReportWizard);

