
var Widget = require('./widget');
var Step = require('./step');
var Toast = require('./toast');

/**
 * A simple assistant with steps.
 */
module.exports = new Class({
	Extends: Widget,
	Tag: 'htk-assistant',
	Properties: {
		/**
		 * The current step index.
		 */
		step: {
			type: Number,
			set: function(x) {
				this.setStep(x);
			},
			get: function() {
				return this._stepIndex;
			}
		},
		/**
		 * The current step name.
		 */
		stepName: {
			type: String,
			set: function(x) {
				this.setStepByName(x);
			},
			get: function() {
				return this._stepName;
			}
		},
		/**
		 * The steps index.
		 */
		stepsIndex: {
			type: Array,
			set: function(x) {
				this._stepsIndex = x;
				this.setStep(this._stepIndex);
				this.signalEmit('steps-change');
			},
			get: function() {
				return this._stepsIndex;
			}
		},
		/**
		 * The total number of steps in the assistant.
		 */
		stepCount: {
			type: Number,
			get: function() {
				if (this._stepsIndex)
					return this._stepsIndex.length;
				return 0;
			}
		},
		/**
		 * Function to call on every step change.
		 */
		stepFunc: {
			type: Function,
			value: null
		},
		/**
		 * Function to call on every step change.
		 */
		endFunc: {
			type: Function,
			value: null
		},
	},

	_stepNode: null,
	_stepIndex: 0,
	_stepName: null,
	steps: {},

	initialize: function(props) {
		var node = this.createRoot('div');
		node.className = 'htk-assistant';
		this.parent(props);
	},

	appendChild: function(step) {
		if (!(step instanceof Step))
			throw new Error('Invalid child for assistant');

		this.node.appendChild(step.node);
		this.steps[step.name] = step;
	},

	setStepByName: function(stepName) {
		if (this._stepsIndex)
			this.setStep(this._stepsIndex.indexOf(stepName));
	},

	setStep: function(stepIndex) {
		if ((this.currentStep && stepIndex == this._stepIndex)
		|| !this._stepsIndex
		|| !(stepIndex >= -1 && stepIndex < this._stepsIndex.length))
			return;

		if (stepIndex > this._stepIndex) {
			var validateIni = Math.max(this._stepIndex, 0);

			try {
				for (var i = validateIni; i < stepIndex; i++) {
					var validateName = this._stepsIndex[i];
					var validateStep = this.steps[validateName];
					validateStep.validate();
				}
			} catch(e) {
				Toast.showError(e.message);
				if (i == this._stepIndex) return;
				stepIndex = i;
			}
		}

		var stepName = this._stepsIndex[stepIndex];
		var step = this.steps[stepName];
		var currentStep = this.currentStep;

		if (currentStep)
			currentStep.hide();

		this._stepIndex = stepIndex;
		this._stepName = stepName;
		this.currentStep = step;
		step.show();
		this.signalEmit('step-change', stepIndex);
		
		if (this.stepFunc)
			this.stepFunc(step);
	},

	/**
	 * Moves the assistant to the previous step.
	 */
	movePrevious: function() {
		this.setStep(this._stepIndex - 1);
	},
	
	/**
	 * Moves the assistant to the next step.
	 */
	moveNext: function() {
		this.setStep(this._stepIndex + 1);
	},

	/**
	 * Ends the assistant. If defined, the stepFunc will be called.
	 */
	end: function() {
		if (this.endFunc)
			this.endFunc();
	}
});
