Ext.ns('Nexts.form', 'Nexts.form.Action');

/**
 * @class Nexts.form.Action.Subload
 * @extends Ext.form.Action
 * A class which handles submission of data from {@link Ext.form.BasicForm Form}s
 * and processes the returned response.
 * <br><br>
 * Instances of this class are only created by a {@link Ext.form.BasicForm Form} when
 * submitting.
 * <br><br>
 * A response packet must contain a boolean <tt style="font-weight:bold">success</tt> property, and, optionally
 * an <tt style="font-weight:bold">errors</tt> property. The <tt style="font-weight:bold">errors</tt> property contains error
 * messages for invalid fields.
 * <br><br>
 * By default, response packets are assumed to be JSON, so a typical response
 * packet may look like this:
 * <br><br><pre><code>
{
	success: false,
	actionErrors: [ "error message 1", "error message 2" ],
	actionWarnings: [ "warning message1" , "warning message2" ],
	actionMessages: [ "message1" , "message2" ],
	fieldErrors: {
		"username": [ "field message 1", "field message 2" ],
		"password": [ "field message 1", "field message 2" ]
	},
	data: {
		username: "Fred. Olsen Lines",
		password: "FXT"
	}
}</code></pre>
 * <br><br>
 * Other data may be placed into the response for processing the the {@link Ext.form.BasicForm}'s callback
 * or event handler methods. The object decoded from this JSON is available in the {@link #result} property.
 */
Nexts.form.Action.Subload = function(form, options){
	Nexts.form.Action.Subload.superclass.constructor.call(this, form, options);
};

Ext.extend(Nexts.form.Action.Subload, Ext.form.Action, {
	/**
	* @cfg {boolean} clientValidation Determines whether a Form's fields are validated
	* in a final call to {@link Ext.form.BasicForm#isValid isValid} prior to submission.
	* Pass <tt>false</tt> in the Form's submit options to prevent this. If not defined, pre-submission field validation
	* is performed.
	*/
	type: 'subload',

	// private
	run: function() {
		var o = this.options;
		var method = this.getMethod();
		var isGet = method == 'GET';
		if (o.clientValidation === false || this.form.isValid()) {
			Ext.Ajax.request(Ext.apply(this.createCallback(o), {
				form:this.form.el.dom,
				url:this.getUrl(isGet),
				method: method,
				headers: o.headers,
				params:!isGet ? this.getParams() : null,
				isUpload: this.form.fileUpload
			}));
		}
		else if (o.clientValidation !== false) { // client validation failed
			this.failureType = Ext.form.Action.CLIENT_INVALID;
			this.form.afterAction(this, false);
		}
	},

	// private
	success: function(response) {
		var result;
		try {
			result = this.processResponse(response);
		}
		catch (e) {
			console.error(e);
		}
		
		if (result === true || !result) {
			this.form.afterAction(this, false);
			return;
		}
		
		if (result.data) {
			this.form.clearInvalid();
			this.form.setValues(result.data);
		}
		if (result.success) {
			this.form.afterAction(this, true);
			return;
		}
		if (result.fieldErrors) {
			var fes = {};
			for (var f in result.fieldErrors) {
				var msg = result.fieldErrors[f];
				if (Ext.isArray(msg)) {
					msg = msg.join('<br/>');
				}
				fes[f] = msg;
			}
			this.form.markInvalid(fes);
		}
		this.failureType = Ext.form.Action.SERVER_INVALID;
		this.form.afterAction(this, false);
	},

	// private
	handleResponse: function(response) {
		if (this.form.handleResponse) {
			return this.form.handleResponse(response, this);
		}

		var ohr;
		
		if (this.form.errorReader) {
			var rs = this.form.errorReader.read(response);
			var fieldErrors = {};
			var actionErrors = [];
			var actionWarnings = [];
			var actionMessages = [];
			
			if (rs.records) {
				for (var i = 0, len = rs.records.length; i < len; i++) {
					var r = rs.records[i];
					switch (r.data.type) {
					case "fieldError":
						if (fieldErrors[r.data.id]) {
							fieldErrors[r.data.id].push(r.data.msg);
						}
						else {
							fieldErrors[r.data.id] = [ r.data.msg ];
						}
						break;
					case "actionError":
						actionErrors.push(r.data.msg);
						break;
					case "actionWarning":
						actionWarnings.push(r.data.msg);
						break;
					case "actionMessage":
						actionMessages.push(r.data.msg);
						break;
					}
				}
			}
			ohr = {
				success: rs.success,
				fieldErrors: fieldErrors,
				actionErrors: actionErrors,
				actionWarnings: actionWarnings,
				actionMessages: actionMessages
			};
		}
		if (this.form.reader) {
			var rs = this.form.reader.read(response);
			var data = rs.records && rs.records[0] ? rs.records[0].data : null;
			if (ohr) {
				ohr.data = data;
			}
			else {
				ohr = {
					success : rs.success,
					data : data
				};
			}
		}

		if (!ohr) {
			ohr = Ext.decode(response.responseText);
		}

		return ohr;
	}
});

Ext.form.Action.ACTION_TYPES.subload = Nexts.form.Action.Subload;

/**
 * Shortcut to do a submit action.
 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
 * @return {BasicForm} this
 */
Ext.form.BasicForm.prototype.subload = function(options) {
	if (this.standardSubmit) {
		var v = this.isValid();
		if (v) {
			this.el.dom.submit();
		}
		return v;
	}
	this.doAction('subload', options);
	return this;
};

