/**
 * SystemManager für ein System. Der Manager behandelt die Anfrage von Daten
 * und die Zuweisung in die Kategorien.
 * 
 * 
 */
var SearchalyzrSystemManager = Class.create({
	/**
	 * Erzeugt einen neuen SystemManager.
	 * 
	 * @param searchalyzr [Searchalyzr]
	 * 
	 * @param system [Hash] 
	 */
	initialize: function(searchalyzr, system) {
		/**
		 * Searchalyzr-Instanz
		 */
		this.searchalyzr = searchalyzr;
		/**
		 * System-Model, das von diesem Manager verwaltet wird.
		 */
		this.system = system;
		/**
		 * Kategorien-Manager.
		 * 
		 * @type Hash: Category-ID => SearchalyzrDataRepresentationManager
		 */
		this.categories = {};
		
		system.setManager(this);
	},
	
	/**
	 * Führt eine Anfrage mit den Parametern aus.
	 */
	getSearchResult: function(searchParams) {
		var self = this;
		searchParams = self.searchalyzr.deepClone(searchParams);	// damit das Original unangetastet bleibt

		if (self.system.columns && (!searchParams.columns || !searchParams.columns.length)) {
			searchParams.columns = self.system.columns;
		}
		
		self.searchalyzr.builder.setTabLoading(self.system.title);
		
		if (self.system.searchResultFilter) {
			searchParams['searchQuery']['terms'].push(self.system.searchResultFilter);
		}
		
		var params = {
			aktion: 'getSearchResult',
			searchParams: Object.toJSON(searchParams),
			searchSystemType: self.system.getId(),
			searchSystemUrl: self.system.getURL()
		};
		if (self.searchalyzr.session) {
			params.session = self.searchalyzr.session;
		}
		new Ajax.Request(self.searchalyzr.url, {
			method: 'post',
			parameters: params,
			evalJSON: 'force',
			onSuccess: function(transport) {
				var data = transport.responseJSON;
				var completeCount = 0;
				if (data.result && data.result.resultCategories) {
					var categories = Object.keys(self.categories);
					var visibles = [];
					// Gehe durch die Kategorien und aktualisiere diese.
					data.result.resultCategories.each(function(category) {
						try {
							categories = categories.without(category.id);
							self.updateCategory(category.id, category.offset, category);
							Element.extend(self.categories[category.id]);
							if (self.categories[category.id].isVisible()) {
								visibles.push(self.categories[category.id]);
								completeCount += category.totalHits;
							}
						}
						catch (e) {
							alert(Object.toJSON(e));
						}
					});
					
					categories.each(function(category) {
						self.hideCategory(category);
					});
					
					if (visibles.length > 1) {
						visibles.each(function(category) {
							category.setUniq(false);
						});
					} else {
						visibles.each(function(category) {
							if (category.isVisible()) {
								category.setUniq(true);
							}
						});
					}
					self.searchalyzr.builder.hideErrorMessage(self.system.errorMessage);
				} else {
					var template = new Template('Could not fetch search result for system "#{system}"\n' +
							'Recieved unexpected response:\n#{data}');
					var fields = { system: self.system.getLabel(), data: Object.toJSON(data) };
					var message = template.evaluate(fields);
					self.searchalyzr.builder.showErrorMessage(self.system.errorMessage, message);
				}
				
				self.searchalyzr.builder.updateTabCount(self.system.title, completeCount);
				if (completeCount > 0) {
					self.searchalyzr.builder.hideEmptyIndicator(self.system.emptyIndicator);
				} else {
					self.searchalyzr.builder.showEmptyIndicator(self.system.emptyIndicator);
				}
			},
			onFailure: function(transport) {
				var template = new Template('Could not fetch search result for system "#{system}"\n' +
					'Error in Query: #{url} - #{query}');
				var fields = { system: self.system.getLabel(), url: self.searchalyzr.url, query: Object.toJSON(params) };
				var message = template.evaluate(fields);
				self.searchalyzr.builder.showErrorMessage(self.system.errorMessage, message);
			}
		});
	},
	
	/**
	 * Hier wird NICHTS visualisiert, sondern es werden nur die Daten empfangen.
	 */
	getSearchResultData: function(searchParams) {
		var self = this;

		var params = {
			aktion: 'getSearchResult',
			searchParams: Object.toJSON(searchParams),
			searchSystemType: self.system.getId(),
			searchSystemUrl: self.system.getURL()
		};
		new Ajax.Request(self.searchalyzr.url, {
			method: 'post',
			parameters: params,
			evalJSON: 'force',
			onSuccess: function(transport) {
				var data = transport.responseJSON;
				if (data.result && data.result.resultCategories) {
					self.searchalyzr.builder.handleData(data.result.resultCategories);
				} else {
					var template = new Template('Could not fetch search result for system "#{system}"\n' +
							'Recieved unexpected response:\n#{data}');
					var fields = { system: self.system.getLabel(), data: Object.toJSON(data) };
					alert(template.evaluate(fields));
				}
			},
			onFailure: function(transport) {
				var template = new Template('Could not fetch search result for system "#{system}"\n' +
					'Error in Query: #{url} - #{query}');
				var fields = { system: self.system.getLabel(), url: self.searchalyzr.url, query: Object.toJSON(params) };
				alert(template.evaluate(fields));
			}
		});
	},

	getParameterConfig: function(stateParams) {
		var self = this;
		
		var params = {
			aktion: 'getParameterConfig',
			stateParams: Object.toJSON(stateParams),
			searchSystemType: self.system.getId(),
			searchSystemUrl: self.system.getURL()
		};
		new Ajax.Request(self.searchalyzr.url, {
			method: 'post',
			parameters: params,
			evalJSON: 'force',
			onSuccess: function(transport) {
				var data = transport.responseJSON;
				if (data.result) {
					self.searchalyzr.builder.handleConfig(data.result);
				} else {
					var template = new Template('Could not fetch parameter config for system "#{system}"\n' +
							'Recieved unexpected response:\n#{data}');
					var fields = { system: self.system.getLabel(), data: Object.toJSON(data) };
					alert(template.evaluate(fields));
				}
			},
			onFailure: function(transport) {
				var template = new Template('Could not fetch parameter config for system "#{system}"\n' +
					'Error in Query: #{url} - #{query}');
				var fields = { system: self.system.getLabel(), url: self.searchalyzr.url, query: Object.toJSON(params) };
				alert(template.evaluate(fields));
			}
		});
	},	

	/**
	 * Aktualisiert das gesamte System.
	 * 
	 * @return void
	 */
	updateAll: function() {
		var searchParams = this.searchalyzr.getSearchParams(this.system.tabid);
		this.getSearchResult(searchParams);
	},
	
	/**
	 * Aktualisiert eine Kategorie.
	 * 
	 * @param categoryId [String]
	 * Kategorie-ID die aktualisiert werden soll.
	 * 
	 * @param offset [Integer]
	 * Daten offset.
	 * 
	 * @param data [Object] (optional)
	 * Datenobjekt, mit dem die Kategorie aktualisiert wird.
	 * Wenn dieses nicht existiert, wird eine neue Anfrage gestartet.
	 * 
	 * @return void
	 */
	updateCategory: function(categoryId, offset, data) {
		if (!data) {
			var searchParams = this.searchalyzr.getSearchParams(this.system.tabid);
			for (var i = 0; i < searchParams.categoryStates.length; i++) {
				if (searchParams.categoryStates[i].id == categoryId) {
					searchParams.categoryStates[i].offset = offset;
					searchParams.categoryStates[i].sorting = (this.categories[categoryId] ? this.categories[categoryId].sorting : null);
					this.getSearchResult(searchParams);
					return;
				}
			}
			searchParams.categoryStates.push({
				expanded: true,
				id: categoryId,
				offset: offset,
				sorting: (this.categories[categoryId] ? this.categories[categoryId].sorting : null)
			});
			this.getSearchResult(searchParams);
		} else {
			if (!this.categories[categoryId]) {
				var categoryContainer = this.searchalyzr.builder.createCategory(data.label);
				this.searchalyzr.builder.addCategory(this.system.container, categoryContainer);
				this.categories[categoryId] = new SearchalyzrDataRepresentationManager(
						this,
						categoryContainer);
			} else {
				this.searchalyzr.builder.readdCategory(this.system.container, this.categories[categoryId].container);
			}
			this.categories[categoryId].setData(data, this.system);
		}
	},
	
	hideCategory: function(categoryId) {
		if (this.categories[categoryId]) {
			this.categories[categoryId].setData(null, this.system);
		}
	}
});
