/*globals Storage, Query, ObjectId, Panel*/
/**
 * @file Manage populate operations
 */
'use strict'

var Populate = {}

/**
 * Registered populate operations
 * @property {Storage}
 */
Populate.paths = new Storage('populate')

/**
 * Create and run a populate operation
 * @param {string} conn
 * @param {string} coll
 * @param {string} path
 * @param {string} targetConn
 * @param {string} targetColl
 * @param {string} targetPath
 */
Populate.create = function (conn, coll, path, targetConn, targetColl, targetPath) {
	var op = {
		path: path,
		targetConn: targetConn,
		targetColl: targetColl,
		targetPath: targetPath
	}
	Populate.paths.getArray(conn, coll).pushAndSave(op)
	Populate.run(op)
}

/**
 * Remove a populate operation
 * @param {string} conn
 * @param {string} coll
 * @param {string} path
 */
Populate.remove = function (conn, coll, path) {
	var ops = Populate.paths.getArray(conn, coll)
	ops.set(ops.filter(function (op) {
		return op.path !== path && path.indexOf(op.path + '.') !== 0
	}))
	// TODO: find a better way of doing this
	window.location.reload()
}

/**
 * Run all operations related to a collection
 * @param {string} conn
 * @param {string} coll
 */
Populate.runAll = function (conn, coll) {
	Populate.paths.getArray(conn, coll).forEach(Populate.run)
}

/**
 * Return all paths that are/will be populate
 * @param {string} conn
 * @param {string} coll
 * @returns {Array<string>}
 */
Populate.getPaths = function (conn, coll) {
	return Populate.paths.getArray(conn, coll).map(function (op) {
		return op.path
	})
}

/**
 * Check whether a given path is populated
 * @param {Array<string>} paths - populated paths (returned by getPaths)
 * @param {string} path - path to check
 * @returns {boolean}
 */
Populate.isPopulated = function (paths, path) {
	return paths.some(function (each) {
		return each === path || path.indexOf(each + '.') === 0
	})
}

/**
 * Run a given populate operation
 * @param {Object} op
 */
Populate.run = function (op) {
	var replaceSites = Object.create(null),
		pathParts = op.path.split('.'),
		ids

	// Collect ids to replace
	Query.result.forEach(function (doc) {
		var i, parent
		for (i = 0; i < pathParts.length; i++) {
			if (!doc ||
				typeof doc !== 'object' ||
				Array.isArray(doc) ||
				Query.specialTypes.indexOf(doc.constructor) !== -1) {
				return
			}
			parent = doc
			doc = doc[pathParts[i]]
		}

		if (doc instanceof ObjectId) {
			if (!(doc in replaceSites)) {
				replaceSites[doc] = []
			}
			replaceSites[doc].push(parent)
		}
	})
	ids = Object.keys(replaceSites)

	// Find in the DB
	if (!ids.length) {
		return
	}
	Panel.request('populate', {
		connection: op.targetConn,
		collection: op.targetColl,
		ids: ids,
		path: op.targetPath
	}, function (result) {
		var path = pathParts[pathParts.length - 1]
		result.docs.forEach(function (doc) {
			replaceSites[doc._id].forEach(function (each) {
				each[path] = op.targetPath ? doc[op.targetPath] : doc
			})
		})
		Query.populateResultTable()
	})
}
@@ -2752,16 +2752,22 @@
 %09%09var pa
+rentPa
 th = pat
@@ -2794,16 +2794,53 @@
 gth - 1%5D
+,%0A%09%09%09parts = op.targetPath.split('.')
 %0A%09%09resul
@@ -2933,16 +2933,22 @@
 %09each%5Bpa
+rentPa
 th%5D = op
@@ -2965,26 +2965,29 @@
 h ? 
-doc%5Bop.tar
 get
+In
 Path
-%5D
+(doc, parts)
  : d
@@ -3029,14 +3029,332 @@
 tTable()%0A%09%7D)
+%0A%0A%09// return doc%5Bpath%5D, but considering sub-docs%0A%09function getInPath(doc, parts) %7B%0A%09%09var i%0A%09%09for (i = 0; i %3C parts.length; i++) %7B%0A%09%09%09if (!doc %7C%7C%0A%09%09%09%09typeof doc !== 'object' %7C%7C%0A%09%09%09%09Array.isArray(doc) %7C%7C%0A%09%09%09%09Query.specialTypes.indexOf(doc.constructor) !== -1) %7B%0A%09%09%09%09return%0A%09%09%09%7D%0A%09%09%09doc = doc%5Bparts%5Bi%5D%5D%0A%09%09%7D%0A%09%09return doc%0A%09%7D
 %0A%7D

Fix to populate