﻿///summary>
///Simulates the tree structure of the categories and exposes useful methods for working with the tree itself - (traversal, manipulation)
///</summary>

var CategoriesTree = Class.create({
	initialize: function (checkAll) {
		if (!$globals || !$globals.gatewayJS)
			throw new MissingGatewayException("The gateway for the categories is missing.");

		this.checkAll = checkAll;

		this.tree = this.getData();
		this.indexTree();
		this.createParentLinks(this.tree);
	},
	getData: function () {
		var data;
		new Ajax.Request($globals.gatewayJS + "poicategories", {
			asynchronous: false,
			onSuccess: function (req) {
				data = req.responseJSON;
			}
		});

		if (this.checkAll) {
			var f = function (cat) {
				cat.Selected = true;
				cat.Children.each(function (child) { f(child); });
			};

			data = data.each(function (cat) {
				cat.Checked = true;
				f(cat);
			});
		}

		return data;
	},
	getTree: function () {
		return this.tree;
	},
	selectId: function (id, selected) {
		var category = this.getById(id);
		if (category)
			category.Selected = selected;
	},
	markId: function (id, checked) {
		var category = this.getById(id);
		if (category) {
			category.Checked = checked;
			if (category.Children) {
				this.actionTraverse(category.Children, ParentChildActions.markChecked.curry(checked));
			}
			var parent = category.Parent;
			while (parent) {
				parent.Checked = parent.Children.all(function (child) { return child.Checked; });
				parent = parent.Parent;
			}
		}
	},
	getById: function (id) {
		return this.indexedCategories[id];
	},
	conditionalTraverseAll: function (tree, condition) {
		var result = [];

		for (var i = 0; i < tree.length; i++) {
			var current = tree[i];
			if (condition(current))
				result.push(current);

			if (current.Children != null)
				result = result.concat(this.conditionalTraverseAll(current.Children, condition));
		}

		return result;
	},
	conditionalTraverse: function (tree, condition) {
		var result = [];

		for (var i = 0; i < tree.length; i++) {
			var current = tree[i];
			if (condition(current))
				result.push(current);
			else if (current.Children != null)
				result = result.concat(this.conditionalTraverse(current.Children, condition));
		}

		return result;
	},
	getTopSelected: function (id) {
		var category = this.getById(id);
		if (category && category.Children)
			return this.conditionalTraverse(category.Children, CategoryConditions.selected);
		else
			return [];
	},
	indexTree: function () {
		this.indexedCategories = {};
		var categories = this.conditionalTraverseAll(this.tree, CategoryConditions.allTrue);
		for (var i = 0; i < categories.length; i++) {
			var category = categories[i];
			this.indexedCategories[category.Id] = category;
		}
	},
	actionTraverseChildren: function (tree, action) {
		for (var i = 0; i < tree.length; i++) {
			var current = tree[i];
			for (var j = 0; j < current.Children.length; j++) {
				var child = current.Children[j];
				action(current, child);
			}
			this.actionTraverseChildren(current.Children, action);
		}
	},
	actionTraverse: function (tree, action) {
		for (var i = 0; i < tree.length; i++) {
			var current = tree[i];
			action(current);
			this.actionTraverse(current.Children, action);
		}
	},
	createParentLinks: function () {
		this.actionTraverseChildren(this.tree, ParentChildActions.setParent);
	}
});

var CategoryConditions = {
	byId: function(id, category) { return category.Id == id; },
	selected: function(category) { return category.Selected; },
	allTrue: function(category) { return true; }
};
var ParentChildActions = {
	setParent: function(parent, child) { child.Parent = parent; },
	markChecked: function(checked, current) { current.Checked = checked }
}

generateException("MissingGatewayException");

var sampleData =
	[{Id: 1, Name: "Category1", Url: "/inselferien/mallorca/category1", Children: [
		{Id: 6, Name: "Category6", Url: "/inselferien/mallorca/category6", Children: [
			{Id: 10, Name: "Category10", Url: "/inselferien/mallorca/category10", Children: []},
			{Id: 11, Name: "Category11", Url: "/inselferien/mallorca/category11", Children: []},
			{Id: 12, Name: "Category12", Url: "/inselferien/mallorca/category12", Selected: true, Children: []},
			{Id: 13, Name: "Category13", Url: "/inselferien/mallorca/category13", Children: []},
			{Id: 14, Name: "Category14", Url: "/inselferien/mallorca/category14", Selected: true, Children: []},
			{Id: 15, Name: "Category15", Url: "/inselferien/mallorca/category15", Selected: true, Children: [
				{Id: 21, Name: "Category21", Url: "/inselferien/mallorca/category21", Selected: true, Children: []},
				{Id: 22, Name: "Category22", Url: "/inselferien/mallorca/category22", Selected: true, Children: []},
				{Id: 23, Name: "Category23", Url: "/inselferien/mallorca/category23", Selected: true, Children: []}
			]},
			{Id: 20, Name: "Category20", Url: "/inselferien/mallorca/category20", Children: []}
		]},
		{Id: 7, Name: "Category7", Url: "/inselferien/mallorca/category7", Children: [
			{Id: 16, Name: "Category16", Url: "/inselferien/mallorca/category16", Children: []},
			{Id: 17, Name: "Category17", Url: "/inselferien/mallorca/category17", Children: []},
			{Id: 18, Name: "Category18", Url: "/inselferien/mallorca/category18", Children: []},
			{Id: 19, Name: "Category19", Url: "/inselferien/mallorca/category19", Children: []}
		]},
		{Id: 8, Name: "Category8", Url: "/inselferien/mallorca/category8", Selected: true, Children: []}
	]},
	{Id: 2, Name: "Category2", Url: "/inselferien/mallorca/category2", Children: [
		{Id: 9, Name: "Category9", Url: "/inselferien/mallorca/category9", Children: []}
	]},
	{Id: 3, Name: "Category3", Url: "/inselferien/mallorca/category3", Children: []},
	{Id: 4, Name: "Category4", Url: "/inselferien/mallorca/category4", Children: []},
	{Id: 5, Name: "Category5", Url: "/inselferien/mallorca/category5", Children: []}];
