Ext.define("Ext.ux.form.field.AceTextArea", {

	statics: {
		n: 0,
		ace: null
	},

	requires: [
		"Ext.form.field.TextArea",
		"Ext.ux.util.ace.Editor"
	],

	mixins: {
		"ace": "Ext.ux.util.ace.Editor"
	},

	extend: "Ext.form.field.TextArea",

	alias: [
		"widget.acetextarea",
		"widget.acetextareafield"
	],

	// CONFIG
	loadMask: true,

	// PROPERTIES
	_loadMask: null,
	_internalValueChange: false,
	_editorActionEl: null,

	config: {
		asArray: false,
		asJson: false,
		splitRegEx: /\n/g,
		joinDelimiter: null
	},

	initComponent: function () {

		var i_cmp = this;

		i_cmp.callParent(arguments);

		i_cmp.on({
			aceloaded: {
				fn: i_cmp.initAceTextArea,
				scope: i_cmp
			},
			editorchange: {
				fn: function (i_self, i_editor, value) {
					i_cmp.value = value;
					i_cmp.checkChange();
				}
			},
			editorvalidate: {
				fn: function(i_self, i_editor) {
					i_cmp.validate();
				}
			}
		});

		i_cmp.initAce();

		return i_cmp;
	},

	initAceTextArea: function () {

		var i_cmp = this;

		var f_init = function (i_self) {
			var i_inputEl = i_self.inputEl;

			// Create a container for AceEditor with height of textarea
			var s_height = Ext.DomQuery.getStyle(i_inputEl, "height");
			var s_id = "aceeditortextarea-wrapper-" + i_cmp.getRewriter().n++;
			var s_classNames = i_inputEl.getAttribute("class");

			var o_styles = Ext.apply({}, {
				width: "100%",
				height: "100%",
				position: "relative"
			});

			setTimeout(function () {

				i_inputEl.setStyle("display", "none");
				var s_value = i_inputEl.getValue() || "";
				var i_actionEl = Ext.DomHelper.insertBefore(i_inputEl, {
					tag: "div",
					id: s_id,
					style: o_styles,
					cls: s_classNames
				});

				i_cmp._editorActionEl = Ext.get(i_actionEl);
				i_cmp.suspendCheckChange++;
				i_cmp.initEditor(s_id);
				i_cmp.setEditorValue(s_value);
				i_cmp.resetOriginalValue();
				i_cmp.suspendCheckChange--;
			}, 10);
		};

		if (!i_cmp.inputEl) {
			i_cmp.on("afterrender", f_init, i_cmp, { single: true });
		}
		else {
			f_init(i_cmp);
		}
	},

	setValue: function (value) {

		var i_cmp = this;

		if (Ext.isObject(value)) {
			value = JSON.stringify(value, null, "\t");
		}
		else if (Ext.isArray(value)) {

			if (i_cmp.getAsArray()) {
				var s_delimiter = i_cmp.getJoinDelimiter();
				if (s_delimiter === null) {
					value = value.join("\n");
				}
				else {
					value = value.join(s_delimiter);
				}
			}

			value = value;
		}

		var b_internal = i_cmp._internalValueChange;

		if (i_cmp.getEditor()) {
			if (!b_internal) {
				i_cmp.setEditorValue(value);
			}
		}
		else {
			i_cmp.needSet = true;
		}

		i_cmp.callParent([value]);

		return i_cmp;
	},

	getValue: function() {

		var i_self = this;
		var value = i_self.value;
		if (value) {
			if (i_self.asJson) {
				value = Ext.decode(value, true);
			}
			else if (i_self.getAsArray()) {
				value = value.split(i_self.getSplitRegEx());
			}
		}

		return value;
	},

	getSubmitValue: function() {

		var i_self = this;
		return i_self.getValue();
	},

	isDirty: function() {

		var i_self = this;
		var originalValue = i_self.originalValue;
		var value = i_self.getValue();

		if (i_self.getAsJson()) {

			var i_editor = i_self.getEditor();
			if (i_editor) {
				originalValue = JSON.stringify(originalValue, null, "\t");
				value = i_editor.getValue();
			}
			else {
				originalValue = Ext.encode(originalValue);
				value = Ext.encode(value);
			}
		}
		else {
			originalValue = Ext.encode(originalValue);
			value = Ext.encode(value);
		}

		return originalValue != value;
	},

	didValueChange: function(newVal, oldVal) {

		if (Ext.isObject(newVal)) {
			newVal = Ext.encode(newVal);
		}

		if (Ext.isObject(oldVal)) {
			oldVal = Ext.encode(oldVal);
		}

		return !this.isEqual(newVal, oldVal);
	},

	setError: function(error) {
		var me = this;
		var msgTarget = me.msgTarget;
		var prop;
		if (me.rendered) {
			if (msgTarget == "title" || msgTarget == "qtip") {
				prop = msgTarget == "qtip" ? "data-errorqtip" : "title";
				me.getEditor().container.setAttribute(prop, error || "");
			}
			else {
				me.updateLayout();
			}
		}
	},

	getErrors: function () {

		var i_cmp = this;
		var a_errors = i_cmp.callParent(arguments);
		var a_editorErrors = i_cmp.getEditorErrors();

		return a_errors.concat(a_editorErrors);
	},

	getRewriter: function () {
		return Ext.ux.form.field.AceTextArea;
	}
});
