ax_forms = {};
lang.form = {
	'es':{'load':"Cargando datos...",
		   'submit':"Mandando datos..."
		  },
	'en':{'load':"Loading data...",
		  'submit':"Submitting data..."
		  }
};

AxForm = Class.create();
AxForm.prototype = {
	
	initialize: function(id, options) {
		
		if (id) {
			this.id = id;	
			this.self = $(this.id);
			
			this.validators = {};
			this.media_inputs = {};
			this.options = options || {};
			this.reset_form = (this.options.reset_form != undefined) ? this.options.reset_form : true;
			this.curStep = 0;
			
			if (this.options.updater) {
				this.updater = updaters[this.options.updater];	
			}
			
			if (this.options.steps) {
				this.setUpSteps();	
			}
			
			this.state = this.options.state || 'closed';
			
			this.registry = [];
			
			var me = this;
			page_init.scripts['axform_'+this.id] = function() {
				if (screen_overlay.register && !me.options.no_hide) screen_overlay.register(me);
			};
			
			if (btns) {
				this.btn = {};
				this.btn.save = btns[this.id + "_save"];
				this.btn.reset = btns[this.id + "_reset"];
				this.btn.cancel = btns[this.id + "_cancel"];
				if (this.options.steps) {
					this.btn.prev = btns[this.id + "_prev"];
					if (this.btn.prev) Element.hide(this.btn.prev.id);
					this.btn.next = btns[this.id + "_next"];
					if (this.btn.save) Element.hide(this.btn.save.id);
					if (this.options.disable_next) this.btn.next.disable();
				}
			}
			
			this._injectBehaviours();
			
		}
		
	},
	
	/** PUBLIC METHODS **/
	
	setUpSteps: function() {
		this.steps = [];
		this.skip_steps = [];
		for(var i=1; i<=this.options.steps; i++) {
			var ob = {};
			ob.element = $(this.id+'_step'+i);
			ob.label = $(this.id+'_step'+i+'_label');
			if (ob.element) {
				this.steps.push(ob);	
			}
		}
		this.cur_step = 0;
	},
	
	loadData: function(cmd, id, updater) {
		
		var callParams = [];
		callParams.push('item=' + id);
		
		var u = (updater) ? updaters[updater] : this.updater;
		if (u) {
			u.run(callParams, cmd, lang.form[cur_lang].load);
			this.clearForm();
			this.show();
		}
		
	},
	
	attemptSubmit: function(no_return, cmd) {
		//if (console) console.log('attempting submit: ' + this.self.id + ' step complete: ' + this._isStepComplete());
		if (this.options.service)  {
			this.submitToService(this.options.service);
		} else {
			if (this._isStepComplete()) {
				
				if (!this.options.no_submit) {
					var orig = this._encryptForm();
					if (this.updater) {
						var args = [];
						ApexUtil.extractForm(this.self, args);
						this.revertForm(orig);
						
						var c = (cmd) ? cmd : this.options.cmd;
						this.updater.run(args, c, lang.form[cur_lang].submit);
						//this.self.elements[0].0focus();
						
						if (this.reset_form) this.clearForm();
						
						if (this.options.disable_on_submit) this.btn.save.disable();
					} else {
						this.self.submit();
					}
				}
				this.onSubmitForm();
			}
			
			if (!no_return) {
				return false;
			}
		}
	},
	
	submitToService: function(serv) {
		if (this._isStepComplete()) {
			if (!this.options.no_submit) {
				var orig = this._encryptForm();
				
				var args = [];
				ApexUtil.extractForm(this.self, args);
				this.revertForm(orig);
				
				if (this.reset_form) this.clearForm();
				if (this.options.disable_on_submit) this.btn.save.disable();
				
				this.updater.callService(serv, args, lang.form[cur_lang].submit);
			}
			this.onSubmitForm();
		}
	},
	
	onSubmitForm: function() {},
	
	show: function(use_visibility) {
		if (use_visibility) {
			this.self.style.visibility = '';
		} else {
			if (this.state != 'open') {
				var effect = new Effect.BlindDown(this.self,
												   {duration: 0.5});
				this.state = 'open';
			}
			//this.self.style.display = '';
		}
		if (this.options.disable_on_submit) this.btn.save.enable();
	},
	
	hide: function(use_visibility) {
		if (!this.options.no_collapse) {
			if (use_visibility) {
				this.self.style.visibility = 'hidden';
			} else {
				if (this.state != 'closed') {
					var effect = new Effect.BlindUp(this.self,
													{duration: 0.5});
					this.state = 'closed';
				}
				//this.self.style.display = 'none';	
			}
		}
	},
	
	clearForm: function() {
		// if (console) console.log('Clear Form called!!!');
		
		this.self.reset();
		for(var name in this.media_inputs) {
			var ob  = this.media_inputs[name];
			if (ob) {
				if (ob.label) ob.label.innerHTML = ob.starting_label;	
				if (ob.input) ob.input.value = '';
			}
		}

		var inputs = this.self.getElementsByTagName('input');
		if (inputs.length) {
			for(var i=0; i<inputs.length; ++i) {				
				if (inputs[i].type == 'hidden' && !inputs[i].getAttribute('constant')) {					
					inputs[i].value = '';	
				}
			}
		}
		
		if ($('to_box')) {
			// if (console) console.log('CLEARING SELECTOR:'+$('to_box'));
			ApexUtil.selectAll('to_box');
			ApexUtil.selectBoxMove('to_box', 'from_box');
		}
		
		if (this.options.text_editor) text_editors[this.options.text_editor+'_textEditor'].setContent('<p>&nbsp;</p>');
		
		
		
		if (this.options.steps) {
			this.gotoStep(0);	
		}
		
		
		
		
		this.dispatchEvent('onClearForm');
		this.onClearForm();		
		
		if (this.options.disable_on_submit) this.btn.save.enable();
		
		//if (this.self.elements[0]) this.self.elements[0].focus();
		
		this._clearValidators();
		
	},
	
	_clearValidators: function(step) {
		if (!step) step = this.curStep;
		
		if (this.options.validate_all) {
			var group = [];
			for(var i in this.validators) {
				for(var j in this.validators[i]) {
					group.push(this.validators[i][j]);
				}
			}
		} else {
			var group = this.validators['step' + step];
		}
		
		
		if (group && group.length) {
			for(var i=0; i<group.length; ++i) {
				var v = group[i];
				group[i].changeState(false);
			}
		}
	},
	
	onClearForm: function() {},
	onValidate: function() { return true; },
	
	cancelForm: function() {
		this.clearForm();
		this.hide();
	},
	
	revertForm: function(orig) {
		for(var i=0; i<orig.length; ++i) {
			var ob = orig[i];
			ob.self.value = ob.val;
		}
	},
	
	disableGroup: function(step) {
		var group = this.validators['step' + step];
		for(var i=0; i<group.length; ++i) {
			group[i].setActive(false);	
		}	
	},
	
	enableGroup: function(step) {
		var group = this.validators['step' + step];
		for(var i=0; i<group.length; ++i) {
			group[i].setActive(true);	
		}
	},
	
	getMediaFile: function(target, type, folder) {
		this.cur_media_target = target;
		mediaBrowser.open(this, null, type, folder);	
	},
	
	mediaInsert: function(res) {
		if (this.cur_media_target) {
			var parts = res.split('|');
			var target = this.media_inputs[this.cur_media_target];

			target.label.innerHTML = parts[1];
			target.input.value = parts[0];
		}
		this.cur_media_target = null;
	},
	
	register: function(ob) {
		this.registry.push(ob);	
	},
	
	dispatchEvent: function(method, args) {
		for(var i=0; i<this.registry.length; i++) {
			if (this.registry[i][method]) {
				this.registry[i][method].apply(this.registry[i], args);	
			}
		}
	},
	
	nextStep: function() {
		var load_step = true;
		if (this.options.validate_steps) {
			load_step = this.validateStep(this.cur_step);
		}
		
		if (this.cur_step < this.steps.length-1 && load_step) {
			this.gotoStep(this.getNextAvailableStep(1));
			this.onNextStep();
		}
	},
	
	onNextStep: function() {},
	
	prevStep: function() {
		if (this.cur_step > 0) {
			this.gotoStep(this.getNextAvailableStep(-1));
			this.onPrevStep();
		}
	},
	
	onPrevStep: function() {},
	
	getNextAvailableStep: function(dir) {
		var step = this.cur_step;
		do {
			step += dir;
		} while(this.skip_steps.inArray(step) != -1);
		
		return step;
	},
	
	displayButtons: function() {
		if (this.btn.prev) {
			if (this.cur_step > 0) {
				Element.show(this.btn.prev.id);	
			} else {
				Element.hide(this.btn.prev.id);	
			}
		}
		if (this.cur_step == this.options.steps-1) {
			Element.hide(this.btn.next.id);
			Element.show(this.btn.save.id);	
		} else {
			Element.hide(this.btn.save.id);
			Element.show(this.btn.next.id);
		}
	},
	
	skipStep: function(step, state) {
		var index = this.skip_steps.inArray(step);
		if (state) {
			if (index == -1) {
				this.skip_steps.push(step);
			}
		} else {
			if (index != -1) {
				this.skip_steps.splice(index, 1);
			}
		}
		// if (console) console.log('SKIP STEPS: '+this.skip_steps);
	},
		
	gotoStep: function(step) {
	
		if (!this.options.no_step_hide) this.hideStep(this.steps[this.cur_step]);
		this.cur_step = step;
		this.displayButtons();
		this.showStep(this.steps[this.cur_step]);
		this.onLoadStep(step);
		
	},
	
	onLoadStep: function(step) {},
	
	showStep: function(step) {
		if ($(step.element.id)) {
			Element.show(step.element.id);
			if (step.label) Element.addClassName(step.label.id, 'on');
		}
	},
	
	hideStep: function(step) {
		Element.hide(step.element.id);
		if (step.label) Element.removeClassName(step.label.id, 'on');	
	},
	
	validateStep: function(step) {
		if (console) console.log('VALIDATING STEP: '+step);
		if (this.onValidateStep(step)) return this._isStepComplete(step);
	},
	
	onValidateStep: function(step) { return true; },
	
	/** PRIVATE METHODS **/
	
	_injectBehaviours: function() {
		//// if (console) console.log(this.options.use_return);
		if (this.options.use_return && this.self) {
			this.self.onkeyup = this._keyupHandler.bindAsEventListener(this);
		}
		
		if (this.btn.save) {
			this.btn.save.setAction(this.attemptSubmit.bind(this));	
		}
		
		if (this.btn.reset) {
			this.btn.reset.setAction(this.clearForm.bind(this));	
		}
		
		if (this.btn.cancel) {
			this.btn.cancel.setAction(this.cancelForm.bind(this));	
		}
		
		if (this.btn.prev) {
			this.btn.prev.setAction(this.prevStep.bind(this));	
		}
		
		if (this.btn.next) {
			this.btn.next.setAction(this.nextStep.bind(this));	
		}
		
		this._parseFormElements();
	},	
	
	_parseFormElements: function() {
		// if (console) console.log('IN FORM: '+this.id + ' self: ' + this.self);
		this.validators = {};
		var elmts = this.self.elements;
		for(var i=0; i<elmts.length; i++) {
			var e = elmts[i];
			if (e.getAttribute('validator')) {
				var validator = (elmts[i].getAttribute('validator')).split(':');
				var group = 'step' + validator.shift();
				var id = e.id;
				var type = validator.shift();
				// if (console) console.log('Validator Found : ' + group + ' : ' + id + ': ' + type + " : ARGS : " + validator);
				
				if (!this.validators[group]) {
					this.validators[group] = [];	
				}
				// if (console) console.log('Validator for group: '+group);
				var args = {app:this.app, type:type, args:validator};
				if (this.options.no_blur_validate) args.no_blur = true;
				this.validators[group].push(new Validator(this, id, args));
			}
			// if (console) console.log(this.validators);
		}
		
		var divs = this.self.getElementsByTagName('div');
		for(var i=0; i<divs.length; i++) {
			var e = divs[i];
			if (e.getAttribute('media')) {
				var id = e.id;
				var temp = {};
				temp.label = $(id + '_label');
				temp.input = $(id + '_input');
				temp.starting_label = temp.label.innerHTML;
				this.media_inputs[id] = temp;
			}
			
		}
	},
	
	_keyupHandler: function(e) {
		if (e.keyCode == 13) {
			this.attemptSubmit(true);
		}
	},
	
	_encryptForm: function() {
		// if (console) console.log('USING KEY: '+this.options.key);
		var elmts = this.self.elements;
		var original = [];
		for(var i=0; i<elmts.length; i++) {
			var e = elmts[i];
			if (e.getAttribute('encrypt') && e.value) {
				var ob = {self:e, val:e.value};
				original.push(ob);
				var res = encodeStr(this.options.key, e.value);
				e.value = res.join('|');
			}
		}
		return original;
	},
	
	_isStepComplete: function(step) {
		if (!step) step = this.curStep;
		
		if (this.options.validate_all) {
			var group = [];
			for(var i in this.validators) {
				for(var j in this.validators[i]) {
					group.push(this.validators[i][j]);
				}
			}
		} else {
			var group = this.validators['step' + step];
		}
		
		var res = true;
		if (group && group.length) {
			for(var i=0; i<group.length; ++i) {
				var v = group[i];
				//if (console) console.log(v.self.id + ' = ' + v.args);
				if (v.args.indexOf('optional') != -1) {
					continue;	
				}
				if (v.type != 'cmd') {
					v.blurHandler();	
				} 
				
				if (!v.status || !v.self.value) {
					//if (console) console.log(v.self.id + ' = ' + v.self.value);
					res = false;
				}
			}
		}


		if (res) {
			res = this.onValidate();
		}
		
		return res;
	}
};
