module.exports = DataTree;

/**
	@class DataTree
	@constructor
*/
function DataTree() {
	this._root = {};
}

/**
	@method create
*/
DataTree.create = function () {
	return new DataTree();
};

/**
	@method getRoot
	@return {Object}
*/
DataTree.prototype.getRoot = function () {
	return this._root;
};

/**
	Walk object tree to parent of defined path

	@method walkTree
	@param  {Object}       root  Tree root
	@param  {String|Array} path  Key path
	@return {Object} Parent branch
*/
DataTree.prototype.walkTree = function (root, path, isArray) {
	var pathParts = Array.isArray(path) ? path : path.split('.');
	var branch = root;
	var key;

	for (var i = 0, il = pathParts.length; i < il; i ++) {
		key = pathParts[i];
		if (!branch[key]) {
			branch[key] = isArray ? [] : {};
		}

		branch = branch[key];
	}

	return branch;
};

/**
	Add value to tree

	@method addValue
	@param {String} key    Defines object path in dot notation
	@param {String} value
*/
DataTree.prototype.addValue = function (key, value) {
	var root = this._root;
	var keyParts = key.split('.');

	var keyEnd = keyParts.pop();
	var keyIsInt = !isNaN(parseInt(keyEnd, 10));
	var branch = this.walkTree(root, keyParts, keyIsInt);
	var isImplicitArray = branch[keyEnd] != null;

	return isImplicitArray ?
		this._addImplicitArrayValue(branch, keyEnd, value) :
		this._addValue(branch, keyEnd, value);
};

/**
	Create or add to `Array` value for duplicat keys

	@method _addImplicitArrayValue
	@param {Object} branch
	@param {String} key
	@param {any}    value
	@private
*/
DataTree.prototype._addImplicitArrayValue = function (branch, key, value) {
	var existing = branch[key];

	if (Array.isArray(existing)) {
		existing.push(value);
	} else {
		branch[key] = [existing, value];
	}
};

/**
	Create value

	@method _addValue
	@param {Object} branch
	@param {String} key
	@param {any}    value
	@private
*/
DataTree.prototype._addValue = function (branch, key, value) {
	branch[key] = value;
};

@@ -529,17 +529,8 @@
 path
-, isArray
 ) %7B%0A
@@ -620,16 +620,34 @@
 %09var key
+, keyNext, isArray
 ;%0A%0A%09for 
@@ -679,16 +679,20 @@
 s.length
+ - 1
 ; i %3C il
@@ -727,15 +727,15 @@
 i%5D;%0A
+%0A
 %09%09if (
-!
 bran
@@ -745,95 +745,318 @@
 key%5D
-) %7B%0A%09%09%09branch%5Bkey%5D = isArray ? %5B%5D : %7B%7D;%0A%09%09%7D%0A%0A%09%09branch = branch%5Bkey%5D;%0A%09%7D%0A%0A%09return branch
+ == null) %7B%0A%09%09%09keyNext = pathParts%5Bi + 1%5D;%0A%09%09%09isArray = this._keyIsInt(keyNext);%0A%09%09%09branch%5Bkey%5D = isArray ? %5B%5D : %7B%7D;%0A%09%09%7D%0A%0A%09%09branch = branch%5Bkey%5D;%0A%09%7D%0A%0A%09return branch;%0A%7D;%0A%0A/**%0A%09@method _keyIsInt%0A%09@return %7BBoolean%7D%0A%09@private%0A*/%0ADataTree.prototype._keyIsInt = function (value) %7B%0A%09return !isNaN(parseInt(value, 10))
 ;%0A%7D;
@@ -1295,17 +1295,16 @@
 t('.');%0A
-%0A
 %09var key
@@ -1321,61 +1321,31 @@
 arts
-.pop();%0A%09var keyIsInt = !isNaN(parseInt(keyEnd, 10));
+%5BkeyParts.length - 1%5D;%0A
 %0A%09va
@@ -1387,18 +1387,8 @@
 arts
-, keyIsInt
 );%0A%09
@@ -1608,16 +1608,17 @@
 duplicat
+e
  keys%0A%0A%09

Fix path walking of arrays