﻿///<summary>
///Configurator for the menu with categories. This is a side panel that slides underneath the right side panel.
///</summary>

var CategoriesMenuConfiguratorControl = Class.create({
	initialize: function (treeManager, container, options) {
		this.treeManager = treeManager;
		this.container = $(container);

		this.options = Object.extend({
			maxRows: 14,
			maxSelected: 4,
			currentCategory: null
		}, options || {});

		this.hide();
		this.prepareContainerForColumns();
		this.addCloseButton();

		Event.observe(window, "unload", this.destroy.bind(this));
	},
	prepareContainerForColumns: function () {
		var table = newElement("tbody", newElement("table", this.container));
		this.contentContainer = $(newElement("tr", table));
	},
	addCloseButton: function () {
		var button = $(newElement("a", this.container, { title: "Schliessen", id: "configuratorClose", href: "javascript: void 0;" })).update("Schliessen").observe("click", this.hide.bind(this));
	},
	buildCategoryListById: function (id) {
		this.currentCategory = id;

		this.clearContent();
		this.buildCategoriesInColumns(this.treeManager.getById(id).Children, this.contentContainer);
	},
	buildCategoriesInColumns: function (list) {
		list.each(this.addCategoryToCurrentColumn.bind(this));
	},
	buildCategoriesList: function (list, container) {
		var htmlList = $(newElement("ul", container, { className: "categories" }));

		list.each(function (category) {
			this.buildCategoryRecursively(category, htmlList);
		} .bind(this));

		return htmlList;
	},
	buildCategoryRecursively: function (category, container) {
		var li = this.buildCategory(category, container);
		if (category.Children && category.Children.length)
			this.buildCategoriesList(category.Children, li);
	},
	buildCategory: function (category, container) {
		var li = $(newElement("li", container, { id: "category" + category.Id }));
		var categoryContainer = newElement("div", li);
		var checkBox = $(newElement("input", categoryContainer, { type: "checkbox", id: "catCheck" + category.Id, name: "category" }));
		checkBox.checked = category.Selected;
		checkBox.observe("click", this.onCheckboxChecked.bind(this));
		var link = $(newElement("label", categoryContainer, { id: "catLink" + category.id, title: category.Name }));
		link.setAttribute("for", "catCheck" + category.Id);
		link.appendChild(document.createTextNode(category.Name));

		return li;
	},
	toggleCategory: function (id) {
		if (this.currentCategory == id)
			this.toggle();
		else {
			if (this.container.visible()) this.hide();
			this.show(this.buildCategoryListById.bind(this, id));
		}
	},
	clearContent: function () {
		removeChildrenRecursively(this.contentContainer);
		this.currentColumnHeight = 0;
		this.currentColumn = null;
	},
	///show/hide methods
	toggle: function () {
		if (this.container.visible())
			this.hide();
		else
			this.show();
	},
	show: function (beforeStartAction) {
		new Effect.Move(this.container, { x: 0, y: this._getContainerYPos(), queue: { position: "end", scope: "conf" }, duration: 0.4, mode: "absolute", beforeSetup: beforeStartAction, afterSetup: this._showContainer.bind(this) });
	},
	_showContainer: function (event) {
		var container = event.element;
		container.show();
		if (Prototype.Browser.IE)
			container.setStyle({ width: pix(container.down("tbody").offsetWidth + 50) });

	},
	hide: function () {
		new Effect.Move(this.container, { x: -450, y: this._getContainerYPos(), queue: { position: "end", scope: "conf" }, duration: 0.4, mode: "absolute", afterFinish: function (event) { event.element.hide(); } });
	},
	tryHide: function () {
		if (this.container.visible())
			this.hide();
	},
	///column design methods
	addCategoryToCurrentColumn: function (category) {
		if (!this.currentColumn || !this.categoryFitsInCurrentColumn(category))
			this.addCategoryToNewColumn(category);
		else
			this._addCategoryToCurrentColumn(category);
	},
	_addCategoryToCurrentColumn: function (category) {
		var htmlList = $(newElement("ul", this.currentColumn, { className: "categories" }));
		this.buildCategoryRecursively(category, htmlList);
		this.currentColumnHeight += this.getCategoryHeight(category);
	},
	addCategoryToNewColumn: function (category) {
		this.currentColumn = $(newElement("td", this.contentContainer));
		this.currentColumnHeight = 0;
		this._addCategoryToCurrentColumn(category);
	},
	categoryFitsInCurrentColumn: function (category) {
		var categoryHeight = this.getCategoryHeight(category);
		return this.options.maxRows >= categoryHeight + this.currentColumnHeight;
	},
	///checkbox event handlers
	onCheckboxChecked: function (event) {
		this.checkboxChanged(event.element());
	},
	///checkbox methods
	checkboxChanged: function (checkbox) {
		this.manageCheckboxesAfterChange(checkbox, checkbox.checked);

		if (this.validateCheckboxes())
			Event.fire(checkbox, "menu:changed", { category: this.treeManager.getById(this.currentCategory) });
		else {
			this.manageCheckboxesAfterChange(checkbox, !checkbox.checked);
			this.raiseError();
		}
	},
	manageCheckboxesAfterChange: function (checkbox, checked) {
		this.checkCategory(checkbox, checked);

		if (this.checkboxIsChild(checkbox)) {
			var childCheckbox = checkbox;
			var parentCheckbox = checkbox;

			while (this.checkboxIsChild(parentCheckbox)) {
				parentCheckbox = this.getParentCheckbox(childCheckbox);
				this.checkCategory(parentCheckbox, this.allNeighbourCheckBoxesChecked(childCheckbox));
				childCheckbox = parentCheckbox;
			}
		}

		if (this.checkboxHasChildren(checkbox)) {
			this.checkAllChildren(checkbox);
		}
	},
	checkCategory: function (checkbox, checked) {
		checkbox.checked = checked;
		this.treeManager.selectId(this.getCheckboxId(checkbox), checked);
	},
	markCategory: function (catId, checked) {
		this.treeManager.markId(catId, checked);
	},
	checkAllChildren: function (parentCheckbox) {
		var childrenCheckboxes = this.getAllChildrenCheckboxes(parentCheckbox);
		childrenCheckboxes.each(function (checkbox) { this.checkCategory(checkbox, parentCheckbox.checked); } .bind(this));
	},
	///state checkers
	allNeighbourCheckBoxesChecked: function (checkbox) {
		var neighbourCheckboxes = this.getAllNeighbourCheckboxes(checkbox);
		return neighbourCheckboxes.all(function (checkbox) { return checkbox.checked; });
	},
	checkboxIsChild: function (checkbox) {
		return checkbox.up("ul").up().tagName.toLowerCase() == "li";
	},
	checkboxHasChildren: function (checkbox) {
		return checkbox.up("li").down("ul") != null;
	},
	validateCheckboxes: function () {
		var chosenCategories = this.getSelectedSubcategoriesForId(this.currentCategory);
		return this.options.maxSelected == 0 || chosenCategories.length <= this.options.maxSelected;
	},
	raiseError: function () {
		alert("Sie koennen leider nicht mehr als " + this.options.maxSelected + " Kategories waehlen.");
	},
	///getters checkbox
	getParentCheckbox: function (checkbox) {
		return checkbox.up("ul").up("li").down(":checkbox");
	},
	getAllNeighbourCheckboxes: function (checkbox) {
		return this.getAllCheckboxesFromList($(checkbox).up("ul"));
	},
	getAllChildrenCheckboxes: function (checkbox) {
		return $(checkbox).up("li").down("ul").select(":checkbox");
	},
	getAllCheckboxesFromList: function (list) {
		return list.select(" >li :checkbox");
	},
	getCheckboxId: function (checkbox) {
		return checkbox.id.substring('catCheck'.length); // parseInt(/\d+$/.exec(checkbox.id)[0]);
	},
	///getters
	getCategoryHeight: function (category) {
		var height = this._getCategoryHeightRecursively(category) + 1; //for the category itself

		return height;
	},
	_getCategoryHeightRecursively: function (category) {
		var height = 0; var currentList = category.Children;

		if (currentList && currentList.length) {
			height += currentList.length;
			currentList.each(function (subCategory) { height += this._getCategoryHeightRecursively(subCategory); } .bind(this));
		}

		return height;
	},
	_getContainerYPos: function () {
		return Prototype.Browser.IE ? parseInt(this.container.getStyle("top")) : this.container.getStyle("y");
	},
	getSelectedSubcategoriesForId: function (id) {
		return this.treeManager.getTopSelected(id);
	},
	getCategories: function () {
		return this.treeManager.getTree();
	},
	destroy: function () {
		this.container = null;
		this.contentContainer = null;
		this.currentColumn = null;
	}
});
