﻿
//Singleton
var TemplateControlRelationManager = new function ()
{
	this.dataContainerId = null;
	this.relations = [];
	this.ruleFuncs = {};
	this.Initialize = function (dataContainerId)
	{
		this.dataContainerId = dataContainerId;
		var jsonData = $("#" + dataContainerId).val();

		if (jsonData != null && jsonData != "" && jsonData.length > 0)
		{
			//deserialize json
			//this.relations = ...;
			this.relations = JSON.parse(unescape(jsonData).replace(/\+/g, " "));
			if (!this.relations)
				this.relations = [];

			//NOTE: the relation rules are processed AFTER all OnPageLoad callbacks have finished executing
			Page.AddOnPageLoaded(function ()
			{
				TemplateControlRelationManager.ProcessRelations();
			});
		}
	}

	this.RegisterRule = function (ruleType, f)
	{
		this.ruleFuncs[ruleType] = f;
	}

	this.ClearRelations = function ()
	{
		this.relations = [];
	}

	this.UpdateDataContainer = function ()
	{
		if (this.dataContainerId)
			$("#" + this.dataContainerId).val(escape(this.ToJSON()));
	}

	this.GetRelations = function ()
	{
		return this.relations;
	}

	this.AddRelationsFromJSON = function (data)
	{
		if (data && data != "")
		{
			this.relations = JSON.parse(data);
			if (!this.relations)
				this.relations = [];
		}
	}

	this.AddRelation = function (relation)
	{
		if (relation)
		{
			this.relations.push(relation);
			this.UpdateDataContainer();
		}
	}

	this.ProcessRelations = function ()
	{
		//foreach rule
		//	find reference to targetcontrol
		//		find reference to sourcecontrol
		//		apply changes
		for (var i = 0; i < this.relations.length; i++)
		{
			var relation = this.relations[i];
			var targetControlId = relation.targetControlId;
			this.ApplyRules(relation, targetControlId);
		}
	}

	this.ToJSON = function ()
	{
		return JSON.stringify(this.relations);
	}


	//
	//
	//
	this.AddRule = function (relation, rule)
	{
		relation.rules.push(rule);
	}

	this.ApplyRules = function (relation, targetControlId)
	{
		for (var i = 0; i < relation.rules.length; i++)
		{
			var rule = relation.rules[i];
			var f = this.ruleFuncs[rule.ruleType];
			if (f)
				f(targetControlId, rule);
		}
	}
};

/**************************
	CONTROL RELATION RULES
**************************/
var ENUM_RELATIONRULETYPE =
{
None: 0,
Position: 1,
Dimension: 2
};

//
function TemplateControlRelation()
{
this.name = "";
this.targetControlId = null;
this.rules = [];
}

function TemplateControlRelationRule()
{
this.ruleType = ENUM_RELATIONRULETYPE.None;
}

/*****************************************
Position
*****************************************/
var ENUM_HORISONTALPOSITIONPLACEMENTS =
{
	None:			0,
	LeftOf:			1, 
	LeftMargin:		2,
	RightMargin:	3,
	RightOf:		4
};

var ENUM_VERTICALPOSITIONPLACEMENTS =
{
	None:			0,
	TopOf:			1,
	TopMargin:		2,
	BottomMargin:	3,
	BottomOf:		4
};

function TemplateControlRelationRule_Position()
{
	this.sourceControlId = null;
	this.horisontalOffset = 0;
	this.verticalOffset = 0;

	this.horisontalPlacement = ENUM_HORISONTALPOSITIONPLACEMENTS.None;
	this.verticalPlacement = ENUM_VERTICALPOSITIONPLACEMENTS.None;
	this.ruleType = ENUM_RELATIONRULETYPE.Position;
}

//Inherit from TemplateControlRelationRule

