/**  @author Gilles Coomans <gilles.coomans@gmail.com> */
//________________________________ Properties management with dot syntax

function getProp(from, path) {
	var start = 0;
	if (path[0] === '$this')
		start = 1;
	var tmp = from;
	for (var i = start, len = path.length; i < len; ++i)
		if (!tmp || (tmp = tmp[path[i]]) === undefined)
			return;
	return tmp;
}

function deleteProp(from, path) {
	var tmp = from,
		i = 0;
	for (len = path.length - 1; i < len; ++i)
		if (tmp && !(tmp = tmp[path[i]]))
			return;
	if (tmp)
		delete tmp[path[i]];
}

function setProp(to, path, value) {
	var tmp = to,
		i = 0,
		old,
		len = path.length - 1;
	for (; i < len; ++i)
		if (tmp && !tmp[path[i]])
			tmp = tmp[path[i]] = {};
		else
			tmp = tmp[path[i]];
	if (tmp) {
		old = tmp[path[i]];
		tmp[path[i]] = value;
	}
	return old;
}

//______________________ EMPTY / DESTROY

function emptyNode(node) {
	if (!node.childNodes || !node.childNodes.length)
		return;
	for (var i = 0, len = node.childNodes.length; i < len; ++i) {
		var child = node.childNodes[i];
		if (child.parent)
			child.parent.removeChild(child);
	}
}

function destroyElement(node, removeFromParent) {
	if (node.context) {
		node.context.destroy();
		node.context = null;
	}

	if (node.__yContainer__) {
		if (node.childNodes && node.childNodes.length)
			destroyChildren(node, removeFromParent);
	} else {
		if (removeFromParent && node.parentNode) {
			node.parentNode.removeChild(node);
			node.parentNode = null;
		}
		if (node.childNodes && node.childNodes.length)
			destroyChildren(node);
	}
	node.childNodes = null;
	if (node.binds) {
		for (var i = 0, len = node.binds.length; i < len; i++)
			node.binds[i]();
		node.binds = null;
	}
}

function destroyChildren(node, removeFromParent) {
	if (!node.childNodes)
		return;
	for (var i = 0; i < node.childNodes.length; i++)
		destroyElement(node.childNodes[i], removeFromParent);
}


//_______________________________________ EXPORTS

var utils = module.exports = {
	setProp: setProp,
	deleteProp: deleteProp,
	getProp: getProp,
	destroyChildren: destroyChildren,
	destroyElement: destroyElement,
	emptyNode: emptyNode,
	hide: function(node) {
		if (node.__yContainer__)
			return node.hide();
		if (node.style)
			node.style.display = 'none';
		return node;
	},
	show: function(node) {
		if (node.__yContainer__)
			return node.show();
		if (node.style)
			node.style.display = '';
		return node;
	},
	shallowMerge: function(src, target) {
		for (var i in src)
			target[i] = src[i];
	},
	shallowCopy: function(obj) {
		if (obj && obj.forEach)
			return obj.slice();
		if (obj && typeof obj === 'object') {
			if (obj instanceof RegExp || obj instanceof Date)
				return obj;
			var res = {};
			for (var i in obj)
				res[i] = obj[i];
			return res;
		}
		return obj;
	},
	insertBefore: function(parent, node, ref) {
		if (node.__yContainer__) {
			if (node.childNodes)
				for (var i = 0, len = node.childNodes.length; i < len; ++i)
					utils.insertBefore(parent, node.childNodes[i], ref);
		} else
			parent.insertBefore(node, ref);
	},
	/**
	 * parse api method reference as "apiname:mywidget"
	 * @param  {[type]} env  [description]
	 * @param  {[type]} path [description]
	 * @return {[type]}      [description]
	 */
	getApiMethod: function(api, path) {
		if (!path.forEach)
			path = path.split(':');
		if (path.length !== 2)
			throw new Error('yamvish method call badly formatted : ' + path.join(':'));
		var output = api[path[0]][path[1]];
		if (!output)
			throw new Error('no template/container found with "' + path.join(':') + '"');
		return output;
	},
	array: {
		remove: function(arr, value) {
			for (var i = 0, len = arr.length; i < len; ++i)
				if (arr[i] === value) {
					arr.splice(i, 1);
					return;
				}
		},
		insertAfter: function(arr, ref, newItem) {
			var index = arr.indexOf(ref);
			if (ref === -1)
				throw new Error('utils.array.insertAfter : ref not found.');
			if (index === arr.length - 1)
				arr.push(newItem);
			else
				arr.splice(index + 1, 0, newItem);
		}
	}
};

@@ -2789,16 +2789,268 @@
 bj;%0A%09%7D,%0A
+%09copy: function(obj) %7B%0A%09%09var clone = %7B%7D;%0A%09%09for (var i in obj)%0A%09%09%09if (typeof obj%5Bi%5D === 'object') %7B%0A%09%09%09%09if (obj%5Bi%5D.forEach)%0A%09%09%09%09%09clone%5Bi%5D = obj%5Bi%5D.slice();%0A%09%09%09%09else%0A%09%09%09%09%09clone%5Bi%5D = this.copy(obj%5Bi%5D);%0A%09%09%09%7D else%0A%09%09%09%09clone%5Bi%5D = obj%5Bi%5D;%0A%09%09return clone;%0A%09%7D,%0A
 %09insertB

add copy in utils