var Ct_Page = new (Class.create({

	_scripts: null,
	_scriptDelegates: null,
	_components: null,
	_componentsTmp: null,
	_componentDelegates: null,
	_request: null,

	_domLoaded: null,
	_domLoadedDelegates: null,
	_windowLoaded: null,
	_windowLoadedDelegates: null,



	initialize: function() {
		this._scripts = new Hash;
		this._scriptDelegates = new Hash;
		this._components = new Hash;
		this._componentsTmp = new Hash;
		this._componentDelegates = new Hash;
		this._request = null;

		this._domLoaded = false;
		this._domLoadedDelegates = new Array;

		this._windowLoaded = false;
		this._windowLoadedDelegates = new Array;

		this.loadComponentScript('Ct_Component');
		this.registerComponent('Ct_Request');
		this.componentIsReady('Ct_Request', function() {
			this._request = this.getComponent('Ct_Request');
		}.bind(this));


		Event.observe(document, 'dom:loaded', function() {
			this._registerDomLoaded();
		}.bindAsEventListener(this));

		Event.observe(window, 'load', function() {
			this._registerWindowLoaded();
		}.bindAsEventListener(this));
	},


	_registerWindowLoaded: function() {
		this._windowLoaded = true;

		if (Object.isArray(this._windowLoadedDelegates)) {
			this._windowLoadedDelegates.each(function(delegate) {
				delegate();
			});
			delete this._windowLoadedDelegates;
			this._windowLoadedDelegates = new Array;
		}

	},


	windowLoaded: function(delegate) {
		if (Object.isFunction(delegate)) {
			if (this._windowLoaded === true) {
				delegate();
			} else {
				this._windowLoadedDelegates.push(delegate);
			}
		}
	},


	_registerDomLoaded: function() {
		this._domLoaded = true;

		if (Object.isArray(this._domLoadedDelegates)) {
			this._domLoadedDelegates.each(function(delegate) {
				delegate();
			});
			delete this._domLoadedDelegates;
			this._domLoadedDelegates = new Array;
		}

	},


	domLoaded: function(delegate) {
		if (Object.isFunction(delegate)) {
			if (this._domLoaded === true) {
				delegate();
			} else {
				this._domLoadedDelegates.push(delegate);
			}
		}
	},


	getComponent: function(componentName) {
		if (!!this._components.get(componentName)) {
			return this._components.get(componentName);
		} else {
			return null;
		}
	},


	registerScript: function(scriptName) {
		this._scripts.set(scriptName, true);

		if (Object.isArray(this._scriptDelegates.get(scriptName))) {
			this._scriptDelegates.get(scriptName).each(function(delegate) {
				delegate();
			});
			this._scriptDelegates.unset(scriptName)
		}
	},


	scriptIsReady: function(scriptName, delegate) {
		if (Object.isFunction(delegate)) {
			if (this._scripts.get(scriptName) === true) {
				delegate();
			} else {
				if (!Object.isArray(this._scriptDelegates.get(scriptName))) {
					this._scriptDelegates.set(scriptName, new Array);
				}
				this._scriptDelegates.get(scriptName).push(delegate);
			}
		}
	},



	registerComponent: function(componentName) {
		if (!!!this._componentsTmp.get(componentName)) {
			this._componentsTmp.set(componentName, true);

			if (this._scripts.get(componentName) !== true) {
				this.scriptIsReady('Ct_Component', function() {
				this.loadComponentScript(componentName);
				}.bindAsEventListener(this));
			}

			this.domLoaded(function(componentName1) {

				this.scriptIsReady(componentName1, function(componentName2) {
					var newComponent = eval('new ' + componentName2);
					this._components.set(componentName2, newComponent);
					if (Object.isArray(this._componentDelegates.get(componentName2))) {
						this._componentDelegates.get(componentName2).each(function(delegate) {
							delegate(newComponent);
						});
						this._componentDelegates.unset(componentName2)
					}
				}.bind(this, componentName1));

			}.bind(this, componentName));

		}
	},


	componentIsReady: function(componentName, delegate) {
		if (Object.isFunction(delegate)) {
			var component = this._components.get(componentName);
			if (!!component) {
				delegate(component);
			} else {
				if (!Object.isArray(this._componentDelegates.get(componentName))) {
					this._componentDelegates.set(componentName, new Array);
				}
				this._componentDelegates.get(componentName).push(delegate);
			}
		}
	},


	getRequest: function(ident, requestType, callback) {
		if (this._request == null) {
			throw 'Component Ct_Request is not registered';
		}
		return this._request.get(ident, requestType, callback);
	},

	refreshComponent: function(ident, response) {
		var element = $(ident);
		if (!Object.isElement(element)) {
			return;
		}
		var component = Ct_Page.getComponent('Ct_Component_Default');
		this._components.each(function(pair) {
			if (Object.isFunction(pair.value.isOwner) && pair.value.isOwner(ident)) {
				component = pair.value;
			}
		});
		component.refresh(ident, response);
		element.fire('Ct_Page:refresh');
	},


	loadComponentScript: function(componentName) {
		var fileName = '/js/' + componentName.gsub('_', '/') + '.js';
		this.loadJs(fileName);
	},


	loadComponentStyle: function(componentName) {
		var fileName = '/js/' + componentName.gsub('_', '/') + '/style.css';
		this.loadCss(fileName);
	},


	loadJs: function(src, params) {
		this.domLoaded(function(srcBinded) {
			var head = $$('head')[0];
			if (head.select('script[src*="' + srcBinded + '"]').length == 0) {
				var scriptElement = new Element("script", {"type": "text/javascript", "src": src});
				if (!!params) {
					$H(params).each(function(scriptElementBinded, item) {
						scriptElementBinded.writeAttribute(item.key, item.value);
					}.bind(this, scriptElement));
				}
				scriptElement.onload = function() {
					Ct_Page.registerScript(srcBinded);
				};
				scriptElement.onreadystatechange = function(scr) {
					if (scr.readyState == 'loaded' || scr.readyState == 'complete') {
						Ct_Page.registerScript(srcBinded);
					}
				}.bind(this, scriptElement);
				head.insert(scriptElement);
			} else {
				Ct_Page.registerScript(srcBinded);
			}
		}.bind(this, src));
	},


	loadCss: function(src) {
		this.domLoaded(function(srcBinded) {
			var head = $$('head')[0];
			if (head.select('link[href*="' + srcBinded + '"]').length == 0) {
				head.insert(new Element("link", {"type": "text/css", "rel": "stylesheet", "media": "screen", "href": src}));
			}
		}.bind(this, src));
	}

}));



