var NameSpace = Class.create();
NameSpace.prototype = {

	initialize: function() {
		this._loggerSink = null;
		this._classes = {};
		this.__waiters = {};
		this.__wcounter = 0;
		this.__wclass = {};
		this.__swfwrapper = {};
		this._isInRequire = 0;
		this._theVersion = '';
		this._ovlRef = null;
		this._audRef = null;
		this._coRef = null;
		this._gateway = null;
		this._objRef = {};
		this._ovlWaiters = new Array();
		this._startupSequence = new Array();
		this._modalList = new Array();

		try
		{
			this._gateway = window.top._dadanet;
		}
		catch(err)
		{
			//Ignore security errors...
			//console.debug("Overlay error %s", err);
		}
		finally
		{
			//Security error or no object found...
//			if(!this._gateway)
//				this._gateway = this;
		}

		try
		{
			if(_useVersion)
				this._theVersion = "?v="+_useVersion;
		}catch(er) {};
	},

	createClass: function(cname, proto) {
		//console.debug("createClass %s", cname);
		if(typeof(this._classes[cname]) == 'undefined')
		{
			this._classes[cname] = Class.create();
			this._classes[cname].prototype = proto;
		}

		if(typeof(this.__wclass[cname]) != 'undefined')
		{
			while(this.__wclass[cname].length)
			{
				var c = this.__wclass[cname].pop();
				if(this.__waiters[c])
				{
					this.__waiters[c].counter--;
					this._flushWaiter(c, cname);
					if(this.__waiters[c] == 'flushed')
					{
						delete(this.__waiters[c]);
					}
				}
			}
			delete(this.__wclass[cname]);
		}
	},

	_flushWaiters: function()
	{
		var kill = new Array();
		for(var i in this.__waiters)
		{
			if(this.__waiters.hasOwnProperty(i))
			{
				this._flushWaiter(i, '_globalFlush');
				if(this.__waiters[i] == 'flushed')
					kill.push(i);
			}
		}
		while(kill.length)
		{
			i = kill.pop();
			delete(this.__waiters[i]);
		}
	},

	_flushWaiter: function(wn, cname)
	{
		if(this.__waiters[wn] == 'flushed')
			return;

		if(this.__waiters[wn].counter == 0)
		{
			var foo = this.__waiters[wn];
			this.__waiters[wn] = 'flushed';
			foo.funct.apply(foo.obj, foo.args);
		}
		else if((this._isInRequire == 0) && (this.__waiters[wn].counter < 0))
		{
			alert("Wrong class count: "+wn+" "+cname+" "+this.__waiters[c].counter);
			throw(new Error("Wrong class count: "+wn+" "+cname+" "+this.__waiters[c].counter));
		}
	},

	definedClass: function(cname) {
		return(typeof(this._classes[cname]) != 'undefined');
	},

	isInstance: function(obj, cname) {
		return(this.definedClass(cname) && (obj instanceof this._classes[cname]));
	},

	requireClass: function(names, fun, thisObj) {
		//console.debug("startRequire %s", names);
		this._isInRequire++;
		var tot = 0;
		var done = {};

		if(names)
		{
			for(var i = 0; i < names.length; i++)
			{
				var cname = names[i].split("/").pop();
				if(!done[cname] && typeof(this._classes[cname]) == 'undefined')
				{
					done[cname] = true;
					if(tot == 0)
					{
						var args = $A(arguments);
						args.splice(0,3);
						this.__waiters["w"+this.__wcounter] = {
							counter: -1,
							funct: fun,
							obj: thisObj,
							args: args
						};
					}
	
					tot++;
	
					if(typeof(this.__wclass[cname]) == 'undefined')
						this.__wclass[cname] = [];
	
					this.__wclass[cname].push("w"+this.__wcounter);
	
					this._loadClass(names[i], cname);
				}
			}
		}

		if(tot > 0)
		{
			this.__waiters["w"+this.__wcounter].counter += tot+1;
			this.__wcounter++;
		}
		else
		{
			var args = $A(arguments);
			args.splice(0,3);
			fun.apply(thisObj, args);			
		}

		this._isInRequire--;
		//console.debug("endRequire");
		this._flushWaiters();
	},

	_loadClass: function(pname, cname) {
		if(!$('dn_cl_'+cname))
		{
			//console.debug("loadClass %s",pname);
			var head = document.getElementsByTagName('head').item(0);
			var script = document.createElement('script');
			script.src = _jsDestDomain+'/'+pname+'.js'+this._theVersion;
			script.type = 'text/javascript';
			script.id = 'dn_cl_'+cname;
			head.appendChild(script);
			//TODO: Gestire TIMEOUT per errori!
		}
	},

	createSWFWrapper: function(flid, obj) {
		if(typeof(this.__swfwrapper[flid]) == 'undefined')
		{
			this.__swfwrapper[flid] = obj;
		}
		else
		{
			throw(new Error("SWF already wrapped for id: "+flid));
		}
	},

	removeSWFWrapper: function(flid, obj) {
		if(this.__swfwrapper[flid] == obj)
		{
			delete(this.__swfwrapper[flid]);
		}
	},

	getSWFObject: function(flid) {
		if(document[flid])
		{
			return(document[flid]);
		}
		else if(window[flid])
		{
			return(window[flid]);
		}

		return null;
	},

	_flashCall: function(flid, fname) {
		if(typeof(this.__swfwrapper[flid]) != 'undefined')
		{
			args = $A(arguments);
			args.splice(0,2);
			if(this.__swfwrapper[flid]['_SWFForceID'])
			{
				args.unshift(flid);
			}

			return(this.__swfwrapper[flid][fname].apply(this.__swfwrapper[flid], args));
		}
		else
		{
			throw(new Error("Call to unwrapped SWF for id: "+flid));
			return(null);
		}
	},

	overlayWatch: function(tgtObj) {
		if(this._ovlRef)
		{
			this._ovlRef.addListener('overlayBegin',tgtObj);
			this._ovlRef.addListener('overlayEnd',tgtObj);
		}
		else
		{
			this._ovlWaiters.push(tgtObj);
		}
	},

	registerOverlay: function(ovl) {
		if(this._ovlRef)
		{
			throw(new Error("Overlay already registered!"));
		}
		else
		{
			this._ovlRef = ovl;
			while(this._ovlWaiters.length)
			{
				var tgtObj = this._ovlWaiters.shift();
				this._ovlRef.addListener('overlayBegin',tgtObj);
				this._ovlRef.addListener('overlayEnd',tgtObj);
			}
			this._ovlRef.addListener('overlayClosed',this);
		}
	},

	createDefaultOverlay: function(opts) {
		if(this._ovlRef)
		{
			return;
		}
		else
		{
			var options = {
				autoOpen: true,
				opacity: 0,
				bgcolor: '#eee',
				depth: 10000
			};
			Object.extend(options, opts || {});

			var _mm = new this._classes.ModalOverlay(options);
			_mm.create();
			this.registerOverlay(_mm);
		}
	},

	getOverlay: function() {
		return(this._ovlRef);
	},

	registerStartup: function()
	{
		if(this._startupSequence)
		{
			this._startupSequence.push($A(arguments));
		}
		else
		{
			this.requireClass.apply(this,$A(arguments));
		}
	},

	_executeStartup: function()
	{
		if(this._startupSequence)
		{
	 		for(var i=0; i<this._startupSequence.length; i++)
	 		{
				this.requireClass.apply(this,this._startupSequence[i]);
			}
			delete this._startupSequence;
			this._startupSequence = null;
		}
	},

	logMessage: function(msg, source)
	{
		if(this._loggerSink)
		{
			this._loggerSink.logMessage(msg, source);
		}
	},

	_createLogger: function() {
		if(this._loggerSink)
		{
			return;
		}
		else
		{
			var foo = new this._classes.SwfLogger();
		}
	},

	createDefaultAudioManager: function(opts)
	{
		if(this._audRef)
		{
			return;
		}
		else
		{
			var _am = new this._classes.AudioManager(null,opts);
			_am.create();
			this.registerAudioManager(_am);
		}
	},

	registerAudioManager: function(obj) {
		if(this._audRef)
		{
			throw(new Error("AudioManager already registered!"));
		}
		else
		{
			this._audRef = obj;
		}
	},

	getAudioManager: function() {
		return(this._audRef);
	},

	registerCommunityHandler: function(obj) {
		if(this._coRef)
		{
			throw(new Error("CommunityHandler already registered!"));
		}
		else
		{
			this._coRef = obj;
		}
	},

	getCommunityHandler: function() {
		return(this._coRef);
	},

	registerObject: function(name, obj) {
		if(typeof(this._objRef[name]) == 'undefined')
		{
			this._objRef[name] = obj;
		}
		else
		{
			throw(new Error("Object already registered for: "+name));
		}
	},

	unregisterObject: function(name, obj) {
		if(this._objRef[name] == obj)
		{
			delete(this._objRef[name]);
		}
	},

	getRegisteredObject: function(name) {
		return(this._objRef[name]);
	},

	requireCSS: function(name) {
		var cname = name.split("/").pop();
		if(!$('dn_cs_'+cname))
		{
			var head = document.getElementsByTagName('head').item(0);
			var css = document.createElement('link');
			css.href = _cssDestDomain+'/'+name+'.css'+this._theVersion;
			css.type = 'text/css';
			css.rel = 'stylesheet';
			css.id = 'dn_cs_'+cname;
			head.appendChild(css);
		}
	},

	showModal: function(target) {
		if(this.definedClass('ModalHelper'))
		{
			for(var i = 0; i < this._modalList.length; i++)
			{
				if(this._modalList[i][0] === target)
				{
					this._modalList[i][1].cancelModal();
					return false;
				}
			}
			var mh = new this._classes.ModalHelper(target);
			this._modalList.push([target,mh]);
			return mh.create();
		}
		else
		{
			return true;
		}
	},

	overlayClosed: function(objEvt) {
		for(var i = 0; i < this._modalList.length; i++)
		{
			if(this._modalList[i][1] === objEvt.controller)
			{
				this._modalList[i][0] = null;	//Stacco il dom
				this._modalList.splice(i,1);
				break;
			}
		}
	},
	
	parentSend: function(cmd) {
		if(this._gateway)
			this._gateway._extMsg(cmd, window.name);
	},

	_extMsg: function(cmd, id_send)
	{
		switch(cmd)
		{
			case 'close':
				this._closeModal(id_send);
			break;

			default:
			break;
		}
	},
	
	_closeModal: function(name) {
		var list = this._modalList;

		for(var i=0; i<list.length; i++)
		{
			var mh = list[i][1];

			if(mh.getFrameName() == name)
				mh.cancelModal();
		}
	}
}

var _dadanet = new NameSpace();
addLoadEvent(_dadanet._executeStartup.bind(_dadanet),true);
