/**
 * Main App class. Handles basic functionality
 * such as plugin registration and event handling.
 * Also provides handly functions such as how to
 * get a full URL from a Cake URL, and opening
 * popup windows.
 *
 * @author Mariano Iglesias
 */

var App = Class.create({
	/**
	 * Base URL to CakePHP application.
	 *
	 * @var string
	 * @access private
	 */
	baseUrl: '',

	/**
	 * List of registered plugins.
	 *
	 * @var array
	 * @access private
	 */
	plugins: [],

	/**
	 * AJAX responders.
	 *
	 * @var object
	 * @access private
	 */
	__responders: false,

	/**
	 * Initializes this JS component
	 *
	 * @access public
	 */
	initialize: function()
	{
		var self = this;

		this.__setBaseUrl();
		this.registerAjaxResponders();

		// Register the DOM update event triggerer

		document.observe('dom:loaded', function(event) {
			self.domUpdated();
		});
	},

	/**
	 * Called when the DOM object has updated (after window
	 * load or after an AJAX complete)
	 *
	 * @access public
	 */
	domUpdated: function()
	{
		// Dispatch DOM update event on plugins

		this.plugins.each(function(plugin)
		{
			if (typeof plugin == 'object' && typeof plugin.domUpdated == 'function')
			{
				plugin.domUpdated();
			}
		});
	},

	/**
	 * Registers a plugin to the list of plugins.
	 *
	 * @param object plugin Plugin to register
	 * @access public
	 */
	registerPlugin: function(plugin)
	{
		this.plugins.push(plugin);
	},

	/**
	 * Unregisters a plugin from the list of plugins.
	 *
	 * @param object plugin Plugin to unregister
	 * @access public
	 */
	unregisterPlugin: function(plugin)
	{
		this.plugins = this.plugins.without(plugin);
	},

    /**
     * Get the full URL to a CakePHP action
     *
     * @param string url CakePHP URL
     * @return string Full URL
     * @access public
     */
	url: function(url)
	{
		if (url.match(/^\//))
		{
			url = url.substr(1);
		}

		return this.baseUrl + url;
	},
	
	/**
	 * Show loading message, used when by AJAX responder callback.
	 *
	 * @access public
	 */
	startLoading: function()
	{
		$('content').hide();
	},

	/**
	 * Hide loading message, used when by AJAX responder callback.
	 *
	 * @access public
	 */
	endLoading: function()
	{
		Effect.Appear('content', {
			afterFinish: function() {
				div = $$("#overflow");
				if (div.length > 0) { 
					div[0].scrollTop = 0; 
				}
			}
		});
	},
	
	/**
	 * Register AJAX responders for showing loading messages.
	 *
	 * @access public
	 */
	registerAjaxResponders: function()
	{
		if (!this.__responders)
		{
			var self = this;

			this.__responders = {
				onCreate: function() {
					if (Ajax.activeRequestCount > 0)
					{
						self.startLoading();
					}
				},

				onComplete: function() {
					if (Ajax.activeRequestCount == 0)
					{
						self.endLoading();
						self.domUpdated();
					}
				}
			};
		}

		Ajax.Responders.register(this.__responders);
	},

	/**
	 * Unregister AJAX responders for showing loading messages.
	 *
	 * @access public
	 */
	unregisterAjaxResponders: function()
	{
		if (this.__responders)
		{
			Ajax.Responders.unregister(this.__responders);
		}
	},

	/**
	 * Set current CakePHP base URL to this application.
	 *
	 * @access private
	 */
	__setBaseUrl: function()
	{
		var self = this;
		var javascriptFile = 'prototype';

		// In case we are being packaged, use the package file as file locator

		if (typeof(__PackagedJavaScriptFile) != 'undefined')
		{
			javascriptFile = __PackagedJavaScriptFile;
		}

		if (!javascriptFile.match(/.*\.js$/))
		{
			javascriptFile += '.js';
		}

		if (javascriptFile.charAt(0) == '/')
		{
			javascriptFile = javascriptFile.substr(1);
		}

		var regex = new RegExp('\\/([^\\/]*)\\/' + javascriptFile.replace(/\./g, '\\.') + '(\\?.*)?$');

		$A(document.getElementsByTagName("script")).findAll( function(s) {
			return (s.src && s.src.match(regex))
		}).each( function(s) {
			var path = s.src.replace(regex,'');

			self.baseUrl = path + '/';
		});
	}
});

// Instantiate main App class

App = new App();

/**
 * App base plugin class. Provides a base for
 * all App plugins. It must be extended.
 *
 * @author Mariano Iglesias
 */

var AppPlugin = Class.create({
	/**
	 * Initializes this plugin. If you override this method,
	 * make sure to call _register() to register your plugin.
	 * If you are looking for an initialization method, better
	 * extend startup instead.
	 *
	 * @access public
	 */
	initialize: function()
	{
		// Startup plugin

		this.startup();

		// Register this plugin

		this._register();
	},

	/**
	 * Starts the plugin.
	 *
	 * @access public
	 */
	startup: function()
	{
	},

	/**
	 * Called when the DOM object has updated (after window
	 * load or after an AJAX complete)
	 *
	 * @access public
	 */
	domUpdated: function()
	{
	},

  /**
   * Get the full URL to a CakePHP action
   *
   * @param string url CakePHP URL
   * @return string Full URL
   * @access public
   */
	url: function(url)
  {
		return App.url(url);
  },

  /**
   * Registers this plugin.
   *
   * @access protected
   */
  _register: function()
  {
		App.registerPlugin(this);
  }
});