TemplateControlRelationRule_Position.prototype = new TemplateControlRelationRule();
TemplateControlRelationManager.RegisterRule(ENUM_RELATIONRULETYPE.Position, function (targetControlId, rule)
{
	if (!rule.sourceControlId)
		return;

	var sourceControl = Template.FindControl(rule.sourceControlId);
	var targetControl = Template.FindControl(targetControlId);

	if (!targetControl || !sourceControl)
		return;

	var srcControlObject = $(sourceControl.GetControlObject());
	var targetControlObject = $(targetControl.GetControlObject());
	var targetData =
	{
		left: parseInt(targetControlObject.position().left),
		top: parseInt(targetControlObject.position().top),
		width: parseInt(targetControlObject.outerWidth()),
		height: parseInt(targetControlObject.outerHeight())
	};

	var sourceData =
	{
		left: parseInt(srcControlObject.position().left),
		top: parseInt(srcControlObject.position().top),
		width: parseInt(srcControlObject.outerWidth()),
		height: parseInt(srcControlObject.outerHeight())
	};

	//
	switch (rule.horisontalPlacement)
	{
		case ENUM_HORISONTALPOSITIONPLACEMENTS.LeftOf:
			targetData.left = sourceData.left - targetData.width + rule.horisontalOffset;
			break;

		case ENUM_HORISONTALPOSITIONPLACEMENTS.LeftMargin:
			targetData.left = sourceData.left + rule.horisontalOffset;
			break;

		case ENUM_HORISONTALPOSITIONPLACEMENTS.RightMargin:
			targetData.left = sourceData.left + sourceData.width - targetData.width + rule.horisontalOffset;
			break;

		case ENUM_HORISONTALPOSITIONPLACEMENTS.RightOf:
			targetData.left = sourceData.left + sourceData.width + rule.horisontalOffset;
			break;

		default: break;
	}

	//
	switch (rule.verticalPlacement)
	{
		case ENUM_VERTICALPOSITIONPLACEMENTS.TopOf:
			targetData.top = sourceData.top - targetData.height + rule.verticalOffset;
			break;

		case ENUM_VERTICALPOSITIONPLACEMENTS.TopMargin:
			targetData.top = sourceData.top + rule.verticalOffset;
			break;

		case ENUM_VERTICALPOSITIONPLACEMENTS.BottomMargin:
			targetData.top = sourceData.top + sourceData.height - targetData.height + rule.verticalOffset;
			break;

		case ENUM_VERTICALPOSITIONPLACEMENTS.BottomOf:
			targetData.top = sourceData.top + sourceData.height + rule.verticalOffset;
			break;

		default: break;
	}

	targetControlObject.css(
	{
		left: targetData.left + "px",
		top: targetData.top + "px"
	});
});

//
function TemplateControlRelationRule_Dimension()
{
	this.sourceControlId = null;
	this.makeSameWidth = false;
	this.makeSameHeight = false;
	this.widthOffset = 0;
	this.heightOffset = 0;
	
	this.ruleType = ENUM_RELATIONRULETYPE.Dimension;
}

//Inherit from TemplateControlRelationRule
TemplateControlRelationRule_Dimension.prototype = new TemplateControlRelationRule();

//Register this rule with TemplateControlRelationManager. This function will be called if there's a rule whose ruletype is ENUM_RELATIONRULETYPE.Dimension
TemplateControlRelationManager.RegisterRule(ENUM_RELATIONRULETYPE.Dimension, function (targetControlId, rule)
{
	if (!rule.sourceControlId)
		return;

	var sourceControl = Template.FindControl(rule.sourceControlId);
	var targetControl = Template.FindControl(targetControlId);

	if (!targetControl || !sourceControl)
		return;

	var srcControlObject = $(sourceControl.GetControlObject());
	var targetControlObject = $(targetControl.GetControlObject());
	var targetData =
	{
		width: parseInt(targetControlObject.outerWidth()),
		height: parseInt(targetControlObject.outerHeight())
	};

	var sourceData =
	{
		width: parseInt(srcControlObject.outerWidth()),
		height: parseInt(srcControlObject.outerHeight())
	};

	if (rule.makeSameWidth)
		targetControlObject.width((sourceData.width + rule.widthOffset) + "px");

	if (rule.makeSameHeight)
		targetControlObject.height((sourceData.height + rule.heightOffset) + "px");
});


try
{
	if (null != EventManager)
	{
		EventManager.AddListener("EVENT_ENDDRAG", EventManager.CreateEventListener("TemplateControlRelationManager:EVENT_ENDDRAG", function() { TemplateControlRelationManager.ProcessRelations(); }, null));
		EventManager.AddListener("EVENT_ENDRESIZE", EventManager.CreateEventListener("TemplateControlRelationManager:EVENT_ENDRESIZE", function() { TemplateControlRelationManager.ProcessRelations(); }, null));
		EventManager.AddListener("EVENT_CONTROLPROPERTIESUPDATED", EventManager.CreateEventListener("TemplateControlRelationManager:EVENT_CONTROLPROPERTIESUPDATED", function() { TemplateControlRelationManager.ProcessRelations(); }, null));
		EventManager.AddListener("EVENT_CONTROLCONTENTCHANGED", EventManager.CreateEventListener("TemplateControlRelationManager:EVENT_CONTROLCONTENTCHANGED",function() { TemplateControlRelationManager.ProcessRelations(); }, null));
	}
}
catch (err)
{
}
