var Tree = new Class({
	Implements: [Options, Events],

	options: {
		subSelector: 'ol|ul',

		openFirst: true,

		openCurrent: true,

		singleOpen: true,

		currentDepth: 3,

		onOpen: {
			addClass: 'active'
		}
	},

	initialize: function (trees, options) {
		this.setOptions(options);

		this.trees = trees.map(function (cont) {
			return this.prepTree(cont);
		}, this);
	},

	prepTree: function (tree, level) {
		var opt = this.options;
		var subNodes = tree.getElements(opt.subSelector);

		tree = subNodes.map(function (subNode) {
			var node = new Hash({open: false, target: subNode});
			node.set('parent', node.get('target').getParent());

			node = this.addOpener(node);

			if (opt.openCurrent) {
				var winLoc = window.location.href;
				if (winLoc.indexOf('#') !== -1) {
					winLoc = winLoc.substring(0, winLoc.indexOf('#'));
				}

				var isCurrent = this.hasCurrent(node.get('parent').getElements('a'), winLoc);

				if (isCurrent) {
					if (isCurrent.getParent().getElements(opt.subSelector).length < 1)
						isCurrent.getParent().addClass('active');
					
					node.set('open', true);
				}
			}

			if (node.get('open')) {
				this.openNode(node);
			} else {
				this.closeNode(node);
			}

			return node;
		}.bind(this));

		return tree;
	},

	hasCurrent: function (items, url) {
		var urlParts = url.substr(url.indexOf('://')+3).split('/');

		var matches = items.filter(function (item) {
			var href = item.get('href');

			if (href) {
				if (href.test(url)) {
					return item;
				} else if (url.test(href)) {
					var hrefParts = href.substr(href.indexOf('://')+3).split('/');
					var depthCount = 0;

					for (var i = 0, l = urlParts.length; i < l; i++) {
						if (urlParts[i] === hrefParts[i]) {
							depthCount++;
						}
					}

					if (depthCount >= this.options.currentDepth) {
						return item;
					}
				}
			}
		}.bind(this));

		return matches[0];
	},

	addOpener: function (node) {
		node.set('opener', node.get('target').getPrevious('a'));

		node.get('opener').addEvent('click', this.nodeClick.bindWithEvent(this, node));

		return node;
	},

	openNode: function (node) {
		node.get('parent').addClass(this.options.onOpen.addClass);
		node.get('target').setStyle('display', 'block');

		node.set('open', true);
	},

	closeNode: function (node) {
		node.get('parent').removeClass(this.options.onOpen.addClass);
		node.get('target').setStyle('display', 'none');

		node.set('open', false);
	},


	nodeClick: function (e, node) {
		e.stop();

		if (node.get('open')) {
			this.closeNode(node);
		} else {
			this.openNode(node);
		}
	}
});