/*
	Copyright (c) 2006-2010, ePages GmbH
	All Rights Reserved.

	epages.widget.LocalizedWidget $Revision: 1.39 $
*/
dojo.provide("epages.widget.WizardController");
dojo.require("epages.widget.LocalizedWidget");
dojo.require("epages.io.json");
dojo.require('epages.uimessagehandler');
dojo.require('epages.string');
dojo.require('epages.browser');
dojo.require('dojo.number');



dojo.declare("epages.widget.WizardController",[epages.widget.LocalizedWidget],{
		/**
		* public properties
		*/
		currentLanguageId : undefined,   // integer - id of current language
		controllerName    : '',          // string - name of controller
		url               : '?',         // string - request url
		saveOnNext        : false,       // boolean - flag that indicates weather the wizards saves after every step or not
		showQuickFinish   : false,       // boolean - flag that indicates weather the show link to finish page will be displayed or not
		debugMode         : false,       // boolean - flag to run the wizard in debug mode
		finishButtonLabel : "",          // string - label of finish button node
		finishRedirectURL : "",          // string - this url is called after the finish step
		cancelRedirectURL : "",          // string - this url is called after clicking the cancel button

		/**
		* private properties
		*/
		_steps                  : undefined,  // array - array with step data objects
		_objects                : undefined,  // hash - contains epages objects: <objectId> : { saveValues: [], saveNames: [], changeActions: []) }
		_jsonHandler            : undefined,  // epages.io.Json - communication
		_initialized            : undefined,  // boolean - you can not add steps after the wizard is initialized
		_activeStep             : undefined,  // integer - index of current step
		_stepNavigation         : undefined,  // array - array with navigation  { node : stepNode, bubbleNode : bubbleNode, stepNumber : i }
		_defaultChangeAction    : 'Save',     // string - default save action for objects (_objects)
		_stepStates             : [
			'Active','Disabled','Done'
		],                                    // array - navigation states (css classes)
		_hideBubbleTimeout      : undefined,  // timeout reference
		HIDEBUBBLE_TIMEOUT      : 800,        // integer - navigation bubble timeout value in ms

		/**
		* dojo widget properties
		*/
		templatePath     : dojo.moduleUrl('epages.widget','templates/WizardController.html'),
		translationName  : dojo.moduleUrl('epages.widget','templates/translation'),
		widgetsInTemplate:true,

		postMixInProperties: function(){
			//summary: initialize all necessary objects and arrays, convert flags to real boolean
			this.inherited("postMixInProperties", arguments);
			if(this.finishButtonLabel == "") {
				this.finishButtonLabel = this.translate("Finish");
			}
			this._jsonHandler = new epages.io.Json();
			this._steps = [];
			this._objects = undefined;
			this._stepNavigation = [];
			this._initialized = false;
			this.showQuickFinish = epages.string.toBoolean(this.showQuickFinish);
			this.saveOnNext = epages.string.toBoolean(this.saveOnNext);
			//if(epages.vars.DebugLevel && epages.vars.DebugLevel != 0){
				this.debugMode = true;
			//}
			if(epages.Browser.engine == "MSIE") {
				var htmlTag = document.getElementsByTagName("html")[0];
				htmlTag.style.overflow="visible";
			}
		},

		postCreate: function(){
			this.inherited("postCreate", arguments);
			if(this.cancelRedirectURL) {
				this.closeButtonNode.style.display="";
			}
		},

		startup: function(){
			//summary: make all event connects and connect to Switch to Edit Mode topic
			this.inherited("startup", arguments);

			dojo.body().appendChild(this.domNode);

			//attach events
			//catch all events that happen inside the domNode
			this.connect(this.domNode,'onclick', '_onDomNodeEvent');
			this.connect(this.domNode,'onkeyup', '_onDomNodeEvent');
			this.connect(this.domNode,'onchange', '_onDomNodeEvent');
			//connect all buttons
			this.connect(this.NextButton.domNode,'onclick', '_onNextButtonClick');
			this.connect(this.BackButton.domNode,'onclick', '_onBackButtonClick');
			this.connect(this.SaveButton.domNode,'onclick', '_onSaveButtonClick');

			// bubble events
			this.connect(this.StepNavigationBubble.domNode,'onmouseleave', '_hideStepNavigationBubble');      //hide stepNavigationBubble on mouse leave of the bubble
			this.connect(this.StepNavigationNode, 'onmouseleave', '_hideStepNavigationBubble');               //hide stepNavigationBubble on mouse leave of the bubble
			this.connect(this.StepNavigationBubble.domNode,'onmouseenter', '_dontHideStepNavigationBubble');  //clear timeout

			if(this.showQuickFinish){
				this.connect(this.QuickFinish,'onclick', '_onQuickFinishClick');
			}
			else{
				dojo.addClass(this.QuickFinish,'HideElement');
			}
			//do subscribes
			dojo.subscribe(this.id+'/SwitchToEditMode',this,'_onSwitchToEditMode');
			dojo.subscribe(this.id+'/switchToStep',this,'_onSwitchToStep');


		},

		start: function(){
			//summary: this function has to be called when all steps are added with publishthe add steps method
			//this function starts the wizard and shows the first step
			//steps inside the _steps Array are processed in there normal order
			this._toggleLoaderOverlay(true);
			this._initialized = true;
			this._activeStep = 0;
			this._initialize();
			//load template of fist step
			this._loadStep(0);
		},

		addStep: function(stepData){
			//summary: add step to wizard with this function is only working before wizard is started
			//example:
			//	|myWizard.addStep({
			//	|		Name            : '{Video}',     - required
			//	|		ViewAction      : 'JSONSnippet', - required
			//	|		TemplateAction  : 'MBO-ViewBookingsystemWizardSteps', - required
			//	|		TemplateName    : 'Content-Video', - required
			//	|		ObjectID        : '#Shop.ID', - required
			//	|		NotInNavigation : true, - optional
			//	|		NoPreload       : true - optional
			//	|		NoButtons       : true, - optional
			//	|		ShowAllStepsOnFinish : true, - optional
			//	|		IsFinishStep    : false - optional
			//	|});
			if(stepData){
				if(this._initialized){
					console.warn(this.id,'unable to add step wizard is already started');
					return;
				}
				//every step is disabled on start
				stepData.state = "Disabled";
				this._steps.push(stepData);
			}
		},

		_preloadSteps:function(){
			//summary: load template of every defined step only loads one step at the same time no multiple simultan loading
			//checks if step is loaded, step is loaded when template is set
			//load next step where template is not defined
			for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){
				var stepData = this._steps[i];
				if(stepData.template == undefined && !stepData.errorOnLoad){
					this._loadStep(i);
					break;
				}
			}
		},

		_loadStep: function(stepNumber){
			//summary: load data of step defined by given stepNumber with async json request
			//when step is loaded call redStepResponse with given data
			//loads given step asynchronous from server
			var stepData = this._steps[stepNumber];
			stepData.TemplateLanguageID = this.currentLanguageId;
			if(epages.vars[this.id+'TemplateObjectID']) {
				stepData.TemplateObjectID = epages.vars[this.id+'TemplateObjectID'];
			}
			if(stepData && stepData.ObjectID) {
				this._jsonHandler.loadAsync(this.url,dojo.hitch(this,function(response){
					this._readStepResponse(response,stepNumber);
				}),stepData);
			} else {
				this._showErrorMessage(this.translate('WizardStepError'),this.translate('WizardStepErrorDesciption'));
			}
		},

		_loadStepSync: function(stepNumber){
			//summary: loads given step synchronous from server
			//is needed when preloading is disabled and next step has to be loaded on next Button click
			//checks if epages.vars[this.id+'TemplateObjectID'] is defined and adds it to request is
			//neccassary if steps are influenced by each other
			var stepData = this._steps[stepNumber];
			stepData.TemplateLanguageID = this.currentLanguageId;
			if(epages.vars[this.id+'TemplateObjectID']) {
				stepData.TemplateObjectID = epages.vars[this.id+'TemplateObjectID'];
			}
			if(stepData && stepData.ObjectID) {
				var response = this._jsonHandler.loadSync(this.url,stepData);
				this._readStepResponse(response,stepNumber);
			}
		},

		_readStepResponse: function(response,stepNumber){
			//summary: read response from server and load next step if preloading is enabled
			var stepData = this._steps[stepNumber];
			//check if step response is okay
			if(response && response.data && response.data.snippet){
				stepData.template = response.data.snippet;

				if(stepNumber == this._activeStep){
					//build step and step navigation if activeStep was loaded, happens on first step
					stepData.state = 'Active';
					this._changeNavigationNodeState(stepNumber,'Active');
					this._buildStep(stepNumber);
				}
			}
			else{
				//set step on error to avoid preload step from loading it again and again
				stepData.errorOnLoad = true;
			}
			if(stepData){
				//is preload is enabled load next step
				if(!stepData.NoPreload){
					this._preloadSteps();
				}
			}
		},

		_buildStep: function(stepNumber){
			//summary: build template of given step and add it to the container
			//step with flag IsFinishStep is added as first element on container for summary mode of this step
			var stepData = this._steps[stepNumber];
			//check if template ist loaded if not load template
			if(stepData.template && stepData.templateNode == undefined){
				//dojo.addClass(this.ContainerNode, "HideElement");
				//create step node and insert loaded template
				var stepNode = document.createElement('div');
				dojo.addClass(stepNode,"Step");
				dojo.addClass(stepNode,"HideElement");
				stepNode.id = stepData.TemplateName;

				stepData.template = stepData.template.replace(/<!--.*-->/g, "");		// remove comments from pagetype
				stepNode.innerHTML = stepData.template;

				//finish step has to be first step in container for design reasons
				if(stepData.IsFinishStep){
					this.ContainerNode.insertBefore(stepNode,this.ContainerNode.firstChild);
				}
				else{
					this.ContainerNode.appendChild(stepNode);
				}
				// no need for extra eval of the script tags on Fx, but on all other browsers
				if(epages.Browser.engine != "Gecko" || (epages.Browser.engine == "Gecko" && epages.Browser.version >= 4)) {
					//evalute script-tags inside content
					var scripts = stepNode.getElementsByTagName('script');
					for( var i=0,iLength=scripts.length ; i<iLength ; i++ ) {
						window.eval(scripts[i].innerHTML);
					}
				}

				//start dojo parser to parse all dojo widgets inside the template
				dojo.parser.parse(stepNode);
				stepData.templateNode = stepNode;
				//dojo.removeClass(this.ContainerNode, "HideElement");
			}
			//show all steps in SummaryMode if FinishStep is shown
			dojo.addClass(this.ContentPlaceHolder,"HideElement");
			// unshow any visible loader overlay
			this._toggleLoaderOverlay(false);
			for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){
				var currentStep = this._steps[i];
				if(stepData.IsFinishStep && (stepData.ShowAllStepsOnFinish === undefined || stepData.ShowAllStepsOnFinish)){
					if(currentStep && currentStep.templateNode && currentStep != stepData){
						dojo.addClass(currentStep.templateNode,'SummaryMode');
						dojo.removeClass(currentStep.templateNode,"HideElement");
					}
				}
				else{
					if(currentStep.templateNode){
						dojo.removeClass(currentStep.templateNode,'SummaryMode');
						dojo.addClass(currentStep.templateNode,"HideElement");
					}
				}
			}
			if(stepData.template && stepData.templateNode){
				dojo.removeClass(stepData.templateNode,"HideElement");
			}
		},

		_closeLastInlineTinyMCE:function(){
			//summary: close last instance of inline tinyMCE
			//Inline tinyMCE is still not working correct
			//TODO: still in progress
			if(epages.vars.currentInlineTinyMCE){
				tinyMCE.execCommand('mceRemoveControl', true,epages.vars.currentInlineTinyMCE);
			}
		},

		_getSaveData:function(stepNumber){
			//summary: this function collects all data from the given step template which has to be send to the server
			//input for saving must have a name attribute like name="ObjectId:attributeAlias:LanguageId"
			//languageId ist optional
			//this function although collects hidden inputs with ChangeActions they must have name="ObjectId:ChangeAction"
			var node;
			if(typeof stepNumber != "undefined"){
				if(!this._steps[stepNumber] && !this._steps[stepNumber].templateNode){
					return;
				}
				node = this._steps[stepNumber].templateNode;

				// possibility to add a hidden input to the step template which tells the wizard NOT to perform a save action for the step
				var doNotSaveOnNextNode = $("DoNotSaveOnNext_" + this._steps[stepNumber].TemplateName);
				if(doNotSaveOnNextNode && doNotSaveOnNextNode.value == "true") {
					return;
				}
			}
			else{
				node = this.ContainerNode;
			}
			//get all named elemnts with name like ObjectId:attributeAlias:LanguageId or ObjectId:attributeAlias
			var allNamedElements = dojo.query("[name*=':']", node);
			if(!this._objects) {
				this._objects = {};
			}
			for( var i=0,iLength=allNamedElements.length ; i<iLength ; i++ ){
				var elm = allNamedElements[i];
				//ignore disabled inputs
				if(elm.disabled && elm.disabled == true){
					continue;
				}
				//special treatment for radio buttons
				if( elm.checked === false && (elm.type.toLowerCase() === 'radio' || dojo.hasClass(elm, 'Radio')) ){
					continue;
				}
				//split name into objectId, atrributeAlias and LanguageID - optional
				if(elm.name){
					var nameValues = elm.name.split(':');
				}
				else if(elm.id){
					var nameValues = elm.id.split(':');
				}
				else{
					return;
				}

				var objectId = nameValues[0];
				if(isNaN(objectId)) {
					// only perform object ids ..
					continue;
				}

				var attributeAlias = nameValues[1];
				var languageId = nameValues[2];
				var languageFieldName = nameValues[3];

				var currentValue = this._objects[objectId] ? this._objects[objectId] : {};
				if(!currentValue.saveNames){
					currentValue.saveNames = [];
				}
				if(!currentValue.saveValues){
					currentValue.saveValues = [];
				}
				if(objectId && attributeAlias){
					// hack for multiple select: if elm is a widget of class type dijit.form.MultiSelect
					if(dijit.registry.byId(elm.id) && $$(elm.id).declaredClass == "dijit.form.MultiSelect") {
						var multiSelectValues = $$(elm.id).attr('value');
						// add all selected values seperately
						if(multiSelectValues && multiSelectValues.length > 0) {
							for( var j=0,jLength=multiSelectValues.length ; j<jLength ; j++ ) {
								currentValue.saveNames.push(attributeAlias);
								currentValue.saveValues.push(multiSelectValues[j]);
							}
						}
					}
					else if(elm.innerHTML && !elm.value){
						currentValue.saveNames.push(attributeAlias);
						currentValue.saveValues.push(elm.innerHTML);
						if(languageId){
							//if object has languages we need other methode to write them
							currentValue.saveNames.push(languageFieldName ? languageFieldName : 'LanguageID');
							currentValue.saveValues.push(languageId);
						}
					}
					else {
						currentValue.saveNames.push(attributeAlias);
						currentValue.saveValues.push(elm.value);
						if(languageId){
							//if object has languages we need other methode to write them
							currentValue.saveNames.push(languageFieldName ? languageFieldName : 'LanguageID');
							currentValue.saveValues.push(languageId);
						}
					}
				}
				this._objects[objectId] = currentValue;
			}
			//get all inputs with name ChangeAction, they must have objectId in name and changeAction name in value
			var allChangeActions = dojo.query("[name='ChangeAction']", node);
			for( var j=0,jLength=allChangeActions.length ; j<jLength ; j++ ){
				var currentAction = allChangeActions[j];
				var splitValues = currentAction.value.split(':');
				if(splitValues.length > 0){
					objectId = splitValues[0];
					var actionName = splitValues[1];
					currentValue = this._objects[objectId] ? this._objects[objectId] : {};
					if(!currentValue.changeActions){
						currentValue.changeActions = [];
					}
					currentValue.changeActions.push(actionName);
				}
				this._objects[objectId] = currentValue;
			}
		},

		saveData:function(){
			//summary: save all data that is inside _objects to the server
			//after successfull save _objects get cleared to allow override of data if user goes back to an already saved step
			//when debugMode is true than saveData sends every object in a own request to the server
			if(!this._objects) {
				return true;
			}
			var result;
			if(!this.debugMode){
				var params = {};
				params['ViewAction'] = 'JSONViewResponse';
				params['ObjectID'] = [];
				params['Value'] = [];
				params['ChangeAction'] = [];
			}
			//add parameters of every object to json request
			for(var key in this._objects){
				if(isNaN(dojo.number.parse(key))) {
					// only valid objectids..
					continue;
				}
				if(this.debugMode){
					var params = {};
					params['ViewAction'] = 'JSONViewResponse';
					params['ObjectID'] = [];
					params['Value'] = [];
					params['ChangeAction'] = [];
				}
				var currentObject = this._objects[key];
				if(!currentObject.saveNames){
					continue;
				}
				for( var j=0,jLength=currentObject.saveNames.length ; j<jLength ; j++ ){
					if(!params[currentObject.saveNames[j]]){
						params[currentObject.saveNames[j]] = [];
					}
					params[currentObject.saveNames[j]].push(currentObject.saveValues[j]);
				}
				//add changeActions for Object
				if(currentObject.changeActions){
					for( var i=0,iLength=currentObject.changeActions.length ; i<iLength ; i++ ){
						params['ObjectID'].push(key);
						params['ChangeAction'].push(currentObject.changeActions[i]);
					}
				}
				else{
					params['ObjectID'].push(key);
					params['ChangeAction'].push(this._defaultChangeAction);
				}
				if(this.debugMode){
					result = this._jsonHandler.loadSync(this.url,params);
				}
			}
			if(!this.debugMode){
				result = this._jsonHandler.loadSync(this.url,params);
			}
			//clear _objects on error to but show error to customer so that he can correct it and save again
			if(result && result.error && result.error.data){
				console.warn("error in wizardcontroller saveData, result=", result);
				this._showErrors(result.error.data.Errors);
				this._objects = undefined;
				return false;
			}
			else{
				//if everything was saved we can clear the saveData object
				if(result && result.data){
					dojo.publish(this.id+'/saveFinished', [ result.data ]);
				}
				else{
					dojo.publish(this.id+'/saveFinished', []);
				}
				this._objects = undefined;
				return true;
			}
		},

		_showErrors:function(errors){
			//summary: show given errors to customer with an error message
			for( var i=0,iLength=errors.length ; i<iLength ; i++ ){
				var currentError = errors[i];
				if(currentError.LoopName && currentError.Index && currentError.Name){
					var errorClass = currentError.LoopName + currentError.Index;
					for( var j=0,jLength=this._steps.length ; j<jLength ; j++ ){
						var stepData = this._steps[j];
						if(stepData.templateNode){
							var errorNodeContainer = dojo.query("."+errorClass, stepData.templateNode);
							if(errorNodeContainer && errorNodeContainer.length == 1){
								errorNodeContainer = errorNodeContainer[0];
								var errorNode = dojo.query("[name*="+currentError.Name+"]", errorNodeContainer);
								if(errorNode && errorNode.length == 1){
									dojo.addClass(errorNode[0],'DialogError');
									if(this._steps[this._activeStep].IsFinishStep){
										dojo.removeClass(stepData.templateNode, "SummaryMode");
										dojo.addClass(stepData.templateNode, "EditMode");
									}
									this._showErrorMessage(this.translate('WizardSaveError'),this.translate('WizardSaveErrorDesciption'));
								}
							}
						}
					}
				}
				else if(currentError.Reason && currentError.Reason == 'FeatureMaxValueReached'){
					var me = this;
					dojo.publish("uimessage/show", [ "", 'The maximum number of services for this website type has been reached.', 'Dialog', {
					titleBar: this._steps[this._activeStep].Name,
					typeClass: 'Warning',
					buttons: [{
						label: '{Close}',
						cssClass: 'Active',
						onclick: function() {
							me._closeWizard();
							this._modalDialogWidget.hide();
						}
					}]
				}
				]);
				}
				else if(currentError.Reason && currentError.Reason == 'OBJECT_EXISTS'){
					dojo.publish("uimessage/show", [ "", this.translate('ServiceNoExists'), 'Dialog', {
						titleBar: this._steps[this._activeStep].Name,
						typeClass: 'Warning'
					}]);
				}
				else if(currentError.Reason && currentError.Message){
					dojo.publish("uimessage/show", [ "", currentError.Message, 'Dialog', {
						titleBar: this._steps[this._activeStep].Name,
						typeClass: 'Warning'
					}]);
				}
				else if(currentError.Name){
					for( var j=0,jLength=this._steps.length ; j<jLength ; j++ ){
						var stepData = this._steps[j];
						if(stepData.templateNode){
								var errorNode = dojo.query("[name*="+currentError.Name+"]", stepData.templateNode);
								if(errorNode && errorNode.length == 1){
									dojo.addClass(errorNode[0],'DialogError');
									if(this._steps[this._activeStep].IsFinishStep){
										dojo.removeClass(stepData.templateNode, "SummaryMode");
										dojo.addClass(stepData.templateNode, "EditMode");
									}
								}
							}
						}
				}
			}
			// remove any loader overlays
			this._toggleLoaderOverlay(false);
		},

		activateStep: function(nextStepNumber){
			//summary: activate given step
			//change to next step is only possible if next step is already loaded
			var nextStepData = this._steps[nextStepNumber];
			if(nextStepData){
				//check if next step is loaded, if not load it sync to avoid error while user have to wait
				if(!nextStepData.template){
					this._loadStepSync(nextStepNumber);
				}
				//update stepNavigation
				this._changeNavigationNodeState(this._activeStep,'Done');
				this._changeNavigationNodeState(nextStepNumber,'Active');
				nextStepData.state = 'Active';
				this._activeStep = nextStepNumber;
				//check if there is a step before the step we now want to activeate
				//disable all buttons if NoButtons flag is set used for last step
				if(nextStepData.NoButtons){
					dojo.addClass(this.ButtonBarNode,'HideElement');
					dojo.addClass(this.StepNavigationNode,'HideElement');
					dojo.addClass(this.QuickFinish,'HideElement');
				}
				else{
					dojo.removeClass(this.ButtonBarNode,'HideElement');
					dojo.removeClass(this.StepNavigationNode,'HideElement');
					if(this.showQuickFinish){
						dojo.removeClass(this.QuickFinish,'HideElement');
					}
				}
				//on IsFinishStep we need the save button not the next button
				if(nextStepData.IsFinishStep){
					this.NextButton.hide();
					this.SaveButton.show();
					dojo.addClass(this.QuickFinish,'HideElement');
				}
				else{
					this.NextButton.show();
					this.SaveButton.hide();
					if(this.showQuickFinish){
						dojo.removeClass(this.QuickFinish,'HideElement');
					}
				}
				//hide BackButton if next step is first step
				if(nextStepNumber == 0){
					this.BackButton.hide();
				}
				else{
					this.BackButton.show();
				}

				var stepdata = this._steps[this._activeStep];
				var templateName= stepdata['TemplateName'];

				//start building next step
				this._buildStep(nextStepNumber);

				// publish step message by templateName
				dojo.publish(this.id+'/stepActivated/'+templateName, []);

				//publish general step change message
				dojo.publish(this.id+'/activateStep', [ {
						'stepNumber' : this._activeStep,
						'stepData' : this._steps[this._activeStep]
				}]);

				if(epages.Browser.engine == "MSIE") {
					var domNode = this.domNode;
					dojo.removeClass(domNode, "WizardController");
					window.setTimeout(function() {
						dojo.addClass(domNode, "WizardController");
					}, 1);
				}

			}
			else{
				//show error to user if we had problems
				this._showErrorMessage(this.translate('WizardStepError'),this.translate('WizardStepErrorDesciption'));
			}
		},

		_calculateRestrictorOverlay : function(){
			var suspendPosition = new epages.html.Element(this.ContainerNode).getAbsolutePosition(dojo.body());
			var aw  = dojo.style(this.ContainerNode,"marginLeft");
					aw += dojo.style(this.ContainerNode,"paddingLeft");
			var l = suspendPosition.x - aw;
					aw += dojo.style(this.ContainerNode,"marginRight");
					aw += dojo.style(this.ContainerNode,"paddingRight");
			var w = this.ContainerNode.offsetWidth + aw;

			var ah = dojo.style(this.ContainerNode,"marginTop");
					ah += dojo.style(this.ContainerNode,"paddingTop");
			var t = suspendPosition.y - ah;
					ah += dojo.style(this.ContainerNode,"marginBottom");
					ah += dojo.style(this.ContainerNode,"paddingBottom");
			var h = this.ContainerNode.offsetHeight + ah;

			return {
				Width  : w,
				Height : h,
				Left   : l,
				Top    : t
			};
		},
		_toggleLoaderOverlay : function(/*boolean*/toggleState){
			if(toggleState){
				dojo.publish("interactionRestrictor/suspend", ["ContainerNodeLoading", this.ContainerNode,false,this._calculateRestrictorOverlay()]);
			} else {
				dojo.publish("interactionRestrictor/permit", ["ContainerNodeLoading"]);
			}
		},
		_onNextButtonClick: function(){
			//summary: got to next step and save if saveOnNext is defined
			dojo.publish(this.id+'/nextButtonClick', []);
			this._toggleLoaderOverlay(true);
			this._closeLastInlineTinyMCE();
			if(this.saveOnNext){
			this._getSaveData(this._activeStep);
				if(!this.saveData()) {
					return;
				}
			}
			this.activateStep(this._activeStep + 1);
		},

		_onBackButtonClick: function(){
			//summary: go to prevoius step
			this._toggleLoaderOverlay(true);
			this.activateStep(this._activeStep - 1);
		},

		_onSaveButtonClick:function(){
			//summary: collect save data and send it to the server
			//go to last step this is always the quickStart step
			this._closeLastInlineTinyMCE();
			if(this.saveOnNext) {
				this._getSaveData(this._activeStep);
			} else {
				this._getSaveData();
			}
			if(this.saveData()){
				var stepdata = this._steps[this._activeStep];
				if(this.finishRedirectURL && stepdata.IsFinishStep) {
					epages.locationHref(this.finishRedirectURL);
				} else {
					this.activateStep(this._steps.length - 1);
				}
			}
		},
		_onQuickFinishClick:function(){
			//summary: save data and go to last step
			this._toggleLoaderOverlay(true);
			this._closeLastInlineTinyMCE();
			this._getSaveData();
			if(this.saveData()){
				this.activateStep(this._steps.length - 1);
			}
		},

		_activateNextButton: function(){
			//summary: activate the next Button
			dojo.addClass(this.NextButton, 'Active');
		},

		_disableNextButton: function(){
			//summary: disable the next Button
			dojo.addClass(this.NextButton, 'Disabled');
		},

		_closeWizard:function(){
			//summary: activates the last step without saving necessary for errors
			location.href = epages.vars.BaseUrl;
		},

		_changeNavigationNodeState: function(stepNumber,state){
			//summary: change states of nextNavigationNodes
			//only steps with state done can be clicked
			var stepNavigationNode;
			for( var j=0,jLength=this._stepNavigation.length ; j<jLength ; j++ ){
				var currentNode = this._stepNavigation[j];
				if(stepNumber == currentNode.stepNumber){
					stepNavigationNode = currentNode;
				}
			}
			//change stepNavigationNode to active and remove all other states on this step only no multiple states possible
			if(stepNavigationNode){
				for( var i=0,iLength=this._stepStates.length ; i<iLength ; i++ ){
					var currentState = this._stepStates[i];
					if(state == currentState){
						dojo.addClass(stepNavigationNode.node,currentState);
						dojo.addClass(stepNavigationNode.bubbleNode,currentState);
					}
					else{
						dojo.removeClass(stepNavigationNode.node,currentState);
						dojo.removeClass(stepNavigationNode.bubbleNode,currentState);
					}
				}
			}
		},

		checkChanges:function(){
			//TODO: diese funktion soll überprüfen, ob es noch ungespeicherte Änderungen gibt und bei Bedarf warnen
			/*this._getSaveData();
			console.debug('check changes',this._objects);
			var unsavedData = false;
			for(var key in this._objects){
				if(this._objects[key]){
					unsavedData = true;
					break;
				}
			}
			if(unsavedData){
				return true;
			}
			else{
				return false;
			}*/
			return false;
		},

		_initialize: function(){
			//summary:make necessary first values to start wizard
			//show step jump list
			//register on onbeforeunload
			epages.onUnloadFunctions.push(dojo.hitch(this,function() {
				return this.checkChanges();
			}));
			this._buildStepNavigation();
			this.BackButton.hide();
			this.SaveButton.hide();
		},

		_buildStepNavigation: function(){
			//summary: build step navigation and stepNavigation Bubble
			this.BubbleContentNode.innerHTML='<div class="Headline">'+this.controllerName+'</div>';

			var visibleStepNumber = 1;
			for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){
				var stepData = this._steps[i];
				if(stepData.NotInNavigation){
					continue;
				}

				// create step node
				var stepNode = document.createElement('a');
				stepNode.innerHTML = visibleStepNumber;
				dojo.addClass(stepNode, "Step");
				dojo.addClass(stepNode, stepData.state);
				this.connect(stepNode,'onclick', '_onStepNumberClick');
				this.connect(stepNode,'onmouseover', '_onStepNumberHover');
				this.StepNavigationNode.appendChild(stepNode);

				// create step node in bubble
				var bubbleNode = document.createElement('div');
				bubbleNode.innerHTML = visibleStepNumber+'. '+stepData.Name;
				dojo.addClass(bubbleNode, stepData.state);
				dojo.addClass(bubbleNode, "Step");
				this.connect(bubbleNode,'onclick', '_onStepNumberClick');
				this.BubbleContentNode.appendChild(bubbleNode);

				// register nodes
				var stepNavigationNode = {
					node : stepNode,
					bubbleNode : bubbleNode,
					stepNumber : i
				};
				this._stepNavigation.push(stepNavigationNode);

				visibleStepNumber++;
			}

			// fill in bubble
			this.StepNavigationBubble.setupContent({
				content: this.BubbleContentNode,
				orientation : 'top-right'
			});
			// show bubble
			dojo.removeClass(this.BubbleContentNode,'HideElement');
		},

		_onStepNumberClick: function(evt){
			//summary: change to clicked step
			currentNode = evt.currentTarget;
			for( var i=0,iLength=this._stepNavigation.length ; i<iLength ; i++ ){
				var stepNavigationNode = this._stepNavigation[i];
				if(currentNode == stepNavigationNode.node ||currentNode == stepNavigationNode.bubbleNode){
					var stepData = this._steps[stepNavigationNode.stepNumber];
					if(stepData.state != 'Disabled'){
						this._toggleLoaderOverlay(true);
						this.activateStep(stepNavigationNode.stepNumber);
					}
				}
			}
		},

		_onStepNumberHover: function(evt){
			//summary: show stepBubble on hover of stepNumbers
			var currentNode = evt.currentTarget;
			var absPos = $E(currentNode).getRelativePosition();
			this.StepNavigationBubble.setupContent({
				x           : absPos.x - 15,
				y           : absPos.y + 20,
				orientation : 'top-right'
			});
			this.StepNavigationBubble.show();
		},

		_hideStepNavigationBubble: function(evt){
			//summary: hide step navigation bubble
			var _this = this;
			window.clearTimeout(this._hideBubbleTimeout);
			this._hideBubbleTimeout = window.setTimeout(function() {
				_this.StepNavigationBubble.hide();
			}, this.HIDEBUBBLE_TIMEOUT);
		},

		_dontHideStepNavigationBubble: function(evt){
			//summary: clear hide bubble
			window.clearTimeout(this._hideBubbleTimeout);
		},

		_showErrorMessage: function(messageTitle,messageText){
			//summary: show given error message
			dojo.publish("uimessage/show", [messageTitle, messageText, 'Dialog',{
				titleBar: this._steps[this._activeStep].Name,
				typeClass: 'Warning'
			}]);
		},

		//Eventhandling for changes and updates to Previews
		_onDomNodeEvent:function(evt){
			//summary: collect all events that happen on the domNode of this widget to update preview nodes if input nodes were changed
			if(evt.target.nodeName == "INPUT" || evt.target.nodeName == "SELECT" || evt.target.nodeName == "TEXTAREA") {
				var sourceNode = evt.target;
				var epUpdateName = (sourceNode.getAttribute('ep_updatename')) ?  sourceNode.getAttribute('ep_updatename') : sourceNode.name;
				// update known elements
				var updateNodes = dojo.query("[ep_updatesource="+epUpdateName+"]", this.ContainerNode);
				var updateValue = sourceNode.value;

				if(sourceNode.nodeName == "SELECT") {
					updateValue = sourceNode[sourceNode.selectedIndex].innerHTML;
				}
				else if(sourceNode.type == "radio" || sourceNode.className.match("Radio")) {
					var aRadioLabel = dojo.query('[for='+sourceNode.id+']', sourceNode.parentNode.parentNode);
					if(aRadioLabel[0]) {
						updateValue = aRadioLabel[0].innerHTML;
					}
				}
				for( var i=0,iLength=updateNodes.length ; i<iLength ; i++ ){
					var currentNode = updateNodes[i];
					var updateTask = currentNode.getAttribute("ep_updatetask");
					var emptyDefault = currentNode.getAttribute("ep_emptyDefault");
					if(updateValue == "" && emptyDefault) {
						updateValue = emptyDefault;
					}
					this._updatePreview(currentNode, updateTask, updateValue);
				}
			}
		},

		_updatePreview: function(/* dom node*/updateNode, /* string */ updateTask, /* string */ updateValue ) {
			//summary: insert new value to preview dom node
			if(!updateTask){
				return;
			}
			if(updateTask.match("setHTML")) {
				if(updateValue == "") {
					updateValue= "&nbsp;";    // avoid empty tags which are not displayed (e.g. business hours table)
				}
				if(updateNode.innerHTML == updateValue) {
					return;
				}
				updateNode.innerHTML = updateValue;
			}

			if(updateTask.match("setText")) {
				updateValue = epages.string.escapeXml(updateValue);

				if(updateNode.innerHTML == updateValue) {
					return;
				}
				updateNode.innerHTML = updateValue;
			}

			if(updateTask.match("setValue")) {
				if(updateNode.value == updateValue) {
					return;
				}
				updateNode.value = updateValue;
			}

			if(updateTask.match("emphasize")) {
				updateNode.style.fontWeight = "bold";
			}
		},

		_onSwitchToEditMode: function(templateName){
			//summary: switch given step to editmode find step with given templateName
			if(!templateName){
				return;
			}
			for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){
				var currentStep = this._steps[i];
				if(currentStep.TemplateName == templateName){
					dojo.addClass(currentStep.templateNode, "EditMode");
					dojo.removeClass(currentStep.templateNode, "SummaryMode");
					break;
				}
			}
		},

		_onSwitchToStep: function(templateName) {
			// summary: message function
			var foundTemplate = false;
			for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){
				var currentStep = this._steps[i];
				if(currentStep.TemplateName == templateName){
					this._toggleLoaderOverlay(true);
					this.activateStep(i);
					foundTemplate= true;
					break;
				}
			}
			if(!foundTemplate) {
				console.warn('Template '+templateName+' not found in _onSwitchToStep() / '+this.declaredClass);
			}
		},

		_onCancel : function() {
			// summary: event function - redirect to cancel page
			if(this.cancelRedirectURL != "") {
				epages.locationHref(this.cancelRedirectURL );
			}
		}
	}
);