/**  
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Switcher : inner class that hold bunch of templates associated with a value.
 * DOM only.
 * It allows to switch between templates (rendered and mounted as Container) somewhere in DOM.
 */

var utils = require('../../utils'),
	interpolable = require('../../interpolable').interpolable;

var Switcher = function(context, node, parentContainer, items, defaultTemplate, destructOnSwitch) {
	this.witness = document.createComment('switcher');
	node.appendChild(this.witness); // dummy dom position marker
	this.node = node;
	this.context = context;
	this.items = items;
	this.defaultTemplate = defaultTemplate;
	this.destructOnSwitch = destructOnSwitch;
};

Switcher.prototype = {
	expression: function(expression) {
		expression = interpolable(expression);
		if (expression.__interpolable__) {
			var self = this;
			expression.subscribeTo(this.context, function(value) {
				self.switch(value);
			});
			this.switch(expression.output(this.context));
		} else if (typeof expression === 'function')
			this.switch(expression(this.context));
		else
			this.switch(expression);
	},
	switch: function(value) {
		var self = this;
		var ok = this.items.some(function(item) {
			if (item.value == value) {
				if (!item.container)
					item.container = item.template.toContainer(self.context);
				self._mount(item.container);
				return true;
			}
		});
		if (!ok) {
			if (this.defaultTemplate) {
				if (!this.defaultContainer)
					this.defaultContainer = this.defaultTemplate.toContainer(this.context);
				self._mount(this.defaultContainer);
			} else
				self._unmountCurrent();
		}
	},
	_unmountCurrent: function() {
		if (this.currentContainer) {
			if (this.node.__yContainer__)
				this.node.removeChild(this.currentContainer);
			else if (this.destructOnSwitch) {
				var cur = this.currentContainer;
				this.currentContainer.unmount(false, function() {
					cur.destroy();
				});
			} else
				this.currentContainer.unmount();
			this.currentContainer = null;
		}
	},
	_mount: function(container) {
		if (this.currentContainer === container)
			return;
		this._unmountCurrent();
		this.currentContainer = container;

		if (this.node.__yContainer__ && !this.node.parentNode) { // node is not mounted
			utils.array.insertAfter(this.node.childNodes, this.witness, container);
			return;
		}
		var nextSibling = this.witness.nextSibling;
		if (nextSibling)
			container.insertBeforeNode(nextSibling);
		else
			container.appendTo(this.witness.parentNode);
	}
};

module.exports = Switcher;

@@ -621,16 +621,57 @@
  items;%0A
+%09this.parentContainer = parentContainer;%0A
 %09this.de
@@ -887,16 +887,60 @@
 le__) %7B%0A
+%09%09%09this.node.binds = this.node.binds %7C%7C %5B%5D;%0A
 %09%09%09var s
@@ -1033,24 +1033,41 @@
 value);%0A%09%09%09%7D
+, this.node.binds
 );%0A%09%09%09this.s
@@ -1282,16 +1282,13 @@
 this
-;%0A%09%09var 
+,%0A%09%09%09
 ok =
@@ -1317,24 +1317,25 @@
 ion(item) %7B%0A
+%09
 %09%09%09if (item.
@@ -1352,24 +1352,25 @@
 alue) %7B%0A%09%09%09%09
+%09
 if (!item.co
@@ -1374,24 +1374,25 @@
 .container)%0A
+%09
 %09%09%09%09%09item.co
@@ -1431,35 +1431,58 @@
 ner(self.context
+, self.parentContainer
 );%0A
+%09
 %09%09%09%09self._mount(
@@ -1502,16 +1502,17 @@
 r);%0A%09%09%09%09
+%09
 return t
@@ -1519,18 +1519,20 @@
 rue;%0A%09%09%09
+%09
 %7D%0A
+%09
 %09%09%7D);%0A%09%09
@@ -1679,16 +1679,38 @@
 .context
+, this.parentContainer
 );%0A%09%09%09%09s
@@ -1855,24 +1855,113 @@
 r) %7B%0A%09%09%09
-if (this
+var cur = this.currentContainer,%0A%09%09%09%09self = this;%0A%09%09%09cur.unmount(false, function() %7B%0A%09%09%09%09if (self
 .node.__
@@ -1978,20 +1978,21 @@
 __)%0A%09%09%09%09
-this
+%09self
 .node.re
@@ -2005,159 +2005,71 @@
 ild(
-this.currentContainer);%0A%09%09%09else if (this.destructOnSwitch) %7B%0A%09%09%09%09var cur = this.currentContainer;%0A%09%09%09%09this.currentContainer.unmount(false, function() %7B
+cur);%0A%09%09%09%09if (self.destructOnSwitch) %7B%0A%09%09%09%09%09cur.context = null;
 %0A%09%09%09
@@ -2094,55 +2094,13 @@
 %09%09%09%7D
-);
 %0A%09%09%09%7D
- else%0A%09%09%09%09this.currentContainer.unmount(
 );%0A%09

debug and finalise switcher