
//= depends: zapi

/**
 * The main ZAPI page class.
 * @name ZAPI.Utils.Page
 * @constructor
 */
ZAPI.namespace('Utils').Page = Class.create(
	/** @scope ZAPI.Utils.Page.prototype */
	{
		/**
		 * Constructor for the ZAPI.Utils.Page class.
		 *
		 * @param options - An options Hash.
		 */
		initialize: function(options) {
			options = $H({
				'initializerSortCallback': function(pair) {
					return pair.key;
				}
			}).merge(options);

			this._objs = new Hash();
			this._initializers = new Hash();
			this._initializerSortCallback = options.get('initializerSortCallback');

			Event.observe(document, 'dom:loaded', this.pageInitialize.bind(this));
		},

		/** Set arbitrary values so they're easier to find. Returns the
		 * object set. */
		set: function(k, v) {
			return this._objs.set(k, v);
		},

		/** Get arbitrary values that were set by ZAPI.Utils.Page#set. */
		get: function(k) {
			return this._objs.get(k);
		},

		/** Unset arbitrary values that were set by ZAPI.Utils.Page#set. */
		unset: function(k) {
			return this._objs.unset(k);
		},

		/** Add a page initializer. */
		addInitializer: function(k, f, options) {
			options = $H({
				'fireImmediately': true
			}).merge(options);

			this._initializers.set(k, f);
			if (document.loaded && options.get('fireImmediately')) {
				f.defer();
			}
			return f;
		},

		/** Remove an initializer. */
		removeInitializer: function(k) {
			return this._initializers.unset(k);
		},

		/** Get an initializer. */
		getInitializer: function(k) {
			return this._initializers.get(k);
		},

		/** Runs the functions set with addInitializer() in alphabetical order.
		 * This helps avoid nonsense with dom:loaded events being fired off
		 * in an unpredictable manner, since the sorting is known. */
		pageInitialize: function() {
			this._initializers.sortBy(this._initializerSortCallback).each(function(pair) {
				pair.value();
			});
		}
	}
);
