Source: Odm.js

"use strict";

// Import external names locally
var Shared,
	Collection;

Shared = require('./Shared');

var Odm = function () {
	this.init.apply(this, arguments);
};

Odm.prototype.init = function (from, name) {
	var self = this;

	self.name(name);

	self._collectionDroppedWrap = function () {
		self._collectionDropped.apply(self, arguments);
	};

	self.from(from);
};

Shared.addModule('Odm', Odm);
Shared.mixin(Odm.prototype, 'Mixin.Common');
Shared.mixin(Odm.prototype, 'Mixin.ChainReactor');
Shared.mixin(Odm.prototype, 'Mixin.Constants');
Shared.mixin(Odm.prototype, 'Mixin.Events');

Collection = require('./Collection');

Shared.synthesize(Odm.prototype, 'name');
Shared.synthesize(Odm.prototype, 'state');
Shared.synthesize(Odm.prototype, 'parent');
Shared.synthesize(Odm.prototype, 'query');
Shared.synthesize(Odm.prototype, 'from', function (val) {
	if (val !== undefined) {
		val.chain(this);
		val.on('drop', this._collectionDroppedWrap);
	}

	return this.$super(val);
});

Odm.prototype._collectionDropped = function (collection) {
	this.drop();
};

Odm.prototype._chainHandler = function (chainPacket) {
	switch (chainPacket.type) {
		case 'setData':
		case 'insert':
		case 'update':
		case 'remove':
			//this._refresh();
			break;

		default:
			break;
	}
};

Odm.prototype.drop = function () {
	if (!this.isDropped()) {
		this.state('dropped');

		this.emit('drop', this);

		if (this._from) {
			delete this._from._odm;
		}

		delete this._name;
	}

	return true;
};

/**
 * Queries the current object and returns a result that can
 * also be queried in the same way.
 * @param {String} prop The property to delve into.
 * @param {Object=} query Optional query that limits the returned documents.
 * @returns {Odm}
 */
Odm.prototype.$ = function (prop, query) {
	var data,
		tmpQuery,
		tmpColl,
		tmpOdm;

	if (prop === this._from.primaryKey()) {
		// Query is against a specific PK id
		tmpQuery = {};
		tmpQuery[prop] = query;

		data = this._from.find(tmpQuery, {$decouple: false});
		tmpColl = new Collection();

		tmpColl.setData(data, {$decouple: false});
		tmpColl._linked = this._from._linked;
	} else {
		// Query is against an array of sub-documents
		tmpColl = new Collection();
		data = this._from.find({}, {$decouple: false});

		if (data[0] && data[0][prop]) {
			// Set the temp collection data to the array property
			tmpColl.setData(data[0][prop], {$decouple: false});

			// Check if we need to filter this array further
			if (query) {
				data = tmpColl.find(query, {$decouple: false});
				tmpColl.setData(data, {$decouple: false});
			}
		}

		tmpColl._linked = this._from._linked;
	}

	tmpOdm = new Odm(tmpColl);

	tmpOdm.parent(this);
	tmpOdm.query(query);

	return tmpOdm;
};

/**
 * Gets / sets a property on the current ODM document.
 * @param {String} prop The name of the property.
 * @param {*} val Optional value to set.
 * @returns {*}
 */
Odm.prototype.prop = function (prop, val) {
	var tmpQuery;

	if (prop !== undefined) {
		if (val !== undefined) {
			tmpQuery = {};
			tmpQuery[prop] = val;

			return this._from.update({}, tmpQuery);
		}

		if (this._from._data[0]) {
			return this._from._data[0][prop];
		}
	}

	return undefined;
};

/**
 * Get the ODM instance for this collection.
 * @returns {Odm}
 */
Collection.prototype.odm = function (name) {
	if (!this._odm) {
		this._odm = new Odm(this, name);
	}

	return this._odm;
};

Shared.finishModule('Odm');
module.exports = Odm;