﻿if (typeof Effect == 'undefined')
    throw ("controls.js requires including script.aculo.us' effects.js library");

   MyAutocompleter = Class.create({
   	D_PAGE_SIZE: 10,
   	D_PARAM: "search",
   	initialize: function (element, update, url, options) {
   		if (element)
   			this.element = $(element);

   		this.update = $(update);
   		this.hasFocus = false;
   		this.changed = false;
   		this.active = false;
   		this.entryCount = 0;
   		this.options = options || {};

   		this.url = url;
   		this.noHide = false;

   		this.types = this.options.types || [];
   		this.types.unshift({ type: "mix", pageSize: this.D_PAGE_SIZE }); //Vorschlag

   		this.options.paramName = this.options.paramName || (this.element ? this.element.name : this.D_PARAM);
   		this.options.frequency = this.options.frequency || 0.4;
   		this.options.minChars = this.options.minChars || 1;
   		this.options.onShow = function (element, update) {
   			var offset = element.cumulativeOffset();
   			$(update).setStyle({ left: pix(offset.left), top: pix(offset.top + element.offsetHeight) });
   			Effect.Appear(update, { duration: 0.15 });
   		};
   		this.onItemClickHandler = options.onItemClickHandler;

   		this.options.asynchronous = true;
   		this.options.onSuccess = this.onSuccess.bind(this);
   		this.timer = null;

   		if (this.options.closeButton) {
   			var closeButton = $(newElement("img", this.update, { src: $globals.root + "content/images/x.jpg", className: "closeButton" }));
   			closeButton.observe("mousedown", this.hide.bind(this));
   		}

   		Element.hide(this.update);

   		if (this.element) {
   			this.element.setAttribute('autocomplete', 'off');
   			Event.observe(this.element, 'focus', this.hide.bind(this));
   			Event.observe(this.element, 'blur', this.hide.bind(this));

   			if (!this.options.manual)	//do not auto show ac after each keypress(i.e show ac manually)
   				Event.observe(this.element, 'keyup', this.onKeyPress.bindAsEventListener(this));
   		}
   	},
   	setMoreParams: function (name, value) {
   		this.options.moreParams = name + "=" + value;
   	},
   	onSuccess: function (request) {
   		this.updateChoices(request.responseJSON);
   	},
   	show: function () {
   		if (Element.getStyle(this.update, 'display') == 'none') this.options.onShow(this.element, this.update);
   		if (!this.iefix && (Prototype.Browser.IE) && (Element.getStyle(this.update, 'position') == 'absolute')) {
   			new Insertion.After(this.update,
       '<iframe id="' + this.update.id + '_iefix" ' +
       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
   			this.iefix = $(this.update.id + '_iefix');
   		}
   		if (this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
   	},
   	fixIEOverlapping: function () {
   		Position.clone(this.update, this.iefix, { setTop: (!this.update.style.height) });
   		this.iefix.style.zIndex = 1001;
   		this.update.style.zIndex = 1002;
   		Element.show(this.iefix);
   	},
   	hide: function () {
   		if (!this.noHide) {
   			if (Element.getStyle(this.update, 'display') != 'none') {
   				new Effect.Fade(this.update, { duration: 0.15 });
   				this.hasFocus = false;
   				this.active = false;
   			}
   			if (this.iefix) Element.hide(this.iefix);
   		}
   	},
   	onKeyPress: function (event) {
   		if (this.active)
   			switch (event.keyCode) {
   			case Event.KEY_TAB:
   			case Event.KEY_RETURN:
   				if (!this.selectEntry())
   					return;
   				Event.stop(event);
   			case Event.KEY_ESC:
   				this.hide();
   				this.active = false;
   				Event.stop(event);
   				return;
   			case Event.KEY_LEFT:
   			case Event.KEY_RIGHT:
   				return;
   			case Event.KEY_UP:
   				this.markPrevious();
   				Event.stop(event);
   				return;
   			case Event.KEY_DOWN:
   				this.markNext();
   				Event.stop(event);
   				return;
   		}
   		else
   			if (event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN || event.keyCode == Event.KEY_LEFT || event.keyCode == Event.KEY_RIGHT ||
         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;

   		this.changed = true;
   		this.hasFocus = true;

   		if (this.timer) clearTimeout(this.timer);
   		this.timer = setTimeout(this.preUpdate.bind(this), this.options.frequency * 1000);
   	},
   	activate: function () {
   		this.changed = false;
   		this.hasFocus = true;
   		this.getUpdatedChoices();
   	},
   	onHover: function (event) {
   		this.noHide = true;
   		var item = Event.findElement(event, 'LI');

   		if (!item.hasClassName("selected")) {
   			this.update.select("li").each(function (li) { li.removeClassName("selected"); });
   			item.addClassName("selected");
   		}

   		Event.stop(event);
   	},
   	markPrevious: function () {
   		var items = this.update.select("li");
   		var i, item;
   		for (i = 0; i < items.length; i++) {
   			var li = items[i];
   			if (li.hasClassName("selected")) {
   				li.removeClassName("selected");
   				break;
   			}
   		}

   		do {
   			i--;
   			if (i < 0)
   				i = (items.length - 1);

   			item = items[i];
   		}
   		while (!Element.visible(item) || !Element.visible(item.up("div")));

   		item.addClassName("selected");
   	},
   	markNext: function () {
   		var items = this.update.select("li");
   		var i, item;
   		for (i = 0; i < items.length; i++) {
   			var li = items[i];
   			if (li.hasClassName("selected")) {
   				li.removeClassName("selected");
   				break;
   			}
   		}

   		do {
   			i++;
   			if (i >= items.length)
   				i = 0;

   			item = items[i];
   		}
   		while (!Element.visible(item) || !Element.visible(item.up("div")));

   		item.addClassName("selected");
   	},
   	getCurrentEntry: function () {
   		var items = this.update.select("li");
   		return items.detect(function (li) { return li.hasClassName("selected"); }) || items[0];
   	},
   	selectEntry: function () {
   		var item = this.getCurrentEntry();

   		if (item.onclick)
   			item.onclick();

   		if (item.hasClassName("acPager"))
   			return false;
   		else
   			return true;
   	},
   	updateElement: function () {
   		var item = this.getCurrentEntry();
   		this.element.value = Element.collectTextNodesIgnoreClass(item, 'informal');
   		this.element.focus();
   		this.active = false;
   	},
   	updateChoices: function (choices) {
   		if ((!this.changed && this.hasFocus) || this.options.manual) {
   			if (choices.length > 0) {
   				this.types.each(function (t) {
   					t.page = 1;
   					var id = "ac-" + t.type;
   					var typeContainer = $(id);

   					if (typeContainer)
   						typeContainer.hide();
   					else {
   						typeContainer = $(newElement("div", this.update, { id: id }));
   						typeContainer.hide();
   						newElement("label", typeContainer);
   						var ul = newElement("ul", typeContainer);

   						var prev = $(newElement("li", ul));
   						prev.className = "acPager";
   						prev.appendChild(document.createTextNode("zurück ..."));
   						this.addObservers(prev);

   						var prevClick = function (type) {
   							this.gotoPage(type, type.page - 1);
   							if (type.page == 1)
   								this.markNext();
   						} .bind(this, t);
   						prev.onclick = prevClick;

   						var i = t.pageSize;
   						while (i--) {
   							var li = $(newElement("li", ul));
   							this.addObservers(li);
   						}

   						var next = $(newElement("li", ul));
   						next.className = "acPager";
   						next.appendChild(document.createTextNode("weiter ..."));
   						this.addObservers(next);

   						var nextClick = function (type) {
   							this.gotoPage(type, type.page + 1);
   							if (type.page == Math.ceil(type.count / t.pageSize))
   								this.markPrevious();
   						} .bind(this, t);
   						next.onclick = nextClick;
   					}
   				} .bind(this));

   				choices.each(function (choiceGroup, ix) {
   					this.updateTypeContainer(choiceGroup);
   				} .bind(this));

   				this.type = choices[0].Type;

   				if (this.hasFocus || this.options.manual) {
   					this.show();
   					this.active = true;
   				}
   			}
   			else
   				this.hide();
   		}
   	},
   	addObservers: function (element) {
   		Event.observe(element, "mouseout", function () { this.noHide = false; } .bind(this));
   		Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
   	},
   	manualUpdate: function (value) {
   		if (this.timer) clearTimeout(this.timer);

   		if (value.length >= this.options.minChars)
   			this.timer = setTimeout(this.getUpdatedChoices.bind(this, value), this.options.frequency * 1000);
   	},
   	preUpdate: function () {
   		this.changed = false;

   		if (this.element.value.length >= this.options.minChars) {
   			this.getUpdatedChoices();
   		} else {
   			this.changed = false;
   			this.active = false;
   			this.hide();
   		}
   	},
   	getUpdatedChoices: function (value) {
   		var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent((value || this.element.value).strip());
   		this.options.parameters = entry;
   		if (this.options.moreParams)
   			this.options.parameters += "&" + this.options.moreParams;
   		new Ajax.Request(this.url, this.options);
   	},
   	updateTypeContainer: function (choiceGroup) {
   		if (!choiceGroup) //nothing selected
   			return;

   		var t = this.types.detect(function (t) { return t.type == choiceGroup.Type; });

   		if (!t) // no such type
   			return;

   		var itemsCount = choiceGroup.Items.length;
   		t.count = choiceGroup.TotalRows;

   		var id = "ac-" + t.type;
   		var typeContainer = $(id);

   		var title = typeContainer.select("label")[0];
   		var ul = typeContainer.select("ul")[0];

   		if (choiceGroup.TotalRows > 0) {
   			if (title.innerHTML != choiceGroup.TitleText)
   				title.innerHTML = choiceGroup.TitleText;

   			var lis = ul.select("li");

   			for (var i = 0; i < t.pageSize; i++) {
   				var item = choiceGroup.Items[i];

   				if (!item) {
   					lis[i + 1].hide();
   					continue;
   				}

   				if (i == 0) {
   					if (item.RowID > 1)
   						lis.first().show();
   					else
   						lis.first().hide();
   				}

   				li = lis[i + 1];
   				li.show();

   				if (this.types.detect(function (tt) { return tt.type == t.type; })) {
   					if (this.onItemClickHandler)
   						li.onclick = function (item) {
   							if (!this.options.manual)
   								this.updateElement();

   							this.noHide = false;
   							this.hide();
   							this.onItemClickHandler(item);
   						} .bind(this, item);

   					switch (t.type) {
   						case "poi":
   							li.innerHTML = "<b>" + item.name + "</b>" + (item.info ? "<span class='informal'>, " + item.info + "</span>" : ""); //name, address
   							if (!this.onItemClickHandler)
   								li.onclick = function (url) { location.href = url; } .bind(null, $globals.root + item.url);
   							break;
   						case "city":
   							li.innerHTML = (item.info ? "<span class='informal'>" + item.info + " </span>" : "") + "<b>" + item.name + "</b>"; //plz city
   							if (!this.onItemClickHandler)
   								li.onclick = function (url) { location.href = url; } .bind(null, $globals.root + item.url);
   							break;
   						case "cat":
   							li.innerHTML = "<b>" + item.name + "</b>";
   							if (!this.onItemClickHandler)
   								li.onclick = function (url) { location.href = url; } .bind(null, $globals.root + item.url);
   							break;
   						case "str":
   							li.innerHTML = "<b>" + item.name + "</b>" + (item.info ? "<span class='informal'>, " + item.info + "</span>" : ""); //name, city
   							if (!this.onItemClickHandler)
   								li.onclick = function (item) {
   									this.updateElement();
   									this.noHide = false;
   									this.hide();
   									AConClickStreet(item);
   								} .bind(this, { type: "str", ids: [item.id] });
   							break;
   						case "mix":
   							li.innerHTML = "<b>" + item.name + "</b>" + (item.info ? "<span class='informal'>, " + item.info + "</span>" : ""); //name, info
   							if (!this.onItemClickHandler)
   								if (item.context.type == "poi")
   									li.onclick = function (url) { location.href = url; } .bind(null, $globals.root + item.url);
   								else if (item.context.type == "city")
   									li.onclick = function (item, catId) {
   										this.updateElement();
   										this.noHide = false;
   										this.hide();
   										AConClickMix(item, catId);
   									} .bind(this, item.context, item.id);
   							break;
   						case "news":
   						case "newslocation":
   							li.innerHTML = "<b>" + item.name + "</b>";
   					}
   				}

   				if (i == itemsCount - 1) {
   					if (item.RowID < choiceGroup.TotalRows)
   						lis.last().show();
   					else
   						lis.last().hide();
   				}
   			}

   			typeContainer.show();
   		}
   		else
   			typeContainer.hide();
   	},
   	gotoPage: function (t, pageNumber) {
   		this.element.focus();

   		this.options.parameters = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.element.value);
   		this.options.parameters += "&type=" + t.type + "&page=" + pageNumber.toString();

   		new Ajax.Request(this.url, {
   			asynchronous: false,
   			parameters: this.options.parameters,
   			onSuccess: function (t, pageNumber, req) {
   				t.page = pageNumber;
   				this.updateTypeContainer(req.responseJSON[0]);
   			} .bind(this, t, pageNumber)
   		});
   	}
   });

   function AConClickStreet(item) {
   	MainMap.setCurrentMarker(item);

   	var onSuccessHandler = function (req) {
   		var item = req.responseJSON;

   		if (this.MainMap.homeInfo && this.MainMap.homeInfo.visible())
   			this.MainMap.homeInfo.hide();

   		MainMap.setCenter(item.loc, MainMap.grid.availZoomLevels.indexOf(10000));
   	};

   	GetMarker(item, MainMap.grid.getView(MainMap.grid.mode, 10000).gridId, onSuccessHandler);
   }

   function AConClickMix(item, catId) {
   	MainMap.setCurrentMarker(item);

   	var onSuccessHandler = function (catId, req) {
   		var item = req.responseJSON;
   		var viewportSize = MainMap.grid.viewport.getDimensions();

   		new Ajax.Request($globals.gatewayJS + "ZoomToCategory", {
   			parameters: {
   				id: catId,
   				center: item.loc.lon.toString() + "," + item.loc.lat.toString(),
   				scale: MainMap.grid.view.gridId,
   				width: viewportSize.width,
   				height: viewportSize.height
   			},
   			onSuccess: function (catId, req) {
   				var res = req.responseJSON;
   				var view = MainMap.grid.views[MainMap.grid.mode].detect(function (view) { return view.gridId == res.Scale; });
   				MainMap.categories = catId;

   				if (this.MainMap.homeInfo && this.MainMap.homeInfo.visible())
   					this.MainMap.homeInfo.hide();

   				MainMap.setCenter(res.Center, MainMap.grid.availZoomLevels.indexOf(view.scale));
   			} .bind(this, catId)
   		});
   	} .bind(this, catId);

   	GetMarker(item, MainMap.grid.view.gridId, onSuccessHandler);
   }
