Ext.define("Ext.ux.form.field.ISOTimestampField", {
	extend: "Ext.form.FieldContainer",
	mixins: {
		field: "Ext.form.field.Field"
	},

	alias: "widget.isotimestampfield",

	config: {
		dateParseFormat: ip2.date2dbDate.parseFormat,
		dateFormat: ip2.date2dbDate.format,
		format: "d-m-Y",
		datevalue: "",
		timevalue: 0,

		maxValue: 0,
		minValue: 0,
		step: 0,
		asHigh: false,

		decimalPrecision: 0,
		forcePrecision: true,
		decimalSeparator: ":",

		dateField: undefined,
		timeField: undefined,
		microField: undefined,

		secondsValue: "00",

		date: true,
		time: true,
		micro: false,
		seconds: false,

		"native": false
	},

	altFormats: "|d-n-Y|d-n-y|j-n-Y|j-n-y|" +
	"|d/n/Y|d/n/y|j/n/Y|j/n/y|" +
	"|d-m-Y|d-m-y|j-m-Y|j-m-y|" +
	"|d/m/Y|d/m/y|j/m/Y|j/m/y|" +
	"|m/d/Y|m/d/y|m/j/Y|m/j/y|" +
	"|m-d-Y|m-d-y|m/j/Y|m/j/y|" +
	"|n/d/Y|n/d/y|n/j/Y|n/j/y|" +
	"|n-d-Y|n-d-y|n-j-Y|n-j-y|" +
	"|Y-m-d|y-m-d|Y-n-d|y-n-d|" +
	"|Y-m-j|y-m-j|Y-n-j|y-n-j|" +
	"|Y/m/d|y/m/d|Y/n/d|y/n/d|" +
	"|Y/m/j|y/m/j|Y/n/j|y/n/j|" +
	"|d.m.Y|d.m.y|j.m.Y|j.m.y|" +
	"|d.n.Y|d.n.y|j.n.Y|j.n.y|" +
	"|m.d.Y|m.d.Y|m.j.Y|m.j.y|" +
	"|n.d.Y|n.d.y|n.j.Y|n.j.y|" +
	"|Y.m.d|y.m.d|Y.m.j|y.m.j|" +
	"|Y.n.d|y.n.d|Y.n.j|y.n.j|" +
	"|dmY|dmy|jmY|jmy|" +
	"|dnY|dny|jnY|jny|" +
	"|mdY|mdy|mjY|mjy|" +
	"|ndY|ndy|njY|njy|" +
	"|Ymd|ymd|Ymj|ymj|" +
	"|Ynd|ynd|Ynj|ynj|",

	layout: {
		type: "hbox",
		align: "stretch"
	},
	defaults: {
		"margin": "0 5 0 0"
	},
	readOnly: false,

	initComponent: function () {

		var i_self = this;
		i_self.callParent();

		i_self.fieldLabel = i_self.fieldLabel;
		if (!i_self.step) {
			i_self.step = i_self.seconds ? 0.0001 : 0.01;
		}
		i_self.maxValue = i_self.seconds ? 23.5959 : 23.59;
		i_self.minValue = 0.00;
		i_self.decimalPrecision = i_self.seconds ? 4 : 2;
		var i_datefield = i_self.createDateField();
		var i_timefield = i_self.createTimeField();
		var i_microfield = i_self.createMicroField();

		if (!i_self.getDate()) {
			i_datefield.hidden = true;
		}
		if (!i_self.getTime()) {

			i_timefield.hidden = true;
			i_self.micro = false;

			i_datefield.setMargin("0 0 0 0");
		}
		if (!i_self.getMicro()) {
			i_microfield.hidden = true;
		}

		i_datefield.on({
			change: {
				fn: function(item) {
					i_self.checkChange();
				}
			}
		});

		i_timefield.on({
			change: {
				fn: function(item) {
					i_self.checkChange();
				},
				buffer: 250
			}
		});

		i_self.setDateField(i_datefield);
		i_self.setTimeField(i_timefield);
		i_self.setMicroField(i_microfield);

		i_self.add(i_datefield);
		i_self.add(i_timefield);
		i_self.add(i_microfield);

		i_self.initField();
	},

	initValue: function() {

		var i_self = this;
		var value = i_self.value;
		var date;

		if (Ext.isDate(value)) {
			date = value;
		}
		else {
			if (value) {
				var a_split = [];

				if (!i_self.date) {

					var i_date = new Date();
					var n_year = i_date.getFullYear();
					var n_month = i_date.getMonth() + 1;
					var n_day = i_date.getDate();

					a_split = value.split(".");

					a_split = Ext.Array.map(a_split, function(s_value) {
						var s_return = s_value;
						var n_value = parseInt(s_value);
						if (n_value) {
							if (n_value < 10 && s_value.length < 2) {
								s_return = "0" + s_value;
							}
						}
						else {
							if (!isNaN(n_value)) {
								if (s_value.length < 2) {
									s_return = "0" + s_value;
								}
							}
							else {
								s_return = "00";
							}
						}
						return s_return;
					});
					value = a_split.join(".");

					if (a_split.length < 3) {
						value = value + ".00";
					}

					var s_date = n_year + "-" + n_month + "-" + n_day;
					var s_value = s_date + "-" + value + ".000000";
					date = Ext.Date.parse(s_value, "Y-n-d-H.i.s.u");
				}
				else {
					if (Ext.isArray(value)) {
						value = value[0];
					}
					a_split = value.split("-");
					if (a_split[1].length == 2) {
						date = Ext.Date.parse(value, i_self.dateParseFormat);
					}
					else {
						// WHEN THE MONTH HAS A NO LEADING ZERO
						date = Ext.Date.parse(value, "Y-n-d-H.i.s.u");
					}
				}
			}
		}

		if (date) {
			var time;

			var h = date.getHours();
			var m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
			var s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
			var mi;

			if (Ext.isDate(value)) {
				mi = date.getMilliseconds() < 10 ? "0" + date.getMilliseconds() : date.getMilliseconds();
			}
			else {
				if (value) {
					var a_values = value.split(".");
					if (a_values.length == 4) {
						mi = a_values[3];
					}
					else {
						mi = "000000";
					}
				}
				else {
					mi = "0000";
				}

				//mi = parseFloat(mi);
			}
			if (i_self.seconds) {
				time = parseFloat(h + "." + m + "" + s);
			}
			else {
				time = parseFloat(h + "." + m);
				i_self.secondsValue = s;
			}

			var i_datefield = i_self.getDateField();
			var i_timefield = i_self.getTimeField();
			var i_microfield = i_self.getMicroField();

			i_datefield.setValue(date);
			i_timefield.setValue(time);
			i_microfield.setValue(mi);

			i_datefield.resetOriginalValue();
			i_timefield.resetOriginalValue();
			i_microfield.resetOriginalValue();
		}

		i_self.originalValue = i_self.lastValue = i_self.value = i_self.getValue();
		i_self.resetOriginalValue();
	},

	createDateField: function () {

		var i_self = this;

		var i_dateField = Ext.create("Ext.form.field.Date", {
			format: Ext.util.Format.dateFormat || i_self.format,
			submitFormat: "Y-m-d",
			altFormats: i_self.altFormats,
			isFormField: false,
			selectOnFocus: i_self.selectOnFocus || false,
			emptyText: i_self.emptyText,
			readOnly: i_self.readOnly,
			value: i_self.datevalue !== "" ? i_self.datevalue : "",
			flex: 1
		});
		return i_dateField;
	},

	focus: function() {

		var i_self = this;
		var i_datefield = i_self.getDateField();
		i_datefield.focus(false, 10);
	},

	createTimeField: function () {

		var i_self = this;

		var i_field = Ext.create("Ext.form.field.Number", {
			dateField: i_self.getDateField(),
			forcePrecision: i_self.forcePrecision,
			decimalPrecision: i_self.decimalPrecision,
			decimalSeparator: i_self.decimalSeparator,
			maxValue: i_self.maxValue,
			minValue: i_self.minValue,
			selectOnFocus: i_self.selectOnFocus || false,
			value: i_self.timevalue !== 0 ? i_self.timevalue : 0,
			step: i_self.step,
			fieldStyle: "text-align: right;",
			isFormField: false,
			readOnly: i_self.readOnly,
			margin: "0 0 0 0",
			parseValue: function (value) {

				if (i_self.decimalPrecision > 2) {
					value = String(value).replace(/\:/g, ".");
					var lastIndex = String(value).lastIndexOf(".");
					if (lastIndex > 2) {
						var valueBefore = String(value).substring(0, lastIndex);
						value = valueBefore + String(value).substr(lastIndex + 1, 2);
					}
				}
				else {
					value = String(value).replace(/\:/g, ".");
				}

				value = parseFloat(String(value));

				return isNaN(value) ? "" : value;
			},

			setValue: function (value) {

				if (i_self.decimalPrecision > 2) {
					value = String(value).replace(/\:/g, ".");
					var lastIndex = String(value).lastIndexOf(".");
					if (lastIndex > 2) {
						var valueBefore = String(value).substring(0, lastIndex);
						value = valueBefore + String(value).substr(lastIndex + 1, 2);
					}
				}
				value = typeof value == "number" ? value : String(value).replace(this.decimalSeparator, ".").replace(/,/g, "");

				//v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
				value = parseFloat(value);
				value = isNaN(value) ? "" : i_self.forcePrecision ? value.toFixed(i_self.decimalPrecision) : parseFloat(value);

				//this.setRawValue(value);
				return Ext.form.NumberField.superclass.setValue.call(this, parseFloat(value));
			},

			validateValue: function (value) {

				if (i_self.decimalPrecision > 2) {
					value = String(value).replace(/\:/g, ".");
					var lastIndex = String(value).lastIndexOf(".");
					if (lastIndex > 2) {
						var valueBefore = String(value).substring(0, lastIndex);
						value = valueBefore + String(value).substr(lastIndex + 1, 2);
					}
				}
				if (value.length < 1) {
					// if it's blank and textfield didn't flag it then it's valid
					return true;
				}
				value = String(value).replace(this.decimalSeparator, ".").replace(/,/g, "");
				if (isNaN(value)) {
					this.markInvalid(this.nanText.replace("{0}", value));
					return false;
				}
				var num = this.parseValue(value);
				if (num < this.minValue) {
					this.markInvalid(this.minText.replace("{0}", this.minValue));
					return false;
				}
				else if (num > this.maxValue) {
					this.markInvalid(this.maxText.replace("{0}", this.maxValue));
					return false;
				}
				else {
					this.clearInvalid();
				}
				return true;
			},

			getSubmitValue: function() {

				var i_field = this;

				var value = i_field.valueToRaw(i_field.value);
				value = String(value).replace(/\:/g, ".");
				return value;
			},

			//valueToRaw: function (c) {
			//    var b = this,
			//    a = b.decimalSeparator;
			//    c = b.parseValue(c);
			//    c = b.fixPrecision(c);
			//    c = Ext.isNumber(c) ? c : parseFloat(String(c).replace(a, "."));
			//    c = isNaN(c) ? "" : String(c).replace(".", a);
			//    return c
			//}

			valueToRaw: function (value) {

				var i_field = this;

				var decimalSeparator = i_self.decimalSeparator;
				value = isNaN(value) ||
					value == null ? 0 : i_self.forcePrecision ?
							parseFloat(value.toFixed(i_self.decimalPrecision)) : parseFloat(value);
				value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, "."));

				var hours = "";
				var minutes = "";
				var seconds = "";
				var decimalIndex = 0;
				var number = 0;

				if (isNaN(value)) {
					value = "";
				}
				else {
					var hourIndex = String(value).indexOf(".");
					var preHours = "";
					var preMins = "";
					var preSecs = "";
					if (hourIndex == -1) {
						if (String(value).length == 3) {
							preHours = String(value).substr(0, 1);
							preMins = String(value).substr(1, 2);
							value = preHours + "." + preMins;
							hourIndex = String(value).indexOf(".");
							value = parseFloat(value).toFixed(i_self.decimalPrecision);
						}
						else if (String(value).length == 4) {
							preHours = String(value).substr(0, 2);
							preMins = String(value).substr(2, 2);
							value = preHours + "." + preMins;
							hourIndex = String(value).indexOf(".");
							value = parseFloat(value).toFixed(i_self.decimalPrecision);
						}

						else if (String(value).length == 5) {
							preHours = String(value).substr(0, 2);
							preMins = String(value).substr(2, 2);
							preSecs = String(value).substr(4, 1);
							value = preHours + "." + preMins + preSecs;
							hourIndex = String(value).indexOf(".");
							value = parseFloat(value).toFixed(i_self.decimalPrecision);
						}

						else if (String(value).length == 6) {
							preHours = String(value).substr(0, 2);
							preMins = String(value).substr(2, 2);
							preSecs = String(value).substr(4, 2);
							value = preHours + "." + preMins + preSecs;
							hourIndex = String(value).indexOf(".");
							value = parseFloat(value).toFixed(i_self.decimalPrecision);
						}
					}

					if (hourIndex == -1) {
						hours = value;
					}
					else {
						hours = String(value).substring(0, String(value).indexOf("."));
					}

					var step = i_self.step;
					var stepSeconds = 0;
					var stepMinues = 0;

					var stepIndex = String(step).indexOf(".") + 1;
					var stepDecimal = String(step).substring(stepIndex, String(step).length);

					if (String(step).length == 5) {
						stepDecimal = parseInt(stepDecimal);
					}

					if (String(stepDecimal).length < 2) {
						stepDecimal += "0";
					}

					if (String(step).length == 6) {
						stepDecimal = parseInt(stepDecimal);
					}
					else if (String(step).length > 6) {
						stepDecimal = parseInt(String(step).substr(stepIndex, 4));
					}

					stepDecimal = parseInt(stepDecimal);

					if (stepDecimal >= 1000) {
						stepMinues = parseInt(String(stepDecimal).substr(0, 2));
						stepSeconds = parseInt(String(stepDecimal).substr(2, 2));
					}
					else {
						if (stepDecimal > 100) {
							stepMinues = parseInt(String(stepDecimal).substr(0, 1));
							stepSeconds = parseInt(String(stepDecimal).substr(1, 2));
						}
						else {
							if (stepDecimal > 9) {
								stepSeconds = parseInt(String(stepDecimal).substr(0, 2));
							}
							else {
								stepSeconds = parseInt(String(stepDecimal).substr(0, 1));
							}
						}
					}
					if (i_self.decimalPrecision == 4) {
						decimalIndex = String(value).indexOf(".") + 1;
						if (decimalIndex === 0) {
							minutes = "";
						}

						else {
							minutes = String(value).substring(decimalIndex, decimalIndex + 2);
							if (String(minutes).length < 2) {
								minutes += "0";
							}
						}

						seconds = String(value).substring((decimalIndex + 2), ((decimalIndex + 2) + 2));

						if (minutes === "") {
							minutes = 0;
						}

						if (seconds === "") {
							seconds = 0;
						}

						var diffMin = minutes;
						var diffSec = seconds;

						if (String(diffSec).length < 2) {
							diffSec += "0";
						}

						if (parseInt(diffSec) > 59) {
							if ((parseInt(diffSec) + parseInt(stepSeconds)) >= 100) {
								number = (parseInt(diffSec) + parseInt(stepSeconds));
								var diffSeconds = number - 100;
								diffSec = 60 - (parseInt(stepSeconds) - diffSeconds);
							}
							else {
								diffSec = diffSec - 60;
								diffMin = parseInt(minutes);
								diffMin++;
								if (diffMin < 10) {
									diffMin = "0" + diffMin;
								}

								minutes = diffMin;

								if (diffSec < 10) {
									diffSec = "0" + diffSec;
								}
							}
						}
						if (parseInt(minutes) > 59) {
							if (parseInt(minutes) + stepMinues >= 100) {
								var diffMinutes = (parseInt(minutes) + stepMinues) - 100;
								diffMin = 60 - (stepMinues - diffMinutes);
							}
							else {
								diffMin = minutes - 60;
								if (diffMin < 10) {
									diffMin = "0" + diffMin;
								}
								hours++;
							}
						}
						if (String(diffSec).length < 2) {
							diffSec = "0" + diffSec;
						}

						seconds = diffSec;

						if (String(diffMin).length < 2) {
							diffMin = "0" + diffMin;
						}

						minutes = diffMin;
						value = i_field.parseValue(hours + "." + diffMin + "." + diffSec);
					}
					else {

						decimalIndex = String(value).indexOf(".") + 1;
						var decimals = String(value).substring(decimalIndex, String(value).length);
						var diff = 0;
						if (decimals.length < 2) {
							if (decimalIndex === 0) {
								decimals = "00";
							}
							else {
								decimals += "0";
							}
						}

						if (parseInt(decimals) > 59) {
							if ((parseInt(decimals) + parseInt(stepDecimal)) >= 100) {
								number = (parseInt(decimals) + parseInt(stepDecimal));
								var diffNumber = number - 100;
								diff = 60 - (parseInt(stepDecimal) - diffNumber);
							}
							else {
								diff = decimals - 60;
								hours++;
								if (diff < 10) {
									diff = "0" + diff;
								}
							}
							value = i_field.parseValue(hours + "." + diff);
						}
					}
				}
				value = i_self.forcePrecision ? Ext.isNumber(value) ? value.toFixed(i_self.decimalPrecision) :
				parseFloat(value).toFixed(i_self.decimalPrecision) : parseFloat(value);

				if (i_self.decimalPrecision != 4) {
					if (hours < 10) {
						value = "0" + String(value);
					}
					value = (value).replace(/\./g, decimalSeparator);
				}
				else {
					if (hours < 10) {
						hours = "0" + hours;
					}
					value = String(hours) + "." + String(minutes) + "." + String(seconds);
					value = (value).replace(/\./g, decimalSeparator);
				}
				return String(value);
			}
		});

		i_field.width = i_self.readOnly ? i_self.seconds ? 110 : 90 : i_self.seconds ? 110 : 90;

		return i_field;
	},

	createMicroField: function () {

		var i_field = Ext.create("Ext.form.field.Text", {
			readOnly: true,
			width: 50,
			isFormField: false
		});

		return i_field;
	},

	getValue: function () {

		var i_self = this;
		var value = "";

		var dateValue = i_self.getDateField().getSubmitValue();

		if (dateValue) {

			var timeValue = i_self.getTimeField().getSubmitValue();
			var microValue = i_self.getMicroField().getValue();
			var i_microLength = microValue.length;
			if (i_microLength < 6) {
				while (i_microLength < 6) {
					microValue = microValue + "0";
					i_microLength++;
				}
			}
			if (!i_self.time) {
				if (i_self.asHigh) {
					timeValue = "23.59";
				}
			}
			if (!i_self.seconds) {
				if (i_self.asHigh) {
					i_self.secondsValue = "59";
				}
				timeValue = timeValue + "." + i_self.secondsValue;
			}
			if (i_self.asHigh) {
				microValue = "999999";
			}

			if (!i_self.date) {
				value = timeValue;
			}
			else {
				value = dateValue + "-" + timeValue + "." + microValue;
			}
		}

		if (i_self.getNative()) {
			value = Ext.Date.parse(value, i_self.dateParseFormat);
		}

		return value;
	},

	getRawValue: function() {

		var i_self = this;
		var i_datefield = i_self.getDateField();
		var i_timefield = i_self.getTimeField();

		var s_value = i_datefield.getRawValue();

		var s_time = i_timefield.getRawValue();

		if (s_value) {
			s_value = s_value + " " + s_time;
		}

		return s_value;
	},

	setValue: function (value) {

		var i_self = this;
		i_self.value = value;
		var date;

		if (value) {
			if (Ext.isDate(value)) {
				date = value;
			}
			else {
				if (value) {
					var a_split = [];

					if (!i_self.date) {

						var i_date = new Date();
						var n_year = i_date.getFullYear();
						var n_month = i_date.getMonth() + 1;
						var n_day = i_date.getDate();

						a_split = value.split(".");

						a_split = Ext.Array.map(a_split, function(s_value) {
							var s_return = s_value;
							var n_value = parseInt(s_value);
							if (n_value) {
								if (n_value < 10 && s_value.length < 2) {
									s_return = "0" + s_value;
								}
							}
							else {
								if (!isNaN(n_value)) {
									if (s_value.length < 2) {
										s_return = "0" + s_value;
									}
								}
								else {
									s_return = "00";
								}
							}
							return s_return;
						});
						value = a_split.join(".");

						if (a_split.length < 3) {
							value = value + ".00";
						}

						var s_date = n_year + "-" + n_month + "-" + n_day;
						var s_value = s_date + "-" + value + ".000000";
						date = Ext.Date.parse(s_value, "Y-n-d-H.i.s.u");
					}
					else {
						if (Ext.isArray(value)) {
							value = value[0];
						}
						a_split = value.split("-");
						if (a_split[1].length == 2) {
							date = Ext.Date.parse(value, i_self.dateParseFormat);
						}
						else {
							// WHEN THE MONTH HAS A NO LEADING ZERO
							date = Ext.Date.parse(value, "Y-n-d-H.i.s.u");
						}
					}
				}
			}

			if (date) {
				var time;

				var h = date.getHours();
				var m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
				var s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
				var mi;

				if (Ext.isDate(value)) {
					mi = date.getMilliseconds() < 10 ? "0" + date.getMilliseconds() : date.getMilliseconds();
				}
				else {
					if (value) {
						var a_values = value.split(".");
						if (a_values.length == 4) {
							mi = a_values[3];
						}
						else {
							mi = "000000";
						}
					}
					else {
						mi = "0000";
					}

					//mi = parseFloat(mi);
				}
				if (i_self.seconds) {
					time = parseFloat(h + "." + m + "" + s);
				}
				else {
					time = parseFloat(h + "." + m);
					i_self.secondsValue = s;
				}

				i_self.getDateField().setValue(date);
				i_self.getTimeField().setValue(time);
				i_self.getMicroField().setValue(mi);
				i_self.value = i_self.getValue();

				var b_reset = false;

				if (i_self.getDateField().originalValue === undefined) {
					i_self.getDateField().originalValue = i_self.getDateField().getValue();
					b_reset = true;
				}

				if (i_self.getTimeField().originalValue === undefined || i_self.getTimeField().originalValue === 0) {
					i_self.getTimeField().originalValue = i_self.getTimeField().getValue();
					b_reset = true;
				}
				if (i_self.getMicroField().originalValue === undefined || i_self.getMicroField().originalValue === "") {
					i_self.getMicroField().originalValue = i_self.getMicroField().getValue();
					b_reset = true;
				}

				if (b_reset) {
					i_self.resetOriginalValue();
				}
			}
		}
		else {
			var i_dateField = i_self.getDateField();
			var i_timeField = i_self.getTimeField();
			var i_microField = i_self.getMicroField();

			i_dateField.setValue(null);
			i_timeField.setValue(null);
			i_microField.setValue(null);
		}

	},

	isDirty: function () {

		var i_self = this;

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

		var b_dirty = originalValue != value;

		if (i_self.getNative()) {
			b_dirty = !Ext.Date.isEqual(originalValue, value);
		}

		return b_dirty;
	},

	isValid: function() {

		var i_self = this;
		var i_datefield = i_self.getDateField();
		var i_timefield = i_self.getTimeField();

		return (i_datefield.isValid() && i_timefield.isValid());
	}

});
