Claim.isObject(UA, "UA namespace is not initiated. GameCatalog.AvatarStudio requires utilities from namespace UA.");

if(!window.GameCatalog) GameCatalog = {};

GameCatalog.AvatarStudio = Class.create();

/***
 *  instance settings
 * <ul>
 * <li><code>FVAR_AvatarSaveURL - the useraccount processing handler for save actions
 * <li><code>FVAR_ColorsXML</code> - the XML feed that defines the colors
 * <li><code>FVAR_LayoutXML</code> - the XML feed that defines the layout
 * <li><code>FVAR_LocalizationXML</code> - the XML feed that translates the terms
 * <li><code>FVAR_OmnitureXML</code> - the omniture XML feed that specifies omniture settings
 * <li><code>FVAR_ItemLibraryXML</code> - the XML feed that defines the available items
 * <li><code>FVAR_PromotionsXML</code> - the XML feed that defines the promoted items
 * <li><code>FVAR_ProgressURL</code> - the URL for the SWF of the progress scene
 * <li><code>FVAR_LoadingSceneURL</code> - the URL for the SWF of the loading scene
 * <li><code>tinyAvatarBaseURL</code> - the base URL for the user-tiny-avatar handler
 * <li><code>fullAvatarBaseURL</code> - the base URL for the user-full-avatar handler
 * <li><code>FVAR_DEBUG</code> - boolean for enable debug
 * <li><code>FVAR_LogLevel</code> - the log-level
 * <li><code>base</code> - the URL for the base path
 * <li><code>studioSWF</code> - the URL for the studio swf file
 * <li><code>genericErrorMsg</code> - generic error message for cases the user-account async call fails
 * <li>Any other Flash settings</code> - any other setting is passed on to the flash worker object.<br>
 *	Examples for flash settings:
 *	<small>(Some of the following examples also have default values)</small><ul>
 *	 <li><code>height</code> - default 424
 *	 <li><code>width</code> - default 571
 *	 <li><code>wmode</code> - default transparent
 *	 <li><code>quality</code> - default high
 *	 <li><code>bgcolor</code> - default #ffffff
 *	 <li><code>menu</code> - default false
 *	 <li><code>allowscriptaccess</code> - default true
 *	 <li><code>class</code></ul>
 *	 <li><code>style</code></ul>
 * </ul>
 */ 										 /* Enviornment Parameters */
GameCatalog.AvatarStudio.defaultSettings =   { FVAR_AvatarSaveURL	: UA.Game.prototype.PRIME_HANDLER_URL

											 /* Channel/Community Parameters */
											 , FVAR_ColorsXML		: null
											 , FVAR_LayoutXML		: null
											 , FVAR_LocalizationXML	: null
											 , FVAR_OmnitureXML		: null
											 , FVAR_ItemLibraryXML	: null
											 , FVAR_PromotionsXML	: null
											 , FVAR_ProgressURL		: null
											 , FVAR_LoadingSceneURL	: null

                                             /* User-Account AvatarXML getter handler*/
											 , tinyAvatarBaseURL	: null
											 , fullAvatarBaseURL	: null

											 /* Studio Execution mode parameters */
											 , FVAR_DEBUG			: "false"
											 , FVAR_LogLevel		: "0"

											 /* special settings */
											 , base					: "/Community/avatars/2.0/"
											 , studioSWF			: "/Community/avatars/2.0/as.swf" 
											 , defaultLanguageCode	: null
											 , genericErrorMsg		: "error occured"

											 /* flash tag settings */
											 , height				: 424
											 , width				: 571
											 , wmode				: "transparent"
											 , quality				: "high"
											 , bgcolor				: "#ffffff"
											 , menu					: false
											 , allowscriptaccess	: true
											 }
var __bothInternalAndMustInit = "channel,genericErrorMsg,studioSWF,defaultLanguageCode,tinyAvatarBaseURL,fullAvatarBaseURL,FVAR_AvatarSaveURL,FVAR_ColorsXML,FVAR_LayoutXML,FVAR_LocalizationXML,FVAR_OmnitureXML,FVAR_ItemLibraryXML,FVAR_PromotionsXML,FVAR_ProgressURL,FVAR_LoadingSceneURL,FVAR_DEBUG,FVAR_LogLevel"

/**
 * A comma-delimited list of all internal-settings that must be initiated 
 * for every instance<br>
 * @private
 * @type String
 */
GameCatalog.AvatarStudio.mustInit = "base," + __bothInternalAndMustInit;

/**
 * A comma-delimited list of all properties from {@link GameCatalog.AvatarStudio#settings} 
 * that should not be used as flash-settings (See third constructor parameter of {@link Flash}).<br>
 * @private
 * @type String
 */
GameCatalog.AvatarStudio.internalSettings = "logger,"  + __bothInternalAndMustInit;

delete __bothInternalAndMustInit;

//------------------------------------------------------------------------------------------------

