//= require <mootools-core-1.3-full-nocompat>
//= require <uiframework/UIComponent>
//= require <uiframework/URLUtil>
//= require <findsalons/ApplicationFacade>
//= require <findsalons/ContentArea>
//= require <finsalons/AccoutSetupView>
//= require <findsalons/AccountSetupViewMediator>
//= require <uiframework/UICEvent>

/**
 * Shell object for centering and semi-fluid layout. This object contains all
 * children used in this application.
 */
var Shell = function()
{
	this.Extends = UIComponent;

	/**
	 * The ApplicationFacade Singleton
	 * 
	 * @type ApplicationFacade
	 */
	this.facade = null;
	// Children
	/**
	 * The create account overlay.
	 * 
	 * @type Panel
	 */
	this.accountSetupForm = null;
	/**
	 * The div used as the background
	 * 
	 * @type UIComponent
	 */
	this.background = null;
	/**
	 * The top left corner graphic
	 * 
	 * @type UIComponent
	 */
	this.topLeftDiv = null;
	/**
	 * The top right corner graphic
	 * 
	 * @type UIComponent
	 */
	this.topRightDiv = null;
	/**
	 * The top gradient grapgic
	 * 
	 * @type UIComponent
	 */
	this.topShellGradDiv = null;
	/**
	 * @type UIComponent
	 */
	this.bottomLeftDiv = null;
	/**
	 * @type UIComponent
	 */
	this.bottomRightDiv = null;
	/**
	 * @type UIComponent
	 */
	this.bottomShellGradDiv = null;
	/**
	 * @type UIComponent
	 */
	this.contentArea = null;
	/**
	 * @type UIComponent
	 */
	this.leftArrow = null;
	/**
	 * @type UIComponent
	 */
	this.rightArrow = null;
	
	/**
	 * @type UIComponent
	 */
	this._modalShield = null;
	/**
	 * Flag indicating whether or not the Shell should look for new links on the
	 * page and attach the link functionality to them
	 * 
	 * @type Boolean
	 */
	this.linkRefreshPending = true;
	/**
	 * Number indicating the last Y position of the link arraows
	 * 
	 * @type Number
	 */
	this.lastPosY = 0;
	/**
	 * @type Fx.Morph
	 */
	this.leftMorph = null;
	/**
	 * @type Fx.Morph
	 */
	this.rightMorph = null;

	this.initialize = function()
	{
		this.parent('shell');
		this.facade = ApplicationFacade.getInstance();
		// Event hander biding overwrite
		this.link_mouseOverHandler = this.link_mouseOverHandler.bind(this);
		this.link_mouseOutHandler = this.link_mouseOutHandler.bind(this);
		this.link_clickHandler = this.link_clickHandler.bind(this);
	};

	this.initializationComplete = function()
	{
		this.facade.startup(this);
		this.parent();
	};

	/**
	 * Creates the children used in the application shell.
	 */
	this.createChildren = function()
	{
		this.background = new UIComponent('div', {
			id : "background"
		});
		this.addChild(this.background);

		this.topLeftDiv = new UIComponent('div',{
			id : "topLeftCornerShell"
		});
		this.addChild(this.topLeftDiv);

		this.topRightDiv = new UIComponent('div',{
			id : "topRightCornerShell"
		});
		this.addChild(this.topRightDiv);

		this.topShellGradDiv = new UIComponent('div',{
			id : "topShellGrad"
		});
		this.addChild(this.topShellGradDiv);

		// Bottom Gradient
		this.bottomLeftDiv = new UIComponent('div',{
			id : "bottomLeftCornerShell"
		});
		this.addChild(this.bottomLeftDiv);

		this.bottomRightDiv = new UIComponent('div',{
			id : "bottomRightCornerShell"
		});
		this.addChild(this.bottomRightDiv);

		this.bottomShellGradDiv = new UIComponent('div',{
			id : "bottomShellGrad"
		});
		this.addChild(this.bottomShellGradDiv);

		this.contentArea = new ContentArea();
		this.addChild(this.contentArea);

		this.leftArrow = new UIComponent('div',	{
			"class" : "leftArrowOrange"
		});
		this.addChild(this.leftArrow);
		this.rightArrow = new UIComponent('div',{
			"class" : "rightArrowOrange"
		});
		this.addChild(this.rightArrow);
	};

	this.childrenCreated = function()
	{
		this.parent();
		var options =
		{
			duration : 500,
			transition : Fx.Transitions.Quint.easeOut
		};
		this.leftMorph = new Fx.Morph(this.leftArrow.element, options);
		this.rightMorph = new Fx.Morph(this.rightArrow.element, options);

		this.initializeLinks();
		this.addEventListener("added", this.uIComponent_addedHandler, true, 0, this);
	};

	/**
	 * @inheritDoc
	 */
	this.updateDisplayList = function(width, height)
	{
		var paddingTop = 10;
		var paddingRight = 10;
		var paddingBottom = 10;
		var paddingLeft = 10;

		this.parent(width, height);
		this.topLeftDiv.setActualSize(25, 234);
		this.topLeftDiv.move(paddingLeft, paddingTop);

		this.topRightDiv.setActualSize(25, 234);
		this.topRightDiv.move(this.width() - this.topRightDiv.width() - paddingRight, paddingTop);

		this.topShellGradDiv.setActualSize(this.width() - this.topLeftDiv.width() - this.topRightDiv.width() - paddingLeft - paddingRight, 234);
		this.topShellGradDiv.move(this.topLeftDiv.width() + this.topLeftDiv._x, paddingTop);

		this.bottomLeftDiv.setActualSize(25, 102);
		this.bottomLeftDiv.move(paddingLeft, this.height() - this.bottomLeftDiv.height() - paddingBottom);

		this.bottomRightDiv.setActualSize(25, 102);
		this.bottomRightDiv.move(this.width() - this.bottomRightDiv.width() - paddingRight, this.bottomLeftDiv._y);

		this.bottomShellGradDiv.setActualSize(this.topShellGradDiv.width(), 102);
		this.bottomShellGradDiv.move(this.bottomLeftDiv.width() + this.bottomLeftDiv._x, this.bottomLeftDiv._y);

		this.background.setActualSize(this.width() - paddingRight - paddingLeft, this.height() - paddingTop - paddingBottom - this.topShellGradDiv.height() - this.bottomShellGradDiv.height() + 2);
		this.background.move(this.topLeftDiv._x, this.topShellGradDiv.height() + this.topShellGradDiv._y - 1);

		this.contentArea.setActualSize(width - paddingLeft - paddingRight, height - paddingTop - paddingBottom);
		this.contentArea.move(paddingLeft, paddingTop);

		this.leftArrow.setActualSize(8, 8);
		this.rightArrow.setActualSize(8, 8);

		if (this.accountSetupForm && this.accountSetupForm.parentComponent)
			this.accountSetupForm.move((width - this.accountSetupForm.width()) / 2, (height - this.accountSetupForm.height()) / 2);
	};

	/**
	 * Targets and captures link interaction across the shell to add custom
	 * behaviors.
	 */
	this.initializeLinks = function()
	{
		// Capture all link clicks
		var links = $$('a');
		var i = links.length;
		while (i--)
		{
			var link = links[i];
			var isImg = link.getChildren('img').length;
			if (!isImg)
			{
				link.addEvent("mouseover", this.link_mouseOverHandler);
				link.addEvent("mouseout", this.link_mouseOutHandler);
			}
			link.addEvent('click', this.link_clickHandler);
		}
		this.linkRefreshPending = false;
	};

	/**
	 * Handler for mouse over events on page links - Triggers the link animation
	 * indicating a mouse over state.
	 * 
	 * @param event
	 *            Event object created by the MooTools framework.
	 */
	this.link_mouseOverHandler = function(event)
	{
		var link = event.target;
		var size = link.getSize();
		var location = link.getPosition(this.element);
		// Place 2x the heigh below the link.
		var posY = this.leftArrow._y < location.y ? location.y - 8 : location.y + size.y;
		this.lastPosY = this.leftArrow._y;
		this.leftArrow.move(location.x - 8, posY);
		this.rightArrow.move(location.x + size.x, posY);
		// begin the animation.
		var params =
		{
			opacity : [ 0.0, 1.0 ],
			top : [ this.leftArrow._y, ((size.y - 8) / 2) + location.y ]
		};
		this.leftMorph.cancel().start(params);
		this.rightMorph.cancel().start(params);
	};

	/**
	 * Mouse out handler for page links - Triggers the animation back to the
	 * mouse out state.
	 * 
	 * @param event
	 *            Event object created by the MooTools framework.
	 */
	this.link_mouseOutHandler = function(event)
	{
		var link = event.target;
		var size = link.getSize();
		var location = link.getPosition(this.element);
		var posY = this.lastPosY < location.y ? location.y + size.y : location.y - 8;
		var params =
		{
			opacity : [ 1.0, 0.0 ],
			top : [ this.leftArrow.getStyle('top').toInt(), posY ]
		};
		this.leftMorph.cancel().start(params);
		this.rightMorph.cancel().start(params);
	};

	/**
	 * Inspects the link to determine if the URL is directed to the current
	 * domain. If so, the link is converted to a hash, the default behavior is
	 * stopped and a request is made to change the hash in the address window.
	 * 
	 * @param event
	 *            Event object created by the MooTools framework.
	 */
	this.link_clickHandler = function(event)
	{
		var link = event.target.get('tag') == "a" ? event.target : event.target.getParent('a');

		var regExp = new RegExp("^(http://" + document.domain + ")");
		if (regExp.test(link))
		{
			this.link_mouseOutHandler(event);
			event.stop();
			// -------------------------------------
			var href = link.get('href');
			var hash = URLUtil.searchStringToObject(href);
			var merged = Object.merge(
			{
				action: false,
				category: false,
				listing: false
			}, hash);
			this.dispatchEvent(new UICEvent("setHash", false, false, merged));
		}
	};

	this.uIComponent_addedHandler = function()
	{
		if (this.linkRefreshPending)
			return;
		this.callLater(this.initializeLinks.bind(this));
	};

	this.accountSetupForm_cancelHandler = function()
	{
		this.dispatchEvent(new UICEvent("setHash", false, false, {action: false}));
	};

	/**
	 * Shows / Hides the account setup form.
	 * @param show Boolean indicating whether or not to
	 * show the form.
	 */
	this.showAccoutSetupForm = function(show /* Boolean */)
	{
		if (!this.accountSetupForm && !show)
			return;
		var rect;
		var x;
		var y;
		if (!show && this.contains(this.accountSetupForm))
		{
			this.removeChild(this.accountSetupForm);
			x = (this._width - 400) / 2;
			y = (this._height - 200) / 2;
			rect = {x:x, y:y, width:400, height:200};
			this.accountSetupForm.expandedRect(rect);
			this.accountSetupForm.expanded(false);
			application.showModal(false);
			return;
		}
		else if (show && !this.accountSetupForm)
		{
			this.accountSetupForm = new AccoutSetupView({styles:{"z-index":11}});
			this.accountSetupForm.expandable(true);
			this.accountSetupForm.setActualSize(400, 200); // 16:9 aspect ratio
			this.accountSetupForm.addEventListener("cancel", this.accountSetupForm_cancelHandler, false, 0, this);
			this.accountSetupForm.addEventListener("updateComplete", this.accountSetupForm_updateCompleteHandler, false, 0, this);
		}
		
		if (show && !this.contains(this.accountSetupForm))
		{
			x = (this._width - 560) / 2;
			y = (this._height - 315) / 2;
			rect = {x:x, y:y, width:560, height:315};
			this.accountSetupForm.expandedRect(rect);
			this.addChild(this.accountSetupForm);
			this.accountSetupForm.expanded(true);
			application.showModal(true);
		}
	};
	
	this.accountSetupForm_updateCompleteHandler = function()
	{
		this.accountSetupForm.removeEventListener("updateComplete", this.accountSetupForm_updateCompleteHandler);
		this.dispatchEvent(new UICEvent("registerMediator", true, false, [ AccountSetupViewMediator, this.accountSetupForm ]));
	}
};
Shell = new Class(new Shell());
