
var Lot = require ('./lot');
var LotIface = require ('./lot-iface');
var Spec = require ('./spec');
var Value = require ('./value');

module.exports = new Class
({
	Extends: Lot
	,Tag: 'vn-lot-query'
	,Properties:
	{
		fields:
		{ 
			type: Array
			,set: function (x)
			{
				this._fields = x;
				this._onSourceChange ();
			}
			,get: function ()
			{
				return this._fields;
			}
		},
		source:
		{ 
			type: LotIface
			,set: function (x)
			{
				this.link ({_source: x}, {change: this._onSourceChange});
				this._onSourceChange ();
			}
			,get: function ()
			{
				return this._source;
			}
		}
	}

	,initialize: function (props)
	{
		Object.assign (this, {
			_fields: null,
			_source: null,
			_lockSource: false,
			_specs: {}
		});
		this.parent (props);
	}

	,appendChild: function (child)
	{
		if (!(child instanceof Spec))
			throw new Error ('VnLotQuery: Child must be a Vn.Spec instance');

		this._specs[child.name] = child;
		this._onSourceChange ();
	}

	,_onSourceChange: function ()
	{
		if (this._lockSource)
			return;

		var params = this._source ? this._source.params : {};
		var myParams = {};

		for (var key in this._specs)
			myParams[key] = Value.simpleClone (params[key]);

		this.assign (myParams);
	}

	,assign: function (params)
	{
		params = this.transformParams (params);
		var diff = Value.partialDiff (this._params, params);

		if (diff)
		{
			Object.assign (this._params, diff);

			if (this.source)
			{
				this._lockSource = true;
				this.source.assign (diff);
				this._lockSource = false;
			}

			this._paramsChanged (diff);
			this.changed (diff);
		}
	}

	,setAll: function (params)
	{
		this.assign (params);
	}

	,transformParams: function (params)
	{
		var newParams = {};

		for (var key in this._specs)
		{
			var spec = this._specs[key];
			if (params[key])
				newParams[key] = cast (params[key], spec.type);
		}

		return Object.assign (params, newParams);
	}
});

function cast (value, type)
{
	switch (type)
	{
		case Boolean:
			return (/^(true|1)$/i).test (value);
		case Number:
			return 0 + new Number (value);
		case Date:
			var date = new Date (value);
			date.setHours (0, 0, 0, 0);
			return date;
		default:
		if (type instanceof Object)
			return JSON.parse (value);
		else
			return value;
	}
}