/**
 * Constructs the avatar-studio that will use sTargetElement as target.
 *
 * @param {String} sTargetElementID
 *  The ID for the DOM-Container to wich the studio (and the preloader) should be rendered
 * @param {Object(optional)} oSettings
 *  HTML settings for the flash tag, <code>param</code> settings for the flash tag, or instance settings for the avatar studio.<ul>
 *  <li> flash settings - Any HTML attribute for the flash object. Examples: height, width, style est. see {@link Flash}
 *  <li> flash params - any special flash params. Examples: bgcolor, base, wmode, quality, est.
 *	<li> instance settings: see {@link GameCatalog.AvatarStudio#settings}
 *  </ul>
 *
 * @class
 * A Class to render an AvararStudio.<br>
 * The class renders a preloader to the screen and applies an asyncronous call for the user tokens.<br>
 * When a successfull response arrives - it renders a studio to the target element.<br>
 * When failure returns, or when the response times out - it renders a generic-error message, taken from <code>settings.genericErrorMsg</code>
 * 
 * @constructor
 */
GameCatalog.AvatarStudio.prototype.initialize = function(sTargetElementID, oSettings, oEvents)
{
    Claim.isString(sTargetElementID,"sTargetElementID must be a String containing an ID of the target DOM-Container for the avatar studio");
	/**
	 * The ID of the DOM-Container for the preloader and then the studio
	 * @type String
	 */
	this.targetElement = sTargetElementID;

	/**
	 * the current instance settings
	 * collextion of all paramateres in config
	 * @type Object
	 */
 	this.settings = Object.extend({}, GameCatalog.AvatarStudio.defaultSettings);
	//overrun on the copy the provided overridig settings
	Object.extend(this.settings, oSettings);

	/**
	 * The Log4Js.Logger instance. Can be provided on <code>oSettings.logger</code>
	 * @type Log4Js.Logger
	 */
	this.log = this.settings.logger;
	if(typeof(this.log) == 'string') this.log = new Log4Js.Logger(this.log);
	if(!this.log) this.log = new Log4Js.Logger("AvatarStudio");

	Claim.isTrue(this.log instanceof Log4Js.Logger, "settings.log can be ither a Log4Js.Logger or a string to be used as logger-name" );

	//if there is one instance with [logType] provided as setting - they all should use it
	if(!GameCatalog.AvatarStudio.logType) GameCatalog.AvatarStudio.logType = this.settings.logType;
	
	//make sure all settings exist
	Claim.isTrue(GameCatalog.AvatarStudio.initated,"GameCatalog.AvatarStudio is not initiated. channel-config must be called before  [GameCatalog.AvatarStudio]  is used on the page");
	var i, arr = GameCatalog.AvatarStudio.mustInit.split(",");
	for(i = 0; i < arr.length; i++)	Claim.isTrue( !!this.settings[arr[i]], "default setting [" + arr[i] + "] is not initiated and not provided on oSettings constructor argument.");

	//render the preloader
	/**
	 * The preloader flash 
	 * @type Flash
	 */
	this.preloader = new Flash(this.settings.FVAR_LoadingSceneURL, this.settings, GameCatalog.AvatarStudio.internalSettings);

	this.preloader.render(sTargetElementID);

	//add the id of the preloader to the settings
	this.settings.id = this.preloader.objectID;

	//prepare Flash object
	/**
	 * The Studio {@link Flash} object
	 * @type Flash
	 */
	this.studio = new Flash(this.settings.studioSWF, this.settings, GameCatalog.AvatarStudio.internalSettings);

	/***
	 * The worker UA.User instance
	 * @type UA.User
	 */
	this.user = new UA.User();
}

/**
 * Applies an asyncronous call to fetch the user-tokens.
 * When the call returns - the Studio is rendered with the tokens as parameter in flashvars.
 *
 * @event onComplete
 */
GameCatalog.AvatarStudio.prototype.apply = function()
{
	this.user.boss = this;
	this.user.GetUserTokens( function(iTokens ){ this.boss.onSuccess(iTokens ) }
						   , function(response){ this.boss.onFailure(response) }
						   , function(request ){ this.boss.onTimeout(request ) } 
						   );
}

/**
 * gets the cookie-data for the current user
 * @private
 */
GameCatalog.AvatarStudio.prototype.getCookieData = function()
{
	return Clearance.getMagic(Clearance.UNCLASSIFIED);
}

/**
 * fired when the asyncronous call for the user-tokens returns successfully.
 * @param {Number} iTokens
 *   The user tokens balance
 */
