Ext.define("IceCap.view.Window", {
	extend: "Ext.window.Window",

	layout: "fit",

	requires: [
		"IceCap.controller.Window"
	],

	config: {
		inputData: null,
		lastTabIndex: 1,
		currentTabIndex: 1,
		content: null,
		keyArea: null,
		working: false,
		needFocus: 1,
		currentPosition: {
			col: 1,
			lin: 1
		},
		statusBar: null,
		main: null,
		sessionValue: "",
		cursor: null,
		timer: null,
		theme: "",
		requestCallBack: Ext.emptyFn,
		responseCallBack: Ext.emptyFn
	},

	closable: false,
	modal: false,

	controller: "icecap.view.window",

	listeners: {
		afterrender: {
			fn: function(i_panel) {

				var i_self = i_panel;

				i_self.addKeyEvents();

				var i_content = i_self.getContent();
				var i_main = i_self.getMain();

				if (i_content) {

					var o_inputData = i_self.getInputData();

					var a_fields = i_content.query("field[focusable]");
					var b_found = false;
					var b_error = false;

					Ext.Array.each(a_fields, function(i_field) {
						if (i_field.getTabIndex() === i_self.getNeedFocus()) {
							if (!b_error) {
								setTimeout(function() {
									i_field.focus(true, 10);
								}, 10);
							}
							b_found = true;

							return false;
						}
					});

					if (!b_found) {

						i_self.setCurrentPosition({
							col: o_inputData.csrCol,
							lin: o_inputData.csrLin
						});

						if (!b_error) {
							setTimeout(function() {
								i_main.focus(true, 10);
							}, 10);
						}
					}
				}
			},
			buffer: 100
		},
		dblclick: {
			fn: "onDblClick",
			element: "body"
		},
		click: {
			fn: "onClick",
			element: "body"
		},
		wheel: {
			fn: "onWheel",
			element: "body"
		}

	},

	onKeyDown: Ext.emptyFn, // THIS IS NEED TO OVERRIDE Ext.util,Floating

	initComponent: function() {

		var i_self = this;
		i_self.callParent(arguments);
		i_self.add(i_self.createLayout());
		i_self.enableBubble("toWindow");
		i_self.enableBubble("onAddWebContainer");
		i_self.recreate();
	},

	createStatusBar: function() {

		var i_statusbar = Ext.widget("toolbar", {
			dock: "bottom",
			height: 30,
			setText: function(s_text) {

				var i_toolbar = this;
				i_toolbar.removeAll(true);
				i_toolbar.add({
					xtype: "label",
					text: s_text
				});
			}
		});

		return i_statusbar;
	},

	createLayout: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		return i_self.createContent();
	},

	createContent: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();
		var n_tabIndex = o_inputData.input.length > 0 ? 0 : 1;
		var b_focusable = o_inputData.input.length > 0 ? false : true;

		var i_panel = Ext.widget("panel", {
			layout: "border",
			border: false,
			focusable: b_focusable,
			tabIndex: n_tabIndex,
			items: i_self.createItems()
		});

		i_self.setMain(i_panel);

		return i_panel;
	},

	createItems: function() {

		var i_self = this;

		var a_items = [];

		var i_center = Ext.widget("form", {
			bodyPadding: 5,
			border: false,
			layout: "absolute",
			region: "center",
			flex: 1,
			ui: ["icecap", i_self.getTheme()].filter(Boolean).join("-")
		});

		a_items.push(i_center);

		var i_south = Ext.widget("panel", {
			layout: {
				type: "column"
			},
			border: false,
			bodyPadding: 5,
			defaults: {
				margin: "0 5 5 0"
			},
			region: "south",
			ui: ["icecap", i_self.getTheme()].filter(Boolean).join("-")
		});

		a_items.push(i_south);

		i_self.setContent(i_center);
		i_self.setKeyArea(i_south);

		var i_statusbar = i_self.createStatusBar();

		i_self.addDocked(i_statusbar);

		i_self.setStatusBar(i_statusbar);

		return a_items;
	},

	createFields: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];

		var n_tabIndex = 1;
		var n_focus = o_inputData.focus;

		var n_inputWidth = o_inputData.width || 80;

		var b_fixed = IceCap.util.Handler.getFixed();

		Ext.Array.each(o_inputData.input, function(o_config, n_index) {

			var n_default = IceCap.util.Handler.getDefaultWidth();
			var n_width = n_default;

			var o_meta = o_config.metaData || {};

			var o_field = {
				inputType: "text",
				xtype: "textfield"
			};

			if (o_config.len > 1) {
				n_width = ((o_config.len - 1) * IceCap.util.Handler.getColSize()) + n_default;
			}

			Ext.apply(o_field, i_self.applyFFW(o_config));

			var s_type = o_field.xtype || "textfield";
			var n_x = IceCap.util.Handler.getX(o_config.col);
			var n_y = IceCap.util.Handler.getY(o_config.lin);
			var b_password = o_config.atr == "27";

			if (o_field.readOnly) {

				o_field.xtype = s_type = "displayfield";

				Ext.apply(o_field.fieldStyle, {
					"padding": "1px 3px 2px 3px",
					"margin-top": IceCap.util.Handler.getMargin() + "px !important",
					"margin-left": "1px",
					"border": "1px solid transparent"
				});
			}

			if (o_config.len > n_inputWidth) {
				var n_temp = n_inputWidth - o_config.col;
				n_width = ((n_temp - 1) * IceCap.util.Handler.getColSize()) + n_default;
			}

			var o_listeners = Ext.apply({}, o_meta.listeners);
			delete o_meta.listeners;

			var a_field = ["icecap-field", i_self.getTheme()];

			var a_pass = [b_password ? "iceCap-input-password" : "iceCap-input-" + (o_config.atr || 20)];

			a_pass.push(i_self.getTheme());

			var a_cls = [a_field.filter(Boolean).join("-"), a_pass.filter(Boolean).join("-")];

			var s_cls = a_cls.join(" ");

			Ext.Object.merge(o_field, {
				width: n_width,
				enforceMaxLength: true,
				maxLength: o_config.len,
				minWidth: IceCap.util.Handler.getDefaultWidth(),
				tabIndex: n_tabIndex,
				lin: o_config.lin,
				col: o_config.col,
				emuId: o_config.id,
				name: o_config.id,
				value: o_config.dta || "",
				x: n_x,
				y: n_y,
				cls: s_cls,
				enableKeyEvents: true,
				selectOnFocus: true,
				listeners: {
					afterrender: {
						fn: function(i_field) {

							if (i_field.inputEl) {
								i_field.inputEl.setMinHeight(0);
								i_field.inputEl.setHeight(IceCap.util.Handler.getDefaultHeight());

								i_field.inputEl.set({
									autocomplete: "off"
								});
							}
						}
					},
					focus: {
						fn: function(i_field) {

							var n_tabIndex = i_field.getTabIndex();
							i_self.setCurrentTabIndex(n_tabIndex);

							var o_position = {
								col: i_field.col,
								lin: i_field.lin
							};
							i_self.setCurrentPosition(o_position);

							var i_cursor = i_self.getCursor();
							i_cursor.moveCursor(o_position);
							i_cursor.hide();
						}
					},
					keyup: {
						fn: function(i_field, i_event) {

							if (i_field.xtype === "textfield") {
								var s_direction = i_field.inputEl.el.dom.selectionDirection;

								var n_start = s_direction == "forward" ? i_field.inputEl.el.dom.selectionEnd : i_field.inputEl.el.dom.selectionStart;
								var n_add = i_field.value.length * IceCap.util.Handler.getColSize();

								if (n_start != i_field.value.length) {
									n_add = n_start * IceCap.util.Handler.getColSize();
								}

								var o_input = Ext.apply({
									x: i_field.getLocalX() + n_add,
									y: i_field.getLocalY()
								});

								var o_position = IceCap.util.Handler.toColAndLine(o_input);
								i_self.setCurrentPosition(o_position);

								var i_cursor = i_self.getCursor();
								i_cursor.moveCursor(o_position);
							}
						}
					},
					keydown: {
						fn: function(i_field, i_event) {

							if (i_event.ctrlKey) {

								if (i_event.keyCode == Ext.event.Event.DOWN ||
									i_event.keyCode == Ext.event.Event.UP) {

									i_event.stopEvent();

									var i_main = i_self.getMain();

									var n_y = IceCap.util.Handler.getLineHeight();

									if (i_event.keyCode == Ext.event.Event.UP) {
										n_y = -IceCap.util.Handler.getLineHeight();
									}

									var o_input = Ext.apply({
										x: i_field.getLocalX(),
										y: i_field.getLocalY() + n_y
									});

									var o_position = IceCap.util.Handler.toColAndLine(o_input);
									i_self.setCurrentPosition(o_position);

									var i_cursor = i_self.getCursor();
									i_cursor.moveCursor(o_position);

									var a_inputs = i_self.query("field[focusable]");

									var o_box = Ext.apply({
										width: IceCap.util.Handler.getColSize(),
										height: 1
									}, o_input);

									var b_intersect = false;

									Ext.Array.each(a_inputs, function(i_field) {

										var o_bound = i_field.el.dom.getBoundingClientRect();

										var o_rect = Ext.apply({}, {
											x: i_field.getLocalX(),
											y: i_field.getLocalY(),
											width: o_bound.width,
											height: o_bound.height
										});

										if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
											b_intersect = true;
											i_field.focus(true, 10);
											return false;
										}
									});

									if (!b_intersect) {

										i_field.blur();
										i_cursor.show();

										i_main.focus(true, 10);
									}
								}
							}
						}
					}
				}
			}, o_meta);

			var i_field = Ext.widget(s_type, o_field);

			var o_on = {};

			Ext.Object.each(o_listeners, function(s_key, value) {

				if (Ext.isFunction(value)) {
					o_on[s_key] = Ext.apply({}, {
						fn: value,
						scope: i_self
					});
				}
				else if (Ext.isObject(value)) {
					value.scope = i_self;
					o_on[s_key] = value;
				}
			});

			i_field.on(o_on);

			n_tabIndex++;

			if (o_config.atr == 25) {

				if (b_readyOnly) {
					i_field.addCls("icecap-invalid");
				}
				else {
					i_field.markInvalid(true);
				}
			}

			a_fields.push(i_field);
		});

		n_tabIndex = n_tabIndex - 1;
		i_self.setLastTabIndex(n_tabIndex);
		i_self.setCurrentTabIndex(o_inputData.focus);

		if (n_focus) {
			i_self.setNeedFocus(n_focus);
		}

		return a_fields;
	},

	createLabels: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];

		var b_fixed = IceCap.util.Handler.getFixed();

		Ext.Array.each(o_inputData.output, function(o_config) {

			var s_value = "";
			if (o_config.len) {
				if (o_config.ta == "right" && !o_config.off) {
					//o_config.col += o_config.len - o_config.dta.length;
				}

				if (o_config.off) {
					o_config.dta = Ext.String.leftPad(o_config.dta, o_config.dta.length + o_config.off);
				}

				var n_x = Math.ceil((IceCap.util.Handler.getX(o_config.col) + (IceCap.util.Handler.getColSize() / 2)));
				var n_y = IceCap.util.Handler.getY(o_config.lin);

				var o_field = {
					value: o_config.dta,
					htmlEncode: true,
					x: n_x,
					y: n_y,
					cls: ["icecap-field", i_self.getTheme()].filter(Boolean).join("-")
				};

				var o_style = {
					"font": "normal " + IceCap.util.Handler.getTextSize() + "px Segoe UI,Segoe,DejaVu Sans,Trebuchet MS,Verdana,sans-serif",
					"margin-top": IceCap.util.Handler.getMargin() + "px !important",
					"min-height": "0px !important"
				};

				if (b_fixed) {

					Ext.apply(o_field, {
						fieldCls: ["x-form-display-field iceCap-output-" + (o_config.atr || 20), i_self.getTheme()].filter(Boolean).join("-")
					});

					Ext.apply(o_style, {
						"font": "normal " + IceCap.util.Handler.getTextSize() + "px Lucida Console, Courier New, monospace",
						"white-space": "pre",
						"margin-top": IceCap.util.Handler.getMargin() + "px !important",
						"min-height": "0px !important"
					});
				}

				Ext.apply(o_field, {
					fieldStyle: o_style
				});

				if (o_config.atr == "27") {
					o_field.hidden = true;
				}

				var i_field = Ext.widget("displayfield", o_field);

				if (o_config.atr == 23) {

					i_field.addCls("icecap-invalid");
				}

				a_fields.push(i_field);
			}
		});

		return a_fields;
	},

	createKeys: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_buttons = [];

		Ext.Array.each(o_inputData.keys, function(o_config) {

			var s_template = "{0}={1}";

			s_template = s_template.replace("{0}", o_config.id);
			s_template = s_template.replace("{1}", o_config.text);

			var i_button = Ext.widget("button", {
				text: s_template,
				key: o_config.id,
				focusable: false,
				handler: function(i_button) {
					i_self.doKeyEvent(i_button.key);
				}
			});

			a_buttons.push(i_button);
		});

		return a_buttons;
	},

	createMetaFields: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var a_fields = [];
		var n_tabIndex = i_self.getLastTabIndex();

		Ext.Array.each(o_inputData.metaFields, function(o_config) {

			var n_x = o_config.x;
			var n_y = o_config.y;

			if (!o_config.x) {
				n_x = Math.ceil((IceCap.util.Handler.getX(o_config.col) + (IceCap.util.Handler.getColSize() / 2)));
			}

			if (!o_config.y) {
				n_y = IceCap.util.Handler.getY(o_config.lin);
			}

			Ext.apply(o_config, {
				tabIndex: n_tabIndex + 1,
				x: n_x,
				y: n_y
			});

			var i_field = Ext.widget(o_config.xtype, o_config);
			a_fields.push(i_field);
		});

		i_self.setLastTabIndex(n_tabIndex);

		return a_fields;
	},

	doCreateFromData: function(o_inputData) {

		var i_self = this;
		i_self.fireEvent("toWindow", i_self, o_inputData);
	},

	recreate: function() {

		var i_self = this;

		var i_content = i_self.getContent();
		var i_keyArea = i_self.getKeyArea();
		var i_main = i_self.getMain();
		var o_inputData = i_self.getInputData();

		var b_fixed = o_inputData.hasOwnProperty("fixed") ? o_inputData.fixed : true;

		IceCap.util.Handler.setFixed(b_fixed);

		if (o_inputData.title) {
			i_self.setTitle(o_inputData.title);
		}

		var a_created = i_self.createFields();
		a_created = a_created.concat(i_self.createLabels());
		a_created = a_created.concat(i_self.createMetaFields());
		a_created.push(i_self.createCursor());

		i_content.removeAll(true);
		i_keyArea.removeAll(true);

		i_content.add(a_created);

		var a_keys = i_self.createKeys();
		i_keyArea.add(a_keys);

		i_keyArea[a_keys.length === 0 ? "hide" : "show"]();

		var a_fields = i_self.query("field[focusable]");
		var b_found = false;
		var b_error = false;

		if (o_inputData.msgBox && o_inputData.msgBox.text) {
			b_error = true;
			i_self.onError(o_inputData);
		}

		Ext.Array.each(a_fields, function(i_field) {
			if (i_field.getTabIndex() === i_self.getNeedFocus()) {
				if (!b_error) {
					setTimeout(function() {
						i_field.focus(true, 10);
					}, 10);
				}
				b_found = true;
				return false;
			}
		});

		if (!b_found) {

			i_self.setCurrentPosition({
				col: o_inputData.csrCol,
				lin: o_inputData.csrLin
			});

			if (!b_error) {
				setTimeout(function() {
					i_main.focus(true, 10);
				}, 10);
			}
		}

		var s_message = "";
		var i_statusbar = i_self.getStatusBar();

		i_statusbar.removeAll(true);
		var b_show = true;

		if (Ext.isArray(o_inputData.message)) {

			if (o_inputData.message.length > 0) {
				Ext.Array.each(o_inputData.message, function(o_message) {
					i_statusbar.add({
						xtype: "label",
						text: o_message.text
					});
					b_show = true;
				});
			}
		}

		if (!b_found && !b_error) {
			setTimeout(function() {
				i_main.focus(true, 10);
			}, 10);
		}

		i_statusbar[b_show ? "show" : "hide"]();

		IceCap.util.Handler.setFixed(true);
	},

	getCurrentField: function() {

		var i_self = this;

		var a_fields = i_self.query("field[focusable]");
		var n_tabIndex = i_self.getCurrentTabIndex();
		var i_controller = i_self.getController();

		var i_content = i_self.getContent();
		var i_currentField;

		Ext.Array.each(a_fields, function(i_field) {
			if (i_field.getTabIndex() === n_tabIndex && i_field.hasFocus) {
				i_currentField = i_field;
				return false;
			}
		});

		return i_currentField;
	},

	doKeyEvent: function(s_value, i_event) {

		if (i_event) {
			i_event.stopEvent();
		}

		var i_self = this;
		var i_controller = i_self.getController();
		i_controller.doKeyEvent(s_value);
	},

	doNavigationKey: function(n_direction, b_tab, i_event) {

		i_event.stopPropagation();
		i_event.preventDefault();

		var i_self = this;
		var i_controller = i_self.getController();
		i_controller[b_tab ? "doTabKey" : "doArrowKeys"](n_direction);
	},

	addKeyEvents: function() {

		var i_self = this;

		var a_bindings = [
			{
				key: Ext.event.Event.PAGE_DOWN,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ROLLUP", i_event);
				}
			},
			{
				key: Ext.event.Event.PAGE_UP,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ROLLDOWN", i_event);
				}
			},
			{
				key: Ext.event.Event.ENTER,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ENTER", i_event);
				}
			},
			{
				key: Ext.event.Event.ESC,
				fn: function(n_key, i_event) {

					i_event.preventDefault();

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doKeyEvent("ATTN", i_event);
				}
			},
			{
				key: Ext.event.Event.UP,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					if (!i_event.target.type) {

						i_event.stopEvent();

						var i_cursor = i_self.getCursor();
						var o_position = i_self.getCurrentPosition();

						var a_inputs = i_self.query("field[focusable]");

						o_position.lin = o_position.lin - 1;

						if (o_position.lin < 1) {
							o_position.lin = 1;
						}

						var o_box = Ext.apply({
							x: IceCap.util.Handler.getX(o_position.col - 1),
							y: IceCap.util.Handler.getY(o_position.lin),
							width: Math.floor(IceCap.util.Handler.getColSize()),
							height: 1
						});

						var b_intersect = false;

						Ext.Array.each(a_inputs, function(i_field) {

							var o_bound = i_field.el.dom.getBoundingClientRect();

							var o_rect = Ext.apply({}, {
								x: i_field.getLocalX(),
								y: i_field.getLocalY(),
								width: o_bound.width,
								height: o_bound.height
							});

							if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
								b_intersect = true;
								i_field.focus(true, 10);
								return false;
							}
						});

						if (!b_intersect) {
							i_cursor.moveCursor(o_position);
						}
						i_self.setCurrentPosition(o_position);
					}
					else {
						i_self.doNavigationKey(0, false, i_event);
					}
				}
			},
			{
				key: Ext.event.Event.DOWN,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					if (!i_event.target.type) {

						i_event.stopEvent();

						var i_cursor = i_self.getCursor();
						var o_position = i_self.getCurrentPosition();
						var o_inputData = i_self.getInputData();
						var o_window = o_inputData.window;

						var a_inputs = i_self.query("field[focusable]");

						o_position.lin = o_position.lin + 1;

						if (o_position.lin > o_window.height) {
							o_position.lin = o_window.height;
						}

						var o_box = Ext.apply({
							x: IceCap.util.Handler.getX(o_position.col - 1),
							y: IceCap.util.Handler.getY(o_position.lin),
							width: Math.floor(IceCap.util.Handler.getColSize()),
							height: 1
						});

						var b_intersect = false;

						Ext.Array.each(a_inputs, function(i_field) {

							var o_bound = i_field.el.dom.getBoundingClientRect();

							var o_rect = Ext.apply({}, {
								x: i_field.getLocalX(),
								y: i_field.getLocalY(),
								width: o_bound.width,
								height: o_bound.height
							});

							if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
								b_intersect = true;
								i_field.focus(true, 10);
								return false;
							}
						});

						if (!b_intersect) {
							i_cursor.moveCursor(o_position);
						}
						i_self.setCurrentPosition(o_position);
					}
					else {
						i_self.doNavigationKey(1, false, i_event);
					}
				}
			},
			{
				key: Ext.event.Event.LEFT,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					if (!i_event.target.type) {
						i_event.stopEvent();

						var i_cursor = i_self.getCursor();
						var o_position = i_self.getCurrentPosition();

						var a_inputs = i_self.query("field[focusable]");

						o_position.col = o_position.col - 1;
						var n_col = o_position.col;
						if (o_position.col < 1) {
							o_position.col = 1;
						}

						var o_box = Ext.apply({
							x: IceCap.util.Handler.getX(n_col - 1),
							y: IceCap.util.Handler.getY(o_position.lin),
							width: Math.floor(IceCap.util.Handler.getColSize()),
							height: 1
						});

						var b_intersect = false;

						Ext.Array.each(a_inputs, function(i_field) {

							var o_bound = i_field.el.dom.getBoundingClientRect();

							var o_rect = Ext.apply({}, {
								x: i_field.getLocalX(),
								y: i_field.getLocalY(),
								width: o_bound.width,
								height: o_bound.height
							});

							if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
								b_intersect = true;
								i_field.focus(true, 10);
								return false;
							}
						});

						if (!b_intersect) {
							i_cursor.moveCursor(o_position);
						}

						i_self.setCurrentPosition(o_position);
					}
				}
			},
			{
				key: Ext.event.Event.RIGHT,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;

					if (!i_event.target.type) {

						i_event.stopEvent();

						var i_cursor = i_self.getCursor();
						var o_position = i_self.getCurrentPosition();
						var o_inputData = i_self.getInputData();
						var o_window = o_inputData.window;

						var a_inputs = i_self.query("field[focusable]");

						o_position.col = o_position.col + 1;

						if (o_position.col > o_inputData.width) {
							o_position.col = o_inputData.width;
						}

						var o_box = Ext.apply({
							x: IceCap.util.Handler.getX(o_position.col - 1),
							y: IceCap.util.Handler.getY(o_position.lin),
							width: Math.floor(IceCap.util.Handler.getColSize()),
							height: 1
						});

						var b_intersect = false;

						Ext.Array.each(a_inputs, function(i_field) {

							var o_bound = i_field.el.dom.getBoundingClientRect();

							var o_rect = Ext.apply({}, {
								x: i_field.getLocalX(),
								y: i_field.getLocalY(),
								width: o_bound.width,
								height: o_bound.height
							});

							if (!Ext.draw.Draw.isBBoxIntersect(o_box, o_rect)) {
								b_intersect = true;
								i_field.focus(true, 10);
								return false;
							}
						});

						if (!b_intersect) {
							i_cursor.moveCursor(o_position);
						}

						i_self.setCurrentPosition(o_position);
					}
				}
			},
			{
				key: Ext.event.Event.TAB,
				shift: false,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doNavigationKey(1, true, i_event);
				}
			},
			{
				key: Ext.event.Event.TAB,
				shift: true,
				fn: function(n_key, i_event) {

					var i_key = this;
					var i_self = i_key.target.component;
					i_self.doNavigationKey(0, true, i_event);
				}
			}
		];

		a_bindings = a_bindings.concat(i_self.getFKeys());

		var i_keyMap = Ext.create("Ext.util.KeyMap", {
			target: i_self.getEl(),
			binding: a_bindings
		});
	},

	getFKeys: function() {

		var i_self = this;

		var a_keys = [
			{
				key: Ext.event.Event.F1,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F1", i_event);
				}
			},
			{
				key: Ext.event.Event.F2,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F2", i_event);
				}
			},
			{
				key: Ext.event.Event.F3,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F3", i_event);
				}
			},
			{
				key: Ext.event.Event.F4,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F4", i_event);
				}
			},
			{
				key: Ext.event.Event.F5,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F5", i_event);
				}
			},
			{
				key: Ext.event.Event.F6,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F6", i_event);
				}
			},
			{
				key: Ext.event.Event.F7,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F7", i_event);
				}
			},
			{
				key: Ext.event.Event.F8,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F8", i_event);
				}
			},
			{
				key: Ext.event.Event.F9,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F9", i_event);
				}
			},
			{
				key: Ext.event.Event.F10,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F10", i_event);
				}
			},
			{
				key: Ext.event.Event.F11,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F11", i_event);
				}
			},
			{
				key: Ext.event.Event.F12,
				shift: false,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F12", i_event);
				}
			}
		];

		a_keys = a_keys.concat(i_self.getFShiftKeys());

		return a_keys;
	},

	getFShiftKeys: function() {

		var i_self = this;

		var a_keys = [
			{
				key: Ext.event.Event.F1,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F13", i_event);
				}
			},
			{
				key: Ext.event.Event.F2,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F14", i_event);
				}
			},
			{
				key: Ext.event.Event.F3,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F15", i_event);
				}
			},
			{
				key: Ext.event.Event.F4,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F16", i_event);
				}
			},
			{
				key: Ext.event.Event.F5,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F17", i_event);
				}
			},
			{
				key: Ext.event.Event.F6,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F18", i_event);
				}
			},
			{
				key: Ext.event.Event.F7,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F19", i_event);
				}
			},
			{
				key: Ext.event.Event.F8,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F20", i_event);
				}
			},
			{
				key: Ext.event.Event.F9,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F21", i_event);
				}
			},
			{
				key: Ext.event.Event.F10,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F22", i_event);
				}
			},
			{
				key: Ext.event.Event.F11,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F23", i_event);
				}
			},
			{
				key: Ext.event.Event.F12,
				shift: true,
				fn: function(n_key, i_event) {

					i_self.doKeyEvent("F24", i_event);
				}
			}
		];

		return a_keys;
	},

	createCursor: function() {

		var i_self = this;
		var o_inputData = i_self.getInputData();

		var i_cursor = Ext.widget("component", {
			cls: ["iceCap-cursor", i_self.getTheme()].filter(Boolean).join("-"),
			autoEl: {
				tag: "div",
				style: {
					"border": "1px solid red;",
					"position": "absolute !important;",
					"width": IceCap.util.Handler.getColSize() + "px !important;"
				}
			},
			listeners: {
				render: {
					fn: function(i_item) {
						i_item.hide();
					}
				},
				afterrender: {
					fn: function(i_cursor) {

						var i_content = i_self.getContent();

						var a_fields = i_content.query("field[focusable]");

						if (a_fields.length === 0) {

							i_cursor.show();

							i_cursor.moveCursor({
								col: o_inputData.csrCol,
								lin: o_inputData.csrLin
							});
						}
					}
				}
			},
			moveCursor: function(o_position) {

				var i_cursor = this;
				var n_col = o_position.col;

				i_cursor.setPosition({
					x: Math.ceil(IceCap.util.Handler.getX(o_position.col - 1) + (IceCap.util.Handler.getColSize() / 2)),
					y: IceCap.util.Handler.getY(o_position.lin + 1) - 5
				});
			}
		});

		i_self.setCursor(i_cursor);

		return i_cursor;
	},

	findFocus: function() {

		var i_self = this;
		var i_main = i_self.getMain();
		var i_content = i_self.getContent();

		var a_fields = i_content.query("field[focusable]");

		if (a_fields.length > 0) {

			var i_field = a_fields[0];
			i_field.focus(true, 10);
		}
		else {
			i_main.focus(false, 10);
		}
	},

	doTimer: function() {

		var i_self = this;

		var i_timer = i_self.getTimer();
		if (!i_timer) {
			i_timer = new Ext.util.DelayedTask(function() {
				i_self.setLoading(true);
			});

			i_self.setTimer(i_timer);

			i_timer.delay(1000);
		}
	},

	cancelTimer: function() {

		var i_self = this;

		var i_timer = i_self.getTimer();

		if (i_timer) {
			i_timer.cancel();
			i_self.setTimer(null);
		}
	},

	onError: function(o_inputData) {

		var i_self = this;

		Ext.Msg.show({
			title: "Server Message",
			msg: o_inputData.msgBox.text,
			icon: Ext.MessageBox.INFO,
			buttons: Ext.MessageBox.OK,
			fn: function(btn) {
				i_self.findFocus();
			}
		});
	},

	updateMessage: function(o_inputData) {

		var i_self = this;
		var i_statusbar = i_self.getStatusBar();

		var a_messages = Ext.Array.from(o_inputData.message);

		if (a_messages.length > 0) {
			Ext.Array.each(a_messages, function(o_message) {
				i_statusbar.setText(o_message.text);
			});
		}
	},

	applyFFW: function(o_config) {

		var i_self = this;
		var s_hex = o_config.ffw;
		var b_fixed = IceCap.util.Handler.getFixed();

		var o_field = {
			xtype: "textfield"
		};

		var o_fieldStyle = {
			font: "normal " + IceCap.util.Handler.getTextSize() + "px Segoe UI,Segoe,DejaVu Sans,Trebuchet MS,Verdana,sans-serif"
		};

		if (b_fixed) {

			Ext.apply(o_fieldStyle, {
				font: "normal " + IceCap.util.Handler.getTextSize() + "px Lucida Console, Courier New, monospace"
			});
		}

		if (o_config.ta) {

			Ext.apply(o_fieldStyle, {
				"text-align": o_config.ta
			});
		}

		if (s_hex) {

			var n_hex = parseInt(s_hex);

			var n_sanHex = IceCap.util.Handler.createIndicators(s_hex);

			if (n_sanHex & IceCap.util.Handler.FFW.BYPASS) {

				Ext.apply(o_field, {
					readOnly: true
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.ALPHA_ONLY) {

				Ext.apply(o_field, {
					maskRe: new RegExp("[a-z A-Z ,.-]")
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.NUMERIC_ONLY) {

				Ext.apply(o_field, {
					xtype: "numberfield",
					fieldStyle: o_fieldStyle,
					allowDecimals: false,
					hideTrigger: true,
					minValue: 0
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.DIGITS_ONLY) {

				Ext.apply(o_field, {
					maskRe: new RegExp("0-9")
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.AUTO_ENTER) {

				// THIS WE DONT NEED IN THE MODERN WORLD...

				// Ext.apply(o_field, {
				// 	listeners: {
				// 		blur: {
				// 			fn: function(i_field) {
				// 				i_self.doKeyEvent("ENTER");
				// 			}
				// 		}
				// 	}
				// });
			}

			if (n_sanHex & IceCap.util.Handler.FFW.MONOCASE) {

				Ext.apply(o_fieldStyle, {
					"text-transform": "uppercase"
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.MAND_ENTER) {

				Ext.apply(o_field, {
					allowBlank: false
				});
			}

			if (o_config.atr == "27" && n_sanHex & IceCap.util.Handler.FFW.RA_READONLY) {

				Ext.apply(o_field, {
					hidden: true,
					disabled: true
				});
			}

			if (n_sanHex & IceCap.util.Handler.FFW.RA_READONLY || (n_hex & 0x0700) == 0x0600) {

				Ext.apply(o_field, {
					readOnly: true
				});
			}
		}

		Ext.apply(o_field, {
			fieldStyle: o_fieldStyle
		});

		return o_field;
	}
});
