
var VnObject = require ('./object');

var scopeUid = 0;

module.exports = new Class
({
	Extends: VnObject

	,initialize: function (builder, objects, signalData, parentScope, lot)
	{
		this.builder = builder;
		this.objects = objects;
		this.signalData = signalData;
		this.parentScope = parentScope;
		this.uid = ++scopeUid;
		this.lot = lot;

		if (!signalData && parentScope)
			this.signalData = parentScope.signalData;

		this.parent ();
	}

	,init: function (extraObjects)
	{
		var contextMap = this.builder._contextMap;
		var objectMap = this.parentScope ? Object.create (this.parentScope.$) : {};
		this.$ = objectMap;

		for (var id in extraObjects)
			objectMap[id] = extraObjects[id];
		for (var id in contextMap)
			objectMap[id] = this.objects[contextMap[id]];
	}

	,getMain: function ()
	{
		return this.builder.getMain (this);
	}
	
	/**
	 * Fetchs a set of elements by it's tag name.
	 *
	 * @param {String} tagName The object tag name
	 * @return {Array[Object]} The list of objects or an empty array
	 */
	,getByTagName: function (tagName)
	{
		return this.builder.getByTagName (this, tagName);
	}

	/**
	 * Links all scope objects and connects it's events.
	 */
	,link: function ()
	{
		this.builder.link (this);
	}

	/**
	 * Replaces all ocurrences of {{value}} by it's corresponding value in the
	 * scope lot.
	 */
	,interpolate: function (string)
	{
		var self = this;

		function replaceFunc (token)
		{
			var key = token.substr (2, token.length - 4);
			var value = self.getLotValue (key);
			return value ? value : '';
		}

		return string.replace (/{{[\w_]+}}/g, replaceFunc);
	}

	,getLotValue: function (key)
	{
		var value = this.lot.$[key];

		if (value === undefined && this.parentScope)
			return this.parentScope.getLotValue (key);

		return value;
	}

	,getMethod: function (value, binded)
	{	
		if (this.signalData)
		{
			var method = this.signalData[value];

			if (method && binded)
				method = method.bind (this.signalData);
		}
		else
			var method = window[value];

		if (method === undefined)
			this.builder._showError ('Function \'%s\' not found', value);

		return method;
	}

	,getHtmlId: function (nodeId)
	{
		return 'vn-'+ this.uid +'-'+ nodeId;
	}
	
	,_destroy: function ()
	{
		var objects = this.objects;
	
		for (var i = objects.length; i--;)
		{
			var object = objects[i];

			if (object instanceof VnObject)
			{
				object.unref ();
				object.disconnectByInstance (this.builder.signalData);
			}
		}

		this.parent ();
	}
});