GameCatalog.AvatarStudio.prototype.onSuccess = function(iTokens)
{
    this.log.info("on success for GetUserTokens. iTokens [" + Serialize(iTokens) + "]");
	var magic = this.getCookieData() || "";

	this.settings.FVAR_UserToken = escape(magic);
	this.settings.FVAR_TinyAvatarXML = Url.appendParamValue(this.settings.tinyAvatarBaseURL, "cookiedata", magic);
	this.settings.FVAR_FullAvatarXML = Url.appendParamValue(this.settings.fullAvatarBaseURL, "cookiedata", magic);

	var defaultLanguage = Url.here.params.ln || Url.here.params.lc || this.settings.defaultLanguageCode
	
	var each;
	var FVARS = [];
	for(each in this.settings)
	{
		if (each.indexOf("FVAR_") == 0)
		{
			if (each.lastIndexOf("XML") == (each.length - 3))
			{
				this.settings[each] = Url.appendParamValue(this.settings[each], "lc", defaultLanguage);
				this.settings[each] = Url.appendParamValue(this.settings[each], "channel", this.settings.channel);
			}
			FVARS[FVARS.length] = each;
			FVARS[FVARS.length] = "=";
			FVARS[FVARS.length] = escape(this.settings[each]);
			FVARS[FVARS.length] = "&";
		}
	}
	FVARS[FVARS.length] = "FVAR_Token=";
	FVARS[FVARS.length] = iTokens;

	this.studio.settings.flashvars = FVARS.join("");
    this.log.info("flashvars:" + this.studio.settings.flashvars );

	this.studio.settings.flashvars = this.studio.settings.flashvars.replace(/https/gi, 'http');
    this.log.info("flashvars:" + this.studio.settings.flashvars );

	this.studio.render( this.targetElement );
    this.log.debug("Studio HTML:" + this.studio.HTML.replace(/\</g,"&lt;"));

	if(typeof(this.onComplete) == 'function')
		this.onComplete();
}

/**
 * fires when the asyncronous call for the user tokens is returned with a failuer
 * @param {Jast.Request#response} r
 *
 * @overridable
 */
GameCatalog.AvatarStudio.prototype.onFailure = function(r)
{
	$(this.targetElement).innerHTML = this.settings.genericErrorMsg;
}

/**
 * fires when the asyncronous call for the user tokens is timed-out
 * @param {Jast.Request} r
 *
 * @overridable
 */
GameCatalog.AvatarStudio.prototype.onTimeout = function(r)
{
	$(this.targetElement).innerHTML = this.settings.genericErrorMsg;
}


/**
 * A handler for FS-Command of the flash object.
 *
 * @param {string} command 
 *	 Log | Save | Dirty
 *
 * @param {string} args
 *
 */
GameCatalog.AvatarStudio.FsCommand = function __DoFSCommand(command, args)
{
	if ( command == "Log" )
	{
//		this.dispatch("onLog", "args");
		this.studio_output(args, "black");
	}
	else if ( command == "Save" )
	{
//		this.dispatch("onSaved");
		this.studio_output("Save Event: Avatar has been saved", "blue");
	}
	else if ( command == "Dirty" )
	{
//		this.dispatch("onDirty", args );
		this.studio_output("Avatar dirty = " + args, "green");
	}
}

/**
 * This Log4Js.Logger instance is for the ODS logging 
 * - the output that the SWF spits to the do-fs-command
 */
GameCatalog.AvatarStudio.log = new Log4Js.Logger("AvatarStudio_ODS");
/**
 * The style attributes or the css class name for the in-page ODS logger
 * @type Object|String
 */
GameCatalog.AvatarStudio.ODS_Style = { textAlign	  : "left"
									 , height		  : "180px"
									 , overflow		  : "auto"
									 , width		  : "100%"
									 , fontSize		  : "10pt"
									 , borderStyle	  : "inset"
									 , backgroundColor: "white" 
									 };
/**
 * outputs the SWF FSCommand comments to the appropriate log
 * @private
 */
GameCatalog.AvatarStudio.studio_output = function(output, textColor)
{

	if (!GameCatalog.AvatarStudio.logType) return;

	//if the log type should be "ODS" 
	if (GameCatalog.AvatarStudio.logType == 'ODS' && !this.ODS)
	{	
		//initiate this.ODS
		this.ODS = $("ODS")
		if (!this.ODS)
		{
			this.ODS = document.createElement("DIV");
			this.ODS.id = "ODS";

			if (typeof( this.ODS_Style ) == 'object')
			{
				Object.extend(this.ODS.style, this.ODS_Style );
			}
			else if ( typeof(this.ODS_Style) == 'string' )
			{
				this.ODS.className = this.ODS_Style;
			}

			document.body.appendChild(this.ODS);
		}
	}

    try
    {
		var currentTime = new Date();
		var ods = this.ODS;

		var escapedHTML = "[" + currentTime.getHours() + ":" + currentTime.getMinutes() + ":" + currentTime.getSeconds() + "] " + output.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
		var preText = "";
		preText = "<div style=\"color:" + textColor + ";\">" + escapedHTML + "</div>";
		
		switch(GameCatalog.AvatarStudio.logType)
		{
			case 'ODS'    :	ods.innerHTML = preText + ods.innerHTML; break;
			case 'Log4Net': switch( textColor ) 
							{
								case 'blue'	 : GameCatalog.AvatarStudio.log.info (preText); break;
								case 'orange': GameCatalog.AvatarStudio.log.warn (preText); break;
								case 'red'	 : GameCatalog.AvatarStudio.log.error(preText); break;
								default		 : GameCatalog.AvatarStudio.log.debug(preText); break;
							}
			default       :	break;
		}
	}
	catch (e)
	{
		GameCatalog.AvatarStudio.log.fatal("Error in studio_output().");
	}
}