/*\
title: $:/core/modules/widgets/let.js
type: application/javascript
module-type: widget

This widget allows defining multiple variables at once, while allowing
the later variables to depend upon the earlier ones.

```
<$let currentTiddler="target" value={{!!value}} currentTiddler="different">
  {{!!value}} will be different from <<value>>
</$let>
```

\*/

"use strict";

var Widget = require("$:/core/modules/widgets/widget.js").widget;

var LetWidget = function(parseTreeNode,options) {
	// Initialise
	this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
LetWidget.prototype = new Widget();

/*
Render this widget into the DOM
*/
LetWidget.prototype.render = function(parent,nextSibling) {
	this.parentDomNode = parent;
	this.computeAttributes();
	this.execute();
	this.renderChildren(parent,nextSibling);
};

LetWidget.prototype.computeAttributes = function() {
	// Before computing attributes, we must make clear that none of the
	// existing attributes are staged for lookup, even on a refresh
	var changedAttributes = {},
		self = this;
	this.currentValueFor = Object.create(null);
	$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
		var value = self.computeAttribute(attribute,{asList: true}),
			name = attribute.name;
		// Now that it's prepped, we're allowed to look this variable up
		// when defining later variables
		if(value !== undefined) {
			self.currentValueFor[name] = value;
		}
	});
	// Run through again, setting variables and looking for differences
	$tw.utils.each(this.currentValueFor,function(value,name) {
		if(self.attributes[name] === undefined || !$tw.utils.isArrayEqual(self.attributes[name],value)) {
			self.attributes[name] = value;
			self.setVariable(name,value);
			changedAttributes[name] = true;
		}
	});
	return changedAttributes;
};

LetWidget.prototype.getVariableInfo = function(name,options) {
	// Special handling: If this variable exists in this very $let, we can
	// use it, but only if it's been staged.
	if($tw.utils.hop(this.currentValueFor,name)) {
		var value = this.currentValueFor[name];
		return {
			text: value[0] || "",
			resultList: value
		};
	}
	return Widget.prototype.getVariableInfo.call(this,name,options);
};

/*
Refresh the widget by ensuring our attributes are up to date
*/
LetWidget.prototype.refresh = function(changedTiddlers) {
	var changedAttributes = this.computeAttributes();
	if($tw.utils.count(changedAttributes) > 0) {
		this.refreshSelf();
		return true;
	}
	return this.refreshChildren(changedTiddlers);
};

exports["let"] = LetWidget;
