Ext.define("Ext.ux.grid.filter.Toolbar", {

	extend: "Ext.toolbar.Toolbar",

	alias: "widget.filterbar",

	dock: "top",

	height: 40,

	layout: {
		type: "hbox",
		"align": "center"
	},

	config: {
		defaultFilter: "",
		allowFilterMenu: true,
		allowMenu: true,
		menu: null,
		buttonReset: null,
		grid: null
	},

	defaults: {
		ui: "filter",
		height: 30
	},

	border: false,

	ui: "filter",

	listeners : {
		afterFilter: {
			fn: function(i_self, n_filters) {

				var i_buttonReset = i_self.getButtonReset();

				i_buttonReset[n_filters ? "show" : "hide"]();
			}
		}
	},

	initComponent: function() {

		var i_self = this;

		i_self.plugins = i_self.createPlugins();

		i_self.callParent(arguments);

		i_self.add(i_self.createItems());

		i_self.enableBubble([
			"afterFilter"
		]);

		return i_self;
	},

	createItems: function() {

		var i_self = this;
		var a_items = [];

		if (i_self.getAllowMenu()) {
			a_items.push(i_self.createMenu());
		}

		var i_buttonReset = Ext.widget("button", {
			itemId: "button-clear",
			iconAlign: "right",
			text: ip2.i18n({
				da: "Nulstil",
				en: "Reset"
			}),
			iconCls: "pf-navigate_cross",
			reorderable: false,
			hidden: true,
			handler: function () {
				i_self.clearFilters();
			}
		});

		a_items.push(i_buttonReset);
		a_items.push({
			xtype: "tbseparator",
			reorderable: false
		});

		i_self.setButtonReset(i_buttonReset);

		return a_items;
	},

	createMenu: function() {

		var i_self = this;

		var i_splitbutton = Ext.widget("filtermenu", {
			reorderable: false,
			arrowVisible: false,
			iconAlign: "right",
			text: ip2.i18n({
				da: "Filter",
				en: "Filter"
			}),
			iconCls: "pf-navigate_close",
			toolBar: i_self,
			itemId: "menuFilter",
			defaultFilter: i_self.getDefaultFilter()
		});
		i_self.menu = i_splitbutton;
		return i_splitbutton;
	},

	getFilterByDataIndex: function(s_dataIndex) {

		var i_self = this;
		return i_self.query("splitbutton[dataIndex=" + s_dataIndex + "]")[0];
	},

	getFilters: function() {

		var i_self = this;
		return i_self.query("splitbutton[isFilter=true]");
	},

	clearFilters: function() {

		var i_self = this;
		var i_grid = i_self.grid;
		var i_store = i_grid.getStore();
		var i_proxy = i_store.getProxy();
		var o_extraParams = i_proxy.getExtraParams();
		var a_filters = i_self.getFilters();

		Ext.Array.each(a_filters, function(i_button) {
			if (i_button.overRuleable === null) {
				i_self.remove(i_button);
			}
			else {
				if (i_button.overRuleable) {
					i_self.remove(i_button);
				}
			}
		});

		a_filters = i_self.getFilters();

		delete o_extraParams.where;
		delete o_extraParams.sort;

		var o_sorters = i_store.getSorters();

		o_sorters.removeAll();

		var a_sorters = [];

		Ext.Array.each(a_filters, function(i_filter) {
			var o_sort = i_filter.getSortInfo();
			a_sorters.push(o_sort);
		});

		if (a_sorters.length > 0) {
			o_sorters.add(a_sorters);
		}
		else {

			if (i_store.isTreeStore) {
				var i_tree = i_store.ownerTree;

				var i_view = i_tree.getView();


				if (i_view.body.dom) {
					i_view.body.translate(0, 0, 0);
				}

				if (i_view.bufferedRenderer) {
					i_view.bufferedRenderer.onStoreClear();
				}
			}

			if (Ext.isFunction(i_store.clearAndLoad)) {
				i_store.clearAndLoad();
			}
			else {
				i_store.load();
			}
		}

		if (i_self.allowMenu) {
			i_self.menu.reset();
		}

		i_self.fireEvent("afterFilter", i_self, a_filters.length);
	},

	clearStatus: function(i_menu) {
		var i_self = this;
		var a_items = i_menu.items.items;
		Ext.Array.each(a_items, function(i_item) {
			if (i_item.menu != null) {
				i_item.setIconCls("");
				i_self.clearStatus(i_item.menu);
			}
			else {
				i_item.setIconCls("");
			}
		});
	},

	clearFiltersNoReload: function() {

		var i_self = this;
		var i_grid = i_self.ownerCt;
		var i_store = i_grid.getStore();
		var a_filters = i_self.getFilters();

		Ext.Array.each(a_filters, function(i_button) {
			if (i_button.overRuleable == null) {
				i_self.remove(i_button);
			}
			else {
				if (i_button.overRuleable) {
					i_self.remove(i_button);
				}
			}
		});

		var i_proxy = i_store.getProxy();
		var o_extraParams = i_proxy.getExtraParams();

		delete o_extraParams.where;
		delete o_extraParams.sort;

		i_self.fireEvent("afterFilter", i_self, a_filters.length);
	},

	createWhere: function() {

		var i_self = this;
		var i_grid = i_self.ownerCt;
		var i_store = i_grid.getStore();
		var i_proxy = i_store.getProxy();
		var o_extraParams = i_proxy.getExtraParams();
		var a_filters = i_self.getFilters();
		var s_where = "";
		var n_whereAdded = 0;

		Ext.Array.each(a_filters, function(i_filter) {
			var s_value = i_filter.getFilterValue();
			if (s_value) {
				if (n_whereAdded === 0) {
					s_where += s_value;
					n_whereAdded++;
				}
				else {
					s_where += " AND " + s_value;
				}
			}
		});

		o_extraParams.where = s_where;
	},

	getWhere: function() {

		var i_self = this;
		var a_filters = i_self.getFilters();
		var s_where = "";
		var n_whereAdded = 0;

		Ext.Array.each(a_filters, function(i_filter, n_index) {
			var s_value = i_filter.getFilterValue();
			if (s_value) {
				if (n_whereAdded === 0) {
					s_where += s_value;
					n_whereAdded++;
				}
				else {
					s_where += " AND " + s_value;
				}
			}
		});
		return s_where;
	},

	getFilterConfig: function() {

		var i_self = this;
		var a_filters = i_self.getFilters();
		var a_configs = [];

		Ext.Array.each(a_filters, function(i_button) {

			var i_config = i_button.getConfig();
			var o_sortInfo = i_button.getSortInfo();
			var a_checkbox = [];
			var a_values = [];

			Ext.Array.each(i_config.checkboxes, function(i_checkbox) {
				a_checkbox.push(i_checkbox.checked);
			});

			Ext.Array.each(i_config.fields, function(i_field) {

				if (i_field.fieldtype != "bt") {
					var value = i_field.getValue() || "";
					a_values.push(value);
				}
				else {
					var a_items = i_field.items.items;
					var i_first = a_items[0];
					var i_second = a_items[1];
					var o_value = {
						first: i_first.getValue() || "",
						second: i_second.getValue() || ""
					};
					a_values.push(o_value);
				}
			});

			var o_config = Ext.apply({}, {
				dataIndex: i_button.dataIndex,
				dataType: i_button.dataType,
				dataDateType: i_button.dataDateType || "",
				isString: i_button.isString || false,
				multiSelect: i_button.multiSelect || false,
				sortDirection: o_sortInfo.direction,
				overRuleable: true,
				dmd: i_button.dmd || "",
				checkboxes: a_checkbox,
				fieldValues: a_values,
				notValue: i_button.getNot(),
				text: i_button.text,
				values: i_button.values || []
			});

			a_configs.push(o_config);
		});
		return a_configs;
	},

	applyFilters: function(b_reset) {

		var i_self = this;
		var i_grid = i_self.grid;
		var i_store = i_grid.getStore();
		var i_proxy = i_store.getProxy();
		var o_extraParams = i_proxy.getExtraParams();
		var a_filters = i_self.getFilters();
		var s_where = "";
		var o_sorters = i_store.getSorters();
		var a_sorters = [];

		var a_where = [];
		var b_needSort =  a_filters.length != o_sorters.getRange().length;

		if (!b_reset) {

			Ext.Array.each(a_filters, function (i_filter) {

				var b_found = false;
				var s_value = i_filter.getFilterValue();
				var o_sort = i_filter.getSortInfo();

				if (s_value) {
					a_where.push(s_value);
				}

				Ext.Array.each(o_sorters.getRange(), function (i_sorter) {

					if (i_sorter.getProperty() == o_sort.property) {
						b_found = true;

						if (i_sorter.getDirection() != o_sort.direction) {
							i_sorter.setDirection(o_sort.direction);
							b_needSort = true;
						}
					}
				});

				if (!b_found) {
					a_sorters.push(o_sort);
				}
			});
		}
		else {
			Ext.Array.each(a_filters, function (i_filter) {

				var s_value = i_filter.getFilterValue();
				var o_sort = i_filter.getSortInfo();

				if (s_value) {
					a_where.push(s_value);
				}

				a_sorters.push(o_sort);
			});

			o_sorters.removeAll();
		}

		s_where = a_where.join(" AND ");

		o_extraParams.where = s_where;

		if (i_store.isTreeStore) {
			var i_tree = i_store.ownerTree;

			var i_view = i_tree.getView();

			if (i_view.body.dom) {
				i_view.body.translate(0, 0, 0);
			}

			if (i_view.bufferedRenderer) {
				i_view.bufferedRenderer.onStoreClear();
			}
		}

		if (a_sorters.length > 0) {
			o_sorters.add(a_sorters);
		}
		else {
			if (b_needSort || !Ext.isEmpty(s_where)) {
				i_store.applySorters(o_sorters.getRange(), o_sorters);
			}
		}

		i_self.fireEvent("afterFilter", i_self, a_filters.length);
	},

	removeFilter: function(i_filter) {

		var i_self = this;
		i_self.remove(i_filter);

		var i_grid = i_self.ownerCt;
		var i_store = i_grid.getStore();
		var o_sorters = i_store.getSorters();
		var o_sort = i_filter.getSortInfo();
		var a_filters = i_self.getFilters();

		var a_removed = o_sorters.items.filter(function(i_sorter) {
			var b_found = false;
			if (i_sorter.getProperty() == o_sort.property) {
				b_found = true;
			}
			return b_found;
		});

		if (a_removed.length > 0 && a_filters.length > 0) {
			o_sorters.remove(a_removed);
		}

		i_self.createWhere();

		if (a_filters.length === 0) {
			i_self.clearFilters();
		}

		i_self.fireEvent("afterFilter", i_self, a_filters.length);
	},

	sortChange: function(i_column) {

		var i_self = this;
		var a_filters = i_self.getFilters();
		var b_found = false;
		var i_plugin = i_self.getPlugin("plugin-drop");

		Ext.Array.each(a_filters, function(i_filter) {

			if (i_filter.dataIndex == i_column.dataIndex ||
				i_filter.sortProperty == i_column.dataIndex ||
				i_filter.dataIndex == i_column.mapping
			) {

				var o_sort = i_filter.getSortInfo();
				b_found = true;
				if (i_column.sortState !== null) {
					if (o_sort.direction != i_column.sortState) {
						i_filter.changeSort();
					}
				}
			}
		});

		if (!b_found) {

			i_plugin.createItem({
				header: i_column
			});
		}
	},

	createPlugins: function() {

		var i_self = this;
		var a_plugins = [
			i_self.createReorderplugin(),
			i_self.createDropPlugin()
		];
		return a_plugins;
	},

	createReorderplugin: function() {

		var i_self = this;
		var o_reorder = {
			ptype: "boxreorder",
			removeOnDrop: function(element, i_button) {
				var i_dropped = Ext.getCmp(element.id);
				var b_remove = false;
				if (i_dropped && i_dropped.itemId == "button-clear") {
					b_remove = true;
					i_self.removeFilter(i_button);
				}
				return b_remove;
			},
			listeners: {
				Drop: {
					fn: function(i_self, i_toolbar, component, startIdx, idx) {
						if (startIdx != idx) {
							i_toolbar.applyFilters(true);
						}
					}
				}
			}
		};
		return o_reorder;
	},

	createDropPlugin: function() {

		var i_self = this;
		var o_dropplugin = {
			pluginId: "plugin-drop",
			ptype: "toolbardroppable",
			canDrop: function(ddSource, event, i_data) {

				var o_header = i_data.header;

				if (o_header) {

					if (!o_header.hasOwnProperty("filterable")) {
						o_header.filterable = true;
					}

					if (o_header.filterable && o_header.sortable) {
						var a_filters = i_self.getFilters();
						var b_result = true;
						Ext.Array.each(a_filters, function(o_filter) {
							if (o_filter.dataIndex == o_header.dataIndex) {
								b_result = false;
							}
						});
						return b_result;
					}
					else {
						return false;
					}
				}
				else {
					return false;
				}
			},
			createItem: function(i_data) {

				var i_grid = i_self.grid;
				var b_allowFilterMenu = i_self.getAllowFilterMenu();
				var o_dmdConfig = i_grid.getModelConfig();
				var i_header = i_data.header;
				var i_reorderer = i_grid.reorderer;
				var s_type = ip2.dbtypes2js(i_header);
				var s_datetype = "datetime";
				var o_dmd = {};
				var b_string = false;
				var b_mulitiSelect = false;
				var b_like = false;
				var s_sortProperty = i_header.sortProperty;
				var b_useRaw = i_header.useRaw || false;

				var o_dmdInfo = ip2.dmd.getInfo({
					dmd: o_dmdConfig.dmd,
					entity: o_dmdConfig.entityName,
					view: o_dmdConfig.uiName,
					context: "grid"
				});

				Ext.Array.each(o_dmdInfo.view.columns, function(o_column) {
					if (o_column.name == i_header.dataIndex) {
						i_header.xpd = o_column.xpd;
					}
				});

				if (s_type == "int") {
					s_type = "number";
				}

				if (i_header.xpd && !i_header["enum"] && !i_header.filterXpd) {
					var o_xpdInfo = ip2.getFieldXpdInfo(i_header.dataIndex, o_dmdInfo.entity, i_header);
					if (!o_xpdInfo) {
						var o_xpd = ip2.resource.get(i_header.xpd + ".xpd");
						var o_xpdProp = o_xpd.properties[i_header.xpdProp];
						o_xpdInfo = {
							xpd: o_xpd,
							definition: o_xpdProp
						};
					}
					var o_definition = o_xpdInfo.definition;
					if (o_definition) {
						if (o_definition.dmd) {
							o_dmd = o_definition.dmd;
							o_dmd.view = o_dmdConfig.uiName;
							s_type = "entity";
						}
						else if (o_definition.context) {
							if (o_definition.context.grid.uitype) {
								s_type = o_definition.context.grid.uitype;
							}
						}
						else if (o_definition.type == "isotimestamp") {
							s_type = "date";
						}
						else if (o_definition.type == "date") {
							s_type = "date";
							s_datetype = "date";
						}
						else {
							var s_db = o_definition.type || "";
							if (s_db.indexOf("varchar") != -1 || s_db.indexOf("display") != -1) {
								s_type = "string";
							}
							else if (o_definition.type == "boolean") {
								s_type = o_definition.type;
							}
							else {
								var o_xpd = o_xpdInfo.xpd;
								var a_keys = Object.keys(o_xpd.collections);
								var a_values = [];
								Ext.Array.each(a_keys, function(s_key) {
									if (s_key != "all") {
										var o_collection = o_xpd.collections[s_key];
										var o_value = {
											key: o_collection.id,
											value: ip2.xpd.translate(o_xpd, o_collection.title)
										};
										a_values.push(o_value);
									}
								});
								a_values.sort(function(o_first, o_second) {
									var n_a = (Ext.isNumber(o_first.value) ? o_first.value : 0);
									var n_b = (Ext.isNumber(o_second.value) ? o_second.value : 0);

									var n_min = Math.min(n_a, n_b);

									return n_min;
								});
								s_type = "enum";
							}
						}
					}
				}
				else if (i_header.filterXpd) {
					var o_column = {
						xpd: i_header.filterXpd
					};
					var o_xpdInfo = ip2.getFieldXpdInfo(i_header.supportProp, o_dmdInfo.entity, o_column);
					if (!o_xpdInfo) {
						var o_xpd = ip2.resource.get(i_header.xpd + ".xpd");
						var o_xpdProp = o_xpd.properties[i_header.xpdProp];
						o_xpdInfo = {
							xpd: o_xpd,
							definition: o_xpdProp
						};
					}
					var o_definition = o_xpdInfo.definition;
					if (o_definition.dmd) {
						o_dmd = o_definition.dmd;

						Ext.applyIf(o_dmd, {
							view: "portfolio"
						});

						s_type = "entity";
					}
					else if (o_definition.context) {
						if (o_definition.context.grid.uitype) {
							s_type = o_definition.context.grid.uitype;
						}
					}
					else if (o_definition.type == "isotimestamp") {
						s_type = "date";
					}
					else if (o_definition.type == "date") {
						s_type = "date";
						s_datetype = "date";
					}
					else {
						var s_db = o_definition.type || "";
						if (s_db.indexOf("varchar") != -1 || s_db.indexOf("display") != -1) {
							s_type = "string";
						}
						else if (o_definition.type == "boolean") {
							s_type = o_definition.type;
						}
						else {
							var o_xpd = o_xpdInfo.xpd;
							var a_keys = Object.keys(o_xpd.collections);
							var a_values = [];
							Ext.Array.each(a_keys, function(s_key) {
								if (s_key != "all") {
									var o_collection = o_xpd.collections[s_key];
									var o_value = {
										key: o_collection.id,
										value: ip2.xpd.translate(o_xpd, o_collection.title)
									};
									a_values.push(o_value);
								}
							});
							a_values.sort(function(o_first, o_second) {
								var n_a = (Ext.isNumber(o_first.value) ? o_first.value : 0);
								var n_b = (Ext.isNumber(o_second.value) ? o_second.value : 0);

								var n_min = Math.min(n_a, n_b);

								return n_min;
							});
							s_type = "enum";
						}
					}
				}
				else if (i_header["enum"]) {
					var o_ns = ip2.resource.get("adm.ns");
					var o_enums = o_ns.enums[i_header["enum"]].values;
					var a_keys = Object.keys(o_enums);
					var a_values = [];
					Ext.Array.each(a_keys, function(s_key) {
						var o_enum = o_enums[s_key];
						var o_value = {
							key: s_key,
							value: ip2.i18n(o_enum)
						};
						a_values.push(o_value);
					});
					b_string = true;
					s_type = "enum";
					if (i_header.xpd) {
						var o_xpdInfo = ip2.getFieldXpdInfo(i_header.dataIndex, o_dmdInfo.entity, i_header);
						var o_definition = o_xpdInfo.definition;
						b_mulitiSelect = o_definition.multiSelect || i_header.multiSelect != undefined ? i_header.multiSelect : false;
						b_like = o_definition.useLike || i_header.useLike != undefined ? i_header.useLike : false;
					}
				}

				else if (i_header.uitype != "") {
					if (i_header.uitype == "boolean") {
						s_type = i_header.uitype;
						b_string = true;
					}
					else if (i_header.uitype == "isotimestamp") {
						s_type = "date";
					}
					else if (i_header.uitype == "array") {
						s_type = i_header.uitype;
						o_dmd = {
							file: i_header.dmd,
							entity: i_header.entity,
							view: i_header.view || "portfolio"
						};
					}
				}

				var s_index = i_header.dataIndex;

				if (i_header.filter) {
					var o_filter = i_header.filter;
					if (o_filter.dmd && o_filter.entity) {
						o_dmd = Ext.apply({}, {
							file: o_filter.dmd,
							entity: o_filter.entity,
							view: o_filter.view || "portfolio"
						});
						s_type = "entity";
					}

					if (o_filter.hasOwnProperty("dataType")) {
						s_type = o_filter.dataType || "string";
					}

					if (s_type === "enum") {

						var o_ns = ip2.resource.get("adm.ns");
						var o_enums = o_ns.enums[o_filter["enum"]].values;

						Ext.Object.each(o_enums, function(s_key, value) {
							var o_value = {
								key: s_key,
								value: ip2.i18n(o_enum)
							};
							a_values.push(o_value);
						});
						b_string = true;
						s_type = "enum";
					}

					if (o_filter.hasOwnProperty("dataIndex")) {
						s_index = o_filter.dataIndex;
					}

					if (o_filter.hasOwnProperty("sortProperty")) {
						s_sortProperty = o_filter.sortProperty;
					}

					if (o_filter.hasOwnProperty("multiSelect")) {
						b_mulitiSelect = o_filter.multiSelect;
					}

					if (o_filter.hasOwnProperty("isString")) {
						b_string = o_filter.isString;
					}

					if (o_filter.hasOwnProperty("useLike")) {
						b_like = o_filter.useLike;
					}

					if (o_filter.hasOwnProperty("values")) {
						a_values = o_filter.values || [];
					}

					if (o_filter.hasOwnProperty("useRaw")) {
						b_useRaw = o_filter.useRaw || false;
					}
				}

				if (i_reorderer) {
					i_reorderer.dropZone.invalidateDrop();
				}

				if (i_header.supportProp) {
					s_index = i_header.supportProp;
				}
				if (i_header.supportIndex) {
					s_index = i_header.supportIndex;
				}
				if (i_header.mapping) {
					s_index = i_header.mapping;
				}

				var o_config = {
					text: i_header.text,
					dataIndex: s_index,
					dataType: s_type,
					dataDateType: s_datetype,
					sortProperty: s_sortProperty,
					isString: b_string,
					multiSelect: b_mulitiSelect,
					sortDirection: i_header.sortState || "ASC",
					overRuleable: true,
					allowMenu: b_allowFilterMenu,
					useLike: b_like,
					useRaw: b_useRaw,
					values: a_values,
					dmd: o_dmd,
					applyFn: function() {
						i_self.applyFilters();
					},
					removeFn: function(i_filter) {
						i_self.removeFilter(i_filter);
					}
				};

				var i_filter = Ext.ux.grid.filter.util.createFilter(o_config);

				i_self.add(i_filter);
				i_self.applyFilters();
			}
		};
		return o_dropplugin;
	},

	loadFilters: function(a_filters) {

		var i_self = this;

		i_self.clearFiltersNoReload();

		Ext.Array.each(a_filters, function(o_config) {

			var a_values = o_config.fieldValues;
			var a_checkbox = o_config.checkboxes;
			var b_not = o_config.notValue || false;

			o_config.applyFn = function() {
				i_self.applyFilters();
			};

			o_config.removeFn = function(i_filter) {
				i_self.removeFilter(i_filter);
			};

			/* REMOVE UNUSED PROPERTIES SO THEY DONT POLLUTE THE FILTER */
			delete o_config.checkboxes;
			delete o_config.fieldValues;
			delete o_config.notValue;

			var i_filter = Ext.ux.grid.filter.util.createFilter(o_config);
			i_filter.setNot(b_not);

			/* ADD PROPERTIES SO WE DONT LOSE THEM FOR FURTHER USAGES */
			o_config.checkboxes = a_checkbox;
			o_config.fieldValues = a_values;
			o_config.notValue = b_not;

			var o_filterConfig = i_filter.getConfig();
			var a_filtercheckboxs = o_filterConfig.checkboxes;
			var a_filterfields = o_filterConfig.fields;

			Ext.Array.each(a_filtercheckboxs, function(i_checkbox, n_index) {

				var i_field = a_filterfields[n_index];
				var value = a_values[n_index];

				i_checkbox.setValue(a_checkbox[n_index]);

				if (i_field.fieldtype != "bt") {
					if (i_checkbox.dataType == "enum") {
						var i_store = i_field.getStore();
						i_store.on({
							load: {
								fn: function(store, records) {
									i_field.setValue(value);
								}
							}
						});
					}
					else {
						i_field.setValue(value);
					}
				}
				else {

					var a_items = i_field.items.items;

					var i_first = a_items[0];
					var i_second = a_items[1];

					i_first.setValue(value.first);
					i_second.setValue(value.second);
				}
			});
			i_self.add(i_filter);
		});

		i_self.applyFilters();
	}
});
