﻿if (typeof tops === 'undefined') tops = {}

/**
* Function to get or set an object with a given string representation of the js reference
*
* tops.object(key)
* @param key <String> a string representation of a js reference.  E.g) "tops.toplets.photoplayer"
* @return <object> the object which can be referenced through "tops.toplets.photoplayer" in javascript
*
* tops.object(key, obj)
* @param key <String> the given key which can be referenced in javascript
*   @caution all of the preceding references from the key cannot be a string/number/boolean.  
*            E.g) if "tops.toplets.photoplayer" is the key, then "tops" and "tops.toplets" must not be string/number/boolean
* @param obj <object> the given object which to be set to the javascript reference
* @return <object> the object which can be referenced through "tops.toplets.photoplayer" in javascript
* @assert tops.resources.ready(key) will be called if obj has been successfully setup
*/
tops.object = (function () {
	function _get(string, context) {
		if (!string) return;
		if (typeof context === "undefined") {
			context = window;
		}

		var splitted = string.split(".");
		var head = splitted.shift();

		if (!splitted.length) {
			return context[head];
		}

		if (head in context) {
			return _get(splitted.join("."), context[head]);
		}
	}

	function _set(string, obj, context) {
		if (!string) return;
		if (typeof context === "undefined") {
			context = window;
		}

		var splitted = string.split(".");
		var head = splitted.shift();

		if (!splitted.length) {
			context[head] = obj;
			return context[head];
		} else {
			context[head] = context[head] || {};

			if (typeof context[head] === "object" || typeof context[head] === "function") {
				return _set(splitted.join("."), obj, context[head]);
			}
		}
	}

	return function (string, obj) {
		switch (arguments.length) {
			case 1:
				return _get(string);

			case 2:
				var o = _set(string, obj);
				// execute the callbacks pool if successfully set the object with the string reference
				if (o === tops.object(string) && !("topsReady" in o)) {
					tops.resources.ready(string);
				}
				return o;
		}
	}
})();

/**
* Misc Utilities function to be used for TOPS development
*/
tops.utilities = {
	/**
	* Determine whether the current window is the top most window within the browser
	* @return <Boolean>
	*/
	isInFrame: function () {
		return window.top !== window;
	},

	/**
	* Parsing a query into a JSON object
	* @param query <String> The query to parse.  E.g) "firstName=Alex&lastName=Tse"
	* @return <Object> JSON object representing the query.  E.g) { firstName : "Alex", lastName : "Tse" }
	*/
	parseQuery: function (query) {
		var json = {};
		var pairs = query.split("&");
		for (var i = 0, j = pairs.length; i < j; i++) {
			var pair = pairs[i];
			var s = pair.split("=");
			json[s.shift()] = s.join("=");
		}

		return json;
	},

	parseQueryString: function (QueryString) {
		var query = new String(QueryString);
		var pos = query.indexOf('?');
		if (pos > 0)
			query = query.substring(pos + 1);

		return tops.utilities.parseQuery(query);
	}
}

/**
* External resources related functions
*/
tops.resources = {
	// private, a dictionary storage which consist of the key and an array of callback functions
	pool: {},

	/**
	* Fire all the callback functions which has been registered to the given key
	* @param key <String> the registered key, usually would be a js object in string representation.  E.g) "tops.toplets.photoplayer"
	* @return <Object> tops.resources
	*/
	ready: function (key) {

		var o = tops.object(key);
		if (typeof o !== "undefined" && "topsReady" in o)
			o.topsReady = true;

		if (!this.pool[key]) return;

		var callback;
		while (callback = this.pool[key].shift()) {
			callback();
		}

		return this;
	},

	/**
	* Ensure the js object in string representation exist before executing the callback, add to the pool for later callback if not exist.
	* @param key <String> the string representation of a js object.  E.g) "tops.toplets.photoplayer"
	* @param callback <Function> callback function to be executed if the js object existed
	* @return <Object> tops.resources
	*/
	ensure: function (key, callback) {
		// fire callback automatically if object is defined or key is available but empty in pool
		var o = tops.object(key);
		if (typeof o !== "undefined" && (!("topsReady" in o) || !!o["topsReady"])) {
			callback();
			return;
		}

		if (!this.pool[key]) {
			this.pool[key] = []
		}
		this.pool[key].push(callback);

		return this;
	}
}




tops.ui = {

	popupModal: function (url, width, height, title) {
		
		//Opening in a frame?  Open popup from top page (this assumes this script is available.)
		if (tops.utilities.isInFrame()) {
			window.top.tops.ui.popupModal(url, width, height, title);
			return;
		}

		
		var $dialog = $('.js-modalPopup');
		if ($dialog.length == 0) {
			//Create the dialog for the first time.
			$dialog = $('<div class="js-modalPopup"><iframe src="' + url + '" width="100%" height="100%" frameborder="0" scrolling="no"></iframe></div>')
				.dialog({
					autoOpen: false,
					draggable: false,
					modal: true,
					position: "center",
					height: height,
					width: width,
					open: function () {
						//Close the dialog if clicked outside
						$('.ui-widget-overlay').die("click");
						$('.ui-widget-overlay').live("click", function () {
							$dialog.dialog("close");
							return false;
						});
					},
					resizable: false,
					title: title
				});
		}
		else {
			//Change the existing dialog's title and content.
			$dialog.dialog("option", "title", title).find('iframe').attr('src', url);

			if ($dialog.dialog('isOpen')) {

				//Re-center and re-size dialog.
				var left = ($(window).width() - width) / 2;
				var top = ($(window).height() - height) / 2;

				$dialog
					.dialog('option', 'height', height)
					.dialog("widget").animate({
						top: top >= 0 ? Math.ceil(top) + "px" : 0,
						left: left >= 0 ? Math.ceil(left) + "px" : 0,
						height: height + "px",
						width: width + "px"
					}, "slow");
			}
			else {

				//Open the dialog in the center of the viewport.
				$dialog
					.dialog('option', 'height', height)
					.dialog('option', 'position', 'center')
					.dialog('option', 'width', width)
					.dialog('open');
			}
		}
		return $dialog;
	},

	popupClose: function (redirect) {
		if (redirect == undefined) {
			if (tops.utilities.isInFrame()) {
				window.top.tops.ui.popupClose(redirect);
				return;
			}

			var $dialog = $('.js-modalPopup');
			if ($dialog.length > 0)
				$dialog.dialog("close")
		}
		else {
			if (tops.utilities.isInFrame())
				window.top.location = redirect;
			else
				window.location = redirect;
		}
	}
}

tops.identity = {
	topsReady: false,
	isAuthenticated: false,
	onLoad: function () {
		var cookie = $.cookie(tops.toplets.account_1.settings.topsCmsAuthCookieName);
		if (cookie === null) {
			tops.identity.isAuthenticated = false;
		}
		else {
			jQuery.extend(tops.identity, tops.utilities.parseQueryString(cookie));
			tops.identity.isAuthenticated = tops.identity.userName != undefined;
		}
		tops.resources.ready('tops.identity');
	}
};

/**
* Initializing objects
*/
tops.object("tops.toplets.settings", {})

tops.resources.ensure('tops.toplets.account_1', function () {
	tops.identity.onLoad();
});


