/******************Prototype.js - Start *********************/

var Prototype={
Version:'1.4.0',
ScriptFragment:'(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
emptyFunction:function(){},
K:function(x){return x}}
var Class={
create:function(){
return function(){
this.initialize.apply(this,arguments);}}}
var Abstract=new Object();
Object.extend=function(destination,source){
for(property in source){
destination[property]=source[property];}
return destination;}
Object.inspect=function(object){
try{
if(object==undefined)return 'undefined';
if(object==null)return 'null';
return object.inspect?object.inspect():object.toString();}catch(e){
if(e instanceof RangeError)return '...';
throw e;}}
Function.prototype.bind=function(){
var __method=this,args=$A(arguments),object=args.shift();
return function(){
return __method.apply(object,args.concat($A(arguments)));}}
Function.prototype.bindAsEventListener=function(object){
var __method=this;
return function(event){
return __method.call(object,event||window.event);}}
Object.extend(Number.prototype,{
toColorPart:function(){
var digits=this.toString(16);
if(this<16)return '0'+digits;
return digits;},
succ:function(){
return this +1;},
times:function(iterator){
$R(0,this,true).each(iterator);
return this;}});
var Try={
these:function(){
var returnValue;
for(var i=0;i<arguments.length;i++){
var lambda=arguments[i];
try{
returnValue=lambda();
break;}catch(e){}}
return returnValue;}}
var PeriodicalExecuter=Class.create();
PeriodicalExecuter.prototype={
initialize:function(callback,frequency){
this.callback=callback;
this.frequency=frequency;
this.currentlyExecuting=false;
this.registerCallback();},
registerCallback:function(){
setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},
onTimerEvent:function(){
if(!this.currentlyExecuting){
try{
this.currentlyExecuting=true;
this.callback();}finally{
this.currentlyExecuting=false;}}}}
function $(){
var elements=new Array();
for(var i=0;i<arguments.length;i++){
var element=arguments[i];
if(typeof element=='string')
element=document.getElementById(element);
if(arguments.length==1)
return element;
elements.push(element);}
return elements;}
Object.extend(String.prototype,{
stripTags:function(){
return this.replace(/<\/?[^>]+>/gi,'');},
stripScripts:function(){
return this.replace(new RegExp(Prototype.ScriptFragment,'img'),'');},
extractScripts:function(){
var matchAll=new RegExp(Prototype.ScriptFragment,'img');
var matchOne=new RegExp(Prototype.ScriptFragment,'im');
return(this.match(matchAll)||[]).map(function(scriptTag){
return(scriptTag.match(matchOne)||['',''])[1];});},
evalScripts:function(){
return this.extractScripts().map(eval);},
escapeHTML:function(){
var div=document.createElement('div');
var text=document.createTextNode(this);
div.appendChild(text);
return div.innerHTML;},
unescapeHTML:function(){
var div=document.createElement('div');
div.innerHTML=this.stripTags();
return div.childNodes[0]?div.childNodes[0].nodeValue:'';},
toQueryParams:function(){
var pairs=this.match(/^\??(.*)$/)[1].split('&');
return pairs.inject({},function(params,pairString){
var pair=pairString.split('=');
params[pair[0]]=pair[1];
return params;});},
toArray:function(){
return this.split('');},
camelize:function(){
var oStringList=this.split('-');
if(oStringList.length==1)return oStringList[0];
var camelizedString=this.indexOf('-')==0?oStringList[0].charAt(0).toUpperCase()+oStringList[0].substring(1):oStringList[0];
for(var i=1,len=oStringList.length;i<len;i++){
var s=oStringList[i];
camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
return camelizedString;},
inspect:function(){
return "'"+this.replace('\\','\\\\').replace("'",'\\\'') + "'";}});
String.prototype.parseQuery=String.prototype.toQueryParams;
var $break=new Object();
var $continue=new Object();
var Enumerable={
each:function(iterator){
var index=0;
try{
this._each(function(value){
try{
iterator(value,index++);}catch(e){
if(e!=$continue)throw e;}});}catch(e){
if(e!=$break)throw e;}},
all:function(iterator){
var result=true;
this.each(function(value,index){
result=result&&!!(iterator||Prototype.K)(value,index);
if(!result)throw $break;});
return result;},
any:function(iterator){
var result=true;
this.each(function(value,index){
if(result=!!(iterator||Prototype.K)(value,index))
throw $break;});
return result;},
collect:function(iterator){
var results=[];
this.each(function(value,index){
results.push(iterator(value,index));});
return results;},
detect:function(iterator){
var result;
this.each(function(value,index){
if(iterator(value,index)){
result=value;
throw $break;}});
return result;},
findAll:function(iterator){
var results=[];
this.each(function(value,index){
if(iterator(value,index))
results.push(value);});
return results;},
grep:function(pattern,iterator){
var results=[];
this.each(function(value,index){
var stringValue=value.toString();
if(stringValue.match(pattern))
results.push((iterator||Prototype.K)(value,index));})
return results;},
include:function(object){
var found=false;
this.each(function(value){
if(value==object){
found=true;
throw $break;}});
return found;},
inject:function(memo,iterator){
this.each(function(value,index){
memo=iterator(memo,value,index);});
return memo;},
invoke:function(method){
var args=$A(arguments).slice(1);
return this.collect(function(value){
return value[method].apply(value,args);});},
max:function(iterator){
var result;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value>=(result||value))
result=value;});
return result;},
min:function(iterator){
var result;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value<=(result||value))
result=value;});
return result;},
partition:function(iterator){
var trues=[],falses=[];
this.each(function(value,index){((iterator||Prototype.K)(value,index)?
trues:falses).push(value);});
return[trues,falses];},
pluck:function(property){
var results=[];
this.each(function(value,index){
results.push(value[property]);});
return results;},
reject:function(iterator){
var results=[];
this.each(function(value,index){
if(!iterator(value,index))
results.push(value);});
return results;},
sortBy:function(iterator){
return this.collect(function(value,index){
return{value:value,criteria:iterator(value,index)};}).sort(function(left,right){
var a=left.criteria,b=right.criteria;
return a<b?-1:a>b?1:0;}).pluck('value');},
toArray:function(){
return this.collect(Prototype.K);},
zip:function(){
var iterator=Prototype.K,args=$A(arguments);
if(typeof args.last()=='function')
iterator=args.pop();
var collections=[this].concat(args).map($A);
return this.map(function(value,index){
iterator(value=collections.pluck(index));
return value;});},
inspect:function(){
return '#<Enumerable:'+this.toArray().inspect()+'>';}}
Object.extend(Enumerable,{
map:Enumerable.collect,
find:Enumerable.detect,
select:Enumerable.findAll,
member:Enumerable.include,
entries:Enumerable.toArray});
var $A=Array.from=function(iterable){
if(!iterable)return[];
if(iterable.toArray){
return iterable.toArray();}else{
var results=[];
for(var i=0;i<iterable.length;i++)
results.push(iterable[i]);
return results;}}
Object.extend(Array.prototype,Enumerable);
Array.prototype._reverse=Array.prototype.reverse;
Object.extend(Array.prototype,{
_each:function(iterator){
for(var i=0;i<this.length;i++)
iterator(this[i]);},
clear:function(){
this.length=0;
return this;},
first:function(){
return this[0];},
last:function(){
return this[this.length-1];},
compact:function(){
return this.select(function(value){
return value!=undefined||value!=null;});},
flatten:function(){
return this.inject([],function(array,value){
return array.concat(value.constructor==Array?
value.flatten():[value]);});},
without:function(){
var values=$A(arguments);
return this.select(function(value){
return !values.include(value);});},
indexOf:function(object){
for(var i=0;i<this.length;i++)
if(this[i]==object)return i;
return -1;},
reverse:function(inline){
return(inline!==false?this:this.toArray())._reverse();},
shift:function(){
var result=this[0];
for(var i=0;i<this.length-1;i++)
this[i]=this[i+1];
this.length--;
return result;},
inspect:function(){
return '['+this.map(Object.inspect).join(', ')+']';}});
var Hash={
_each:function(iterator){
for(key in this){
var value=this[key];
if(typeof value=='function')continue;
var pair=[key,value];
pair.key=key;
pair.value=value;
iterator(pair);}},
keys:function(){
return this.pluck('key');},
values:function(){
return this.pluck('value');},
merge:function(hash){
return $H(hash).inject($H(this),function(mergedHash,pair){
mergedHash[pair.key]=pair.value;
return mergedHash;});},
toQueryString:function(){
return this.map(function(pair){
return pair.map(encodeURIComponent).join('=');}).join('&');},
inspect:function(){
return '#<Hash:{'+this.map(function(pair){
return pair.map(Object.inspect).join(': ');}).join(', ')+'}>';}}
function $H(object){
var hash=Object.extend({},object||{});
Object.extend(hash,Enumerable);
Object.extend(hash,Hash);
return hash;}
ObjectRange=Class.create();
Object.extend(ObjectRange.prototype,Enumerable);
Object.extend(ObjectRange.prototype,{
initialize:function(start,end,exclusive){
this.start=start;
this.end=end;
this.exclusive=exclusive;},
_each:function(iterator){
var value=this.start;
do{
iterator(value);
value=value.succ();}while(this.include(value));},
include:function(value){
if(value<this.start)
return false;
if(this.exclusive)
return value<this.end;
return value<=this.end;}});
var $R=function(start,end,exclusive){
return new ObjectRange(start,end,exclusive);}
var Ajax={
getTransport:function(){
return Try.these(
function(){return new ActiveXObject('Msxml2.XMLHTTP')},
function(){return new ActiveXObject('Microsoft.XMLHTTP')},
function(){return new XMLHttpRequest()})||false;},
activeRequestCount:0}
Ajax.Responders={
responders:[],
_each:function(iterator){
this.responders._each(iterator);},
register:function(responderToAdd){
if(!this.include(responderToAdd))
this.responders.push(responderToAdd);},
unregister:function(responderToRemove){
this.responders=this.responders.without(responderToRemove);},
dispatch:function(callback,request,transport,json){
this.each(function(responder){
if(responder[callback]&&typeof responder[callback]=='function'){
try{
responder[callback].apply(responder,[request,transport,json]);}catch(e){}}});}};
Object.extend(Ajax.Responders,Enumerable);
Ajax.Responders.register({
onCreate:function(){
Ajax.activeRequestCount++;},
onComplete:function(){
Ajax.activeRequestCount--;}});
Ajax.Base=function(){};
Ajax.Base.prototype={
setOptions:function(options){
this.options={
method:'post',
asynchronous:true,
parameters:''}
Object.extend(this.options,options||{});},
responseIsSuccess:function(){
return this.transport.status==undefined||this.transport.status==0||(this.transport.status>=200&&this.transport.status<300);},
responseIsFailure:function(){
return !this.responseIsSuccess();}}
Ajax.Request=Class.create();
Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];
Ajax.Request.prototype=Object.extend(new Ajax.Base(),{
initialize:function(url,options){
this.transport=Ajax.getTransport();
this.setOptions(options);
this.request(url);},
request:function(url){
var parameters=this.options.parameters||'';
if(parameters.length>0)parameters+='&_=';
try{
this.url=url;
if(this.options.method=='get'&&parameters.length>0)
this.url+=(this.url.match(/\?/)?'&':'?')+parameters;
Ajax.Responders.dispatch('onCreate',this,this.transport);
this.transport.open(this.options.method,this.url,
this.options.asynchronous);
if(this.options.asynchronous){
this.transport.onreadystatechange=this.onStateChange.bind(this);
setTimeout((function(){this.respondToReadyState(1)}).bind(this),10);}
this.setRequestHeaders();
var body=this.options.postBody?this.options.postBody:parameters;
this.transport.send(this.options.method=='post'?body:null);}catch(e){
this.dispatchException(e);}},
setRequestHeaders:function(){
var requestHeaders=['X-Requested-With','XMLHttpRequest',
'X-Prototype-Version',Prototype.Version];
if(this.options.method=='post'){
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
if(this.transport.overrideMimeType)
requestHeaders.push('Connection','close');}
if(this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders,this.options.requestHeaders);
for(var i=0;i<requestHeaders.length;i+=2)
this.transport.setRequestHeader(requestHeaders[i],requestHeaders[i+1]);},
onStateChange:function(){
var readyState=this.transport.readyState;
if(readyState!=1)
this.respondToReadyState(this.transport.readyState);},
header:function(name){
try{
return this.transport.getResponseHeader(name);}catch(e){}},
evalJSON:function(){
try{
return eval(this.header('X-JSON'));}catch(e){}},
evalResponse:function(){
try{
return eval(this.transport.responseText);}catch(e){
this.dispatchException(e);}},
respondToReadyState:function(readyState){
var event=Ajax.Request.Events[readyState];
var transport=this.transport,json=this.evalJSON();
if(event=='Complete'){
try{(this.options['on'+this.transport.status]||this.options['on'+(this.responseIsSuccess()?'Success':'Failure')]||Prototype.emptyFunction)(transport,json);}catch(e){
this.dispatchException(e);}
if((this.header('Content-type')||'').match(/^text\/javascript/i))
this.evalResponse();}
try{(this.options['on'+event]||Prototype.emptyFunction)(transport,json);
Ajax.Responders.dispatch('on'+event,this,transport,json);}catch(e){
this.dispatchException(e);}
if(event=='Complete')
this.transport.onreadystatechange=Prototype.emptyFunction;},
dispatchException:function(exception){(this.options.onException||Prototype.emptyFunction)(this,exception);
Ajax.Responders.dispatch('onException',this,exception);}});
Ajax.Updater=Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype,Ajax.Request.prototype),{
initialize:function(container,url,options){
this.containers={
success:container.success?$(container.success):$(container),
failure:container.failure?$(container.failure):(container.success?null:$(container))}
this.transport=Ajax.getTransport();
this.setOptions(options);
var onComplete=this.options.onComplete||Prototype.emptyFunction;
this.options.onComplete=(function(transport,object){
this.updateContent();
onComplete(transport,object);}).bind(this);
this.request(url);},
updateContent:function(){
var receiver=this.responseIsSuccess()?
this.containers.success:this.containers.failure;
var response=this.transport.responseText;
if(!this.options.evalScripts)
response=response.stripScripts();
if(receiver){
if(this.options.insertion){
new this.options.insertion(receiver,response);}else{
Element.update(receiver,response);}}
if(this.responseIsSuccess()){
if(this.onComplete)
setTimeout(this.onComplete.bind(this),10);}}});
Ajax.PeriodicalUpdater=Class.create();
Ajax.PeriodicalUpdater.prototype=Object.extend(new Ajax.Base(),{
initialize:function(container,url,options){
this.setOptions(options);
this.onComplete=this.options.onComplete;
this.frequency=(this.options.frequency||2);
this.decay=(this.options.decay||1);
this.updater={};
this.container=container;
this.url=url;
this.start();},
start:function(){
this.options.onComplete=this.updateComplete.bind(this);
this.onTimerEvent();},
stop:function(){
this.updater.onComplete=undefined;
clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments);},
updateComplete:function(request){
if(this.options.decay){
this.decay=(request.responseText==this.lastText?
this.decay*this.options.decay:1);
this.lastText=request.responseText;}
this.timer=setTimeout(this.onTimerEvent.bind(this),
this.decay*this.frequency*1000);},
onTimerEvent:function(){
this.updater=new Ajax.Updater(this.container,this.url,this.options);}});
document.getElementsByClassName=function(className,parentElement){
var children=($(parentElement)||document.body).getElementsByTagName('*');
return $A(children).inject([],function(elements,child){
if(child.className.match(new RegExp("(^|\\s)"+className+"(\\s|$)")))
elements.push(child);
return elements;});}
if(!window.Element){
var Element=new Object();}
Object.extend(Element,{
visible:function(element){
return $(element).style.display!='none';},
toggle:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
Element[Element.visible(element)?'hide':'show'](element);}},
hide:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
element.style.display='none';}},
show:function(){
for(var i=0;i<arguments.length;i++){
var element=$(arguments[i]);
element.style.display='';}},
remove:function(element){
element=$(element);
element.parentNode.removeChild(element);},
update:function(element,html){
$(element).innerHTML=html.stripScripts();
setTimeout(function(){html.evalScripts()},10);},
getHeight:function(element){
element=$(element);
return element.offsetHeight;},
classNames:function(element){
return new Element.ClassNames(element);},
hasClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).include(className);},
addClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).add(className);},
removeClassName:function(element,className){
if(!(element=$(element)))return;
return Element.classNames(element).remove(className);},
cleanWhitespace:function(element){
element=$(element);
for(var i=0;i<element.childNodes.length;i++){
var node=element.childNodes[i];
if(node.nodeType==3&&!/\S/.test(node.nodeValue))
Element.remove(node);}},
empty:function(element){
return $(element).innerHTML.match(/^\s*$/);},
scrollTo:function(element){
element=$(element);
var x=element.x?element.x:element.offsetLeft,
y=element.y?element.y:element.offsetTop;
window.scrollTo(x,y);},
getStyle:function(element,style){
element=$(element);
var value=element.style[style.camelize()];
if(!value){
if(document.defaultView&&document.defaultView.getComputedStyle){
var css=document.defaultView.getComputedStyle(element,null);
value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){
value=element.currentStyle[style.camelize()];}}
if(window.opera&&['left','top','right','bottom'].include(style))
if(Element.getStyle(element,'position')=='static')value='auto';
return value=='auto'?null:value;},
setStyle:function(element,style){
element=$(element);
for(name in style)
element.style[name.camelize()]=style[name];},
getDimensions:function(element){
element=$(element);
if(Element.getStyle(element,'display')!='none')
return{width:element.offsetWidth,height:element.offsetHeight};
var els=element.style;
var originalVisibility=els.visibility;
var originalPosition=els.position;
els.visibility='hidden';
els.position='absolute';
els.display='';
var originalWidth=element.clientWidth;
var originalHeight=element.clientHeight;
els.display='none';
els.position=originalPosition;
els.visibility=originalVisibility;
return{width:originalWidth,height:originalHeight};},
makePositioned:function(element){
element=$(element);
var pos=Element.getStyle(element,'position');
if(pos=='static'||!pos){
element._madePositioned=true;
element.style.position='relative';
if(window.opera){
element.style.top=0;
element.style.left=0;}}},
undoPositioned:function(element){
element=$(element);
if(element._madePositioned){
element._madePositioned=undefined;
element.style.position=
element.style.top=
element.style.left=
element.style.bottom=
element.style.right='';}},
makeClipping:function(element){
element=$(element);
if(element._overflow)return;
element._overflow=element.style.overflow;
if((Element.getStyle(element,'overflow')||'visible')!='hidden')
element.style.overflow='hidden';},
undoClipping:function(element){
element=$(element);
if(element._overflow)return;
element.style.overflow=element._overflow;
element._overflow=undefined;}});
var Toggle=new Object();
Toggle.display=Element.toggle;
Abstract.Insertion=function(adjacency){
this.adjacency=adjacency;}
Abstract.Insertion.prototype={
initialize:function(element,content){
this.element=$(element);
this.content=content.stripScripts();
if(this.adjacency&&this.element.insertAdjacentHTML){
try{
this.element.insertAdjacentHTML(this.adjacency,this.content);}catch(e){
if(this.element.tagName.toLowerCase()=='tbody'){
this.insertContent(this.contentFromAnonymousTable());}else{
throw e;}}}else{
this.range=this.element.ownerDocument.createRange();
if(this.initializeRange)this.initializeRange();
this.insertContent([this.range.createContextualFragment(this.content)]);}
setTimeout(function(){content.evalScripts()},10);},
contentFromAnonymousTable:function(){
var div=document.createElement('div');
div.innerHTML='<table><tbody>'+this.content+'</tbody></table>';
return $A(div.childNodes[0].childNodes[0].childNodes);}}
var Insertion=new Object();
Insertion.Before=Class.create();
Insertion.Before.prototype=Object.extend(new Abstract.Insertion('beforeBegin'),{
initializeRange:function(){
this.range.setStartBefore(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.parentNode.insertBefore(fragment,this.element);}).bind(this));}});
Insertion.Top=Class.create();
Insertion.Top.prototype=Object.extend(new Abstract.Insertion('afterBegin'),{
initializeRange:function(){
this.range.selectNodeContents(this.element);
this.range.collapse(true);},
insertContent:function(fragments){
fragments.reverse(false).each((function(fragment){
this.element.insertBefore(fragment,this.element.firstChild);}).bind(this));}});
Insertion.Bottom=Class.create();
Insertion.Bottom.prototype=Object.extend(new Abstract.Insertion('beforeEnd'),{
initializeRange:function(){
this.range.selectNodeContents(this.element);
this.range.collapse(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.appendChild(fragment);}).bind(this));}});
Insertion.After=Class.create();
Insertion.After.prototype=Object.extend(new Abstract.Insertion('afterEnd'),{
initializeRange:function(){
this.range.setStartAfter(this.element);},
insertContent:function(fragments){
fragments.each((function(fragment){
this.element.parentNode.insertBefore(fragment,
this.element.nextSibling);}).bind(this));}});
Element.ClassNames=Class.create();
Element.ClassNames.prototype={
initialize:function(element){
this.element=$(element);},
_each:function(iterator){
this.element.className.split(/\s+/).select(function(name){
return name.length>0;})._each(iterator);},
set:function(className){
this.element.className=className;},
add:function(classNameToAdd){
if(this.include(classNameToAdd))return;
this.set(this.toArray().concat(classNameToAdd).join(' '));},
remove:function(classNameToRemove){
if(!this.include(classNameToRemove))return;
this.set(this.select(function(className){
return className!=classNameToRemove;}).join(' '));},
toString:function(){
return this.toArray().join(' ');}}
Object.extend(Element.ClassNames.prototype,Enumerable);
var Field={
clear:function(){
for(var i=0;i<arguments.length;i++)
$(arguments[i]).value='';},
focus:function(element){
$(element).focus();},
present:function(){
for(var i=0;i<arguments.length;i++)
if($(arguments[i]).value=='')return false;
return true;},
select:function(element){
$(element).select();},
activate:function(element){
element=$(element);
element.focus();
if(element.select)
element.select();}}
var Form={
serialize:function(form){
var elements=Form.getElements($(form));
var queryComponents=new Array();
for(var i=0;i<elements.length;i++){
var queryComponent=Form.Element.serialize(elements[i]);
if(queryComponent)
queryComponents.push(queryComponent);}
return queryComponents.join('&');},
getElements:function(form){
form=$(form);
var elements=new Array();
for(tagName in Form.Element.Serializers){
var tagElements=form.getElementsByTagName(tagName);
for(var j=0;j<tagElements.length;j++)
elements.push(tagElements[j]);}
return elements;},
getInputs:function(form,typeName,name){
form=$(form);
var inputs=form.getElementsByTagName('input');
if(!typeName&&!name)
return inputs;
var matchingInputs=new Array();
for(var i=0;i<inputs.length;i++){
var input=inputs[i];
if((typeName&&input.type!=typeName)||(name&&input.name!=name))
continue;
matchingInputs.push(input);}
return matchingInputs;},
disable:function(form){
var elements=Form.getElements(form);
for(var i=0;i<elements.length;i++){
var element=elements[i];
element.blur();
element.disabled='true';}},
enable:function(form){
var elements=Form.getElements(form);
for(var i=0;i<elements.length;i++){
var element=elements[i];
element.disabled='';}},
findFirstElement:function(form){
return Form.getElements(form).find(function(element){
return element.type!='hidden'&&!element.disabled&&['input','select','textarea'].include(element.tagName.toLowerCase());});},
focusFirstElement:function(form){
Field.activate(Form.findFirstElement(form));},
reset:function(form){
$(form).reset();}}
Form.Element={
serialize:function(element){
element=$(element);
var method=element.tagName.toLowerCase();
var parameter=Form.Element.Serializers[method](element);
if(parameter){
var key=encodeURIComponent(parameter);
if(key.length==0)return;
if(parameter[1].constructor !=Array)
parameter[1]=[parameter[1]];
return parameter[1].map(function(value){
return key+'='+encodeURIComponent(value);}).join('&');}},
getValue:function(element){
element=$(element);
var method=element.tagName.toLowerCase();
var parameter=Form.Element.Serializers[method](element);
if(parameter)
return parameter[1];}}
Form.Element.Serializers={
input:function(element){
switch(element.type.toLowerCase()){
case 'submit':
case 'hidden':
case 'password':
case 'text':
return Form.Element.Serializers.textarea(element);
case 'checkbox':
case 'radio':
return Form.Element.Serializers.inputSelector(element);}
return false;},
inputSelector:function(element){
if(element.checked)
return[element.name,element.value];},
textarea:function(element){
return[element.name,element.value];},
select:function(element){
return Form.Element.Serializers[element.type=='select-one'?
'selectOne':'selectMany'](element);},
selectOne:function(element){
var value='',opt,index=element.selectedIndex;
if(index>=0){
opt=element.options[index];
value=opt.value;
if(!value&&!('value' in opt))
value=opt.text;}
return[element.name,value];},
selectMany:function(element){
var value=new Array();
for(var i=0;i<element.length;i++){
var opt=element.options[i];
if(opt.selected){
var optValue=opt.value;
if(!optValue&&!('value' in opt))
optValue=opt.text;
value.push(optValue);}}
return[element.name,value];}}
var $F=Form.Element.getValue;
Abstract.TimedObserver=function(){}
Abstract.TimedObserver.prototype={
initialize:function(element,frequency,callback){
this.frequency=frequency;
this.element=$(element);
this.callback=callback;
this.lastValue=this.getValue();
this.registerCallback();},
registerCallback:function(){
setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},
onTimerEvent:function(){
var value=this.getValue();
if(this.lastValue!=value){
this.callback(this.element,value);
this.lastValue=value;}}}
Form.Element.Observer=Class.create();
Form.Element.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
getValue:function(){
return Form.Element.getValue(this.element);}});
Form.Observer=Class.create();
Form.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{
getValue:function(){
return Form.serialize(this.element);}});
Abstract.EventObserver=function(){}
Abstract.EventObserver.prototype={
initialize:function(element,callback){
this.element=$(element);
this.callback=callback;
this.lastValue=this.getValue();
if(this.element.tagName.toLowerCase()=='form')
this.registerFormCallbacks();
else
this.registerCallback(this.element);},
onElementEvent:function(){
var value=this.getValue();
if(this.lastValue!=value){
this.callback(this.element,value);
this.lastValue=value;}},
registerFormCallbacks:function(){
var elements=Form.getElements(this.element);
for(var i=0;i<elements.length;i++)
this.registerCallback(elements[i]);},
registerCallback:function(element){
if(element.type){
switch(element.type.toLowerCase()){
case 'checkbox':
case 'radio':
Event.observe(element,'click',this.onElementEvent.bind(this));
break;
case 'password':
case 'text':
case 'textarea':
case 'select-one':
case 'select-multiple':
Event.observe(element,'change',this.onElementEvent.bind(this));
break;}}}}
Form.Element.EventObserver=Class.create();
Form.Element.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
getValue:function(){
return Form.Element.getValue(this.element);}});
Form.EventObserver=Class.create();
Form.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{
getValue:function(){
return Form.serialize(this.element);}});
if(!window.Event){
var Event=new Object();}
Object.extend(Event,{
KEY_BACKSPACE:8,
KEY_TAB:9,
KEY_RETURN:13,
KEY_ESC:27,
KEY_LEFT:37,
KEY_UP:38,
KEY_RIGHT:39,
KEY_DOWN:40,
KEY_DELETE:46,
element:function(event){
return event.target||event.srcElement;},
isLeftClick:function(event){
return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},
pointerX:function(event){
return event.pageX||(event.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft));},
pointerY:function(event){
return event.pageY||(event.clientY+(document.documentElement.scrollTop||document.body.scrollTop));},
stop:function(event){
if(event.preventDefault){
event.preventDefault();
event.stopPropagation();}else{
event.returnValue=false;
event.cancelBubble=true;}},
findElement:function(event,tagName){
var element=Event.element(event);
while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase())))
element=element.parentNode;
return element;},
observers:false,
_observeAndCache:function(element,name,observer,useCapture){
if(!this.observers)this.observers=[];
if(element.addEventListener){
this.observers.push([element,name,observer,useCapture]);
element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){
this.observers.push([element,name,observer,useCapture]);
element.attachEvent('on'+name,observer);}},
unloadCache:function(){
if(!Event.observers)return;
for(var i=0;i<Event.observers.length;i++){
Event.stopObserving.apply(this,Event.observers[i]);
Event.observers[i][0]=null;}
Event.observers=false;},
observe:function(element,name,observer,useCapture){
var element=$(element);
useCapture=useCapture||false;
if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent))
name='keydown';
this._observeAndCache(element,name,observer,useCapture);},
stopObserving:function(element,name,observer,useCapture){
var element=$(element);
useCapture=useCapture||false;
if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent))
name='keydown';
if(element.removeEventListener){
element.removeEventListener(name,observer,useCapture);}else if(element.detachEvent){
element.detachEvent('on'+name,observer);}}});
Event.observe(window,'unload',Event.unloadCache,false);
var Position={
includeScrollOffsets:false,
prepare:function(){
this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;},
realOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.scrollTop||0;
valueL+=element.scrollLeft||0;
element=element.parentNode;}while(element);
return[valueL,valueT];},
cumulativeOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
element=element.offsetParent;}while(element);
return[valueL,valueT];},
positionedOffset:function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
element=element.offsetParent;
if(element){
p=Element.getStyle(element,'position');
if(p=='relative'||p=='absolute')break;}}while(element);
return[valueL,valueT];},
offsetParent:function(element){
if(element.offsetParent)return element.offsetParent;
if(element==document.body)return element;
while((element=element.parentNode)&&element!=document.body)
if(Element.getStyle(element,'position')!='static')
return element;
return document.body;},
within:function(element,x,y){
if(this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element,x,y);
this.xcomp=x;
this.ycomp=y;
this.offset=this.cumulativeOffset(element);
return(y>=this.offset[1]&&
y<this.offset[1]+element.offsetHeight&&
x>=this.offset[0]&&
x<this.offset[0]+element.offsetWidth);},
withinIncludingScrolloffsets:function(element,x,y){
var offsetcache=this.realOffset(element);
this.xcomp=x+offsetcache[0]-this.deltaX;
this.ycomp=y+offsetcache[1]-this.deltaY;
this.offset=this.cumulativeOffset(element);
return(this.ycomp>=this.offset[1]&&
this.ycomp<this.offset[1]+element.offsetHeight&&
this.xcomp>=this.offset[0]&&
this.xcomp<this.offset[0]+element.offsetWidth);},
overlap:function(mode,element){
if(!mode)return 0;
if(mode=='vertical')
return((this.offset[1]+element.offsetHeight)-this.ycomp)/
element.offsetHeight;
if(mode=='horizontal')
return((this.offset[0]+element.offsetWidth)-this.xcomp)/
element.offsetWidth;},
clone:function(source,target){
source=$(source);
target=$(target);
target.style.position='absolute';
var offsets=this.cumulativeOffset(source);
target.style.top=offsets[1]+'px';
target.style.left=offsets[0]+'px';
target.style.width=source.offsetWidth+'px';
target.style.height=source.offsetHeight+'px';},
page:function(forElement){
var valueT=0,valueL=0;
var element=forElement;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
if(element.offsetParent==document.body)
if(Element.getStyle(element,'position')=='absolute')break;}while(element=element.offsetParent);
element=forElement;
do{
valueT-=element.scrollTop||0;
valueL-=element.scrollLeft||0;}while(element=element.parentNode);
return[valueL,valueT];},
clone:function(source,target){
var options=Object.extend({
setLeft:true,
setTop:true,
setWidth:true,
setHeight:true,
offsetTop:0,
offsetLeft:0},arguments[2]||{})
source=$(source);
var p=Position.page(source);
target=$(target);
var delta=[0,0];
var parent=null;
if(Element.getStyle(target,'position')=='absolute'){
parent=Position.offsetParent(target);
delta=Position.page(parent);}
if(parent==document.body){
delta[0]-=document.body.offsetLeft;
delta[1]-=document.body.offsetTop;}
if(options.setLeft)target.style.left=(p[0]-delta[0]+options.offsetLeft)+'px';
if(options.setTop)target.style.top=(p[1]-delta[1]+options.offsetTop)+'px';
if(options.setWidth)target.style.width=source.offsetWidth+'px';
if(options.setHeight)target.style.height=source.offsetHeight+'px';},
absolutize:function(element){
element=$(element);
if(element.style.position=='absolute')return;
Position.prepare();
var offsets=Position.positionedOffset(element);
var top=offsets[1];
var left=offsets[0];
var width=element.clientWidth;
var height=element.clientHeight;
element._originalLeft=left-parseFloat(element.style.left||0);
element._originalTop=top-parseFloat(element.style.top||0);
element._originalWidth=element.style.width;
element._originalHeight=element.style.height;
element.style.position='absolute';
element.style.top=top+'px';;
element.style.left=left+'px';;
element.style.width=width+'px';;
element.style.height=height+'px';;},
relativize:function(element){
element=$(element);
if(element.style.position=='relative')return;
Position.prepare();
element.style.position='relative';
var top=parseFloat(element.style.top||0)-(element._originalTop||0);
var left=parseFloat(element.style.left||0)-(element._originalLeft||0);
element.style.top=top+'px';
element.style.left=left+'px';
element.style.height=element._originalHeight;
element.style.width=element._originalWidth;}}
if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){
Position.cumulativeOffset=function(element){
var valueT=0,valueL=0;
do{
valueT+=element.offsetTop||0;
valueL+=element.offsetLeft||0;
if(element.offsetParent==document.body)
if(Element.getStyle(element,'position')=='absolute')break;
element=element.offsetParent;}while(element);
return[valueL,valueT];}}


/******************Prototype.js - End *********************/
/******************Common.js - Start *********************/

function $I(id){
Claim.isString(id,"$I.id");
var element=$(id);
Claim.isObject(element,"Required HTML element id: "+id);
return element;}
function $F(id){
Claim.isString(id,"$F.id")
Claim.isObject($(id),"Required form element id: "+id)
return Form.Element.getValue(id)}
function $T(tagName){
var element=document.getElementsByTagName(tagName).item(0)
Claim.isObject(element,"Required HTML element tag: "+tagName)
return element}
function $SO(id){
return $I(id).options[$I(id).selectedIndex]}
Number.prototype.toText=function(base,width){
Claim.isNumber(base,"Number.toText.base")
Claim.isTrue(base>0,"Number.toText.base")
Claim.isNumber(width,"Number.toText.width")
Claim.isTrue(width>=0,"Number.toText.width")
var text=this.toString(base||10)+""
while(text.length<width)
text="0"+text
return text}
Number.prototype.toDec=function(width){
Claim.isNumber(width,"Number.toText.width")
Claim.isTrue(width>=0,"Number.toText.width")
return this.toText(10,width)}
Number.prototype.toHex=function(width){
Claim.isNumber(width,"width","Number.toText.width")
Claim.isTrue(width>=0,"width","Number.toText.width")
return this.toText(16,width)}
Date.prototype.toText=function(){
var year=this.getUTCFullYear().toDec(4)
var month=this.getUTCMonth().toDec(2)
var day=this.getUTCDate().toDec(2)
var hours=this.getUTCHours().toDec(2)
var minutes=this.getUTCMinutes().toDec(2)
var seconds=this.getUTCSeconds().toDec(2)
var milliseconds=this.getUTCMilliseconds().toDec(3)
return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds+"."+milliseconds}
var PreLoad={}
PreLoad.preLoad=function(){
PreLoad.log=new Log4Js.Logger("PreLoad")}
PreLoad.onLoad=function(){
PreLoad.log.debug("Done pre-load")}
PreLoad.actions=[]
PreLoad.actions.push(PreLoad.preLoad)
Event.observe(window,"load",PreLoad.onLoad)
var Url={}
Url.parse=function(url){
Claim.isString(url,"Url.parse.url")
var parsed={}
parsed.full=url
parsed.base=url.replace(/\?.*$/,'')
parsed.protocol=url.replace(/:.*$/,'')
parsed.domain=
parsed.base.replace(/^[^:]*:\/[\/]/,'').replace(/[:\/].*$/,'')
parsed.path=parsed.base.replace(/^[^\/]*\/\/[^\/]*[\/]/,'/')
parsed.query=url.replace(/^[^?]*\??/,'')
parsed.params=
parsed.query.split("&").inject({},function(params,paramValue){
pair=paramValue.split("=")
params[pair[0]]=unescape(pair[1])
return params})
return parsed}
Url.trimAnchor=function(url){
var i=url.lastIndexOf("#");
var isHasSharpMark=i>-1
var isHasQMark=url.lastIndexOf("?")>-1
if(isHasSharpMark&&((isHasQMark&&i>url.lastIndexOf("="))||!isHasQMark)){
url=url.substr(0,i);}
return url;}
Url.appendParams=function(url,params){
Claim.isString(url,"Url.appendParams.url")
if(!params||params=="")
return url
if(typeof(params)=="string")
return url+(url.match(/\?/)?"&":"?")+params
return $A($H(params).keys().sort()).inject(url,function(url,param){
return Url.appendParamValue(url,param,params[param])})}
Url.appendParamValue=function(url,param,value){
Claim.isString(url,"Url.appendParamValue.url")
Claim.isString(param,"Url.appendParamValue.param")
Claim.isScalar(value,"Url.appendParamValue.value")
return url+(url.match(/\?/)?"&":"?")+escape(param)+"="+escape(value)}
Url.relativeUrl=function(options){
Claim.isObject(options,"Url.relativeUrl.options")
var protocol=options.protocol||Url.here.protocol
Claim.isString(protocol,"Url.relativeUrl.options.protocol")
var domain=options.domain||Url.here.domain
Claim.isString(domain,"Url.relativeUrl.options.domain")
var path=options.path||Url.here.path
Claim.isString(path,"Url.relativeUrl.options.path")
if(!path.match(/^[\/]/)){
var base=Url.here.path
path="../"+path
while(path.match(/^\.\.[\/]/)){
path=path.replace(/^\.\.[\/]/,"")
base=base.replace(/\/[^\/]+$/,"")}
path=base+"/"+path}
var params={}
var withHereParams=options.withHereParams||false
Claim.isBoolean(withHereParams,
"Url.relativeUrl.options.withHereParams")
if(withHereParams)
Object.extend(params,Url.here.params)
var withClearanceParams=options.withClearanceParams
if(withClearanceParams==undefined)
withClearanceParams=domain!=Url.here.domain
Claim.isBoolean(withClearanceParams,
"Url.relativeUrl.options.withClearanceParams")
if(withClearanceParams){
Object.extend(params,Clearance.getAllLevelParams())}
var optionsParams=options.params||{}
Claim.isObject(optionsParams,"Url.relativeUrl.options.params")
Object.extend(params,options.params||{})
return Url.appendParams(protocol+":/"+"/"+domain+path,params)}
Url.here=undefined
Url.preLoad=function(){
Url.here=Url.parse(location.href)}
PreLoad.actions.push(Url.preLoad)
var Claim={}
Claim.check=function(condition,claim,comment){
if(!comment)
comment=claim
else
comment=claim+": "+comment
var log=Claim.log
Claim.log=undefined
try{
if(condition){
if(log)
log.debug(comment)}
else{
if(log)
log.error(comment)
else
alert(comment)
throw new Error(comment)}}
finally{
Claim.log=log}}
Claim.valueType=function(object){
if(object==undefined)
return "undefined"
if(object==null)
return "null"
return typeof(object)+"("+object+")"}
Claim.isTrue=function(condition,comment){
Claim.check(condition,
"isTrue("+Claim.valueType(condition)+")",
comment)}
Claim.isFalse=function(condition,comment){
Claim.check(!condition,
"isFalse("+Claim.valueType(condition)+")",
comment)}
Claim.isNull=function(object,comment){
Claim.check(typeof(object)==null,
"isNull("+Claim.valueType(object)+")",
comment)}
Claim.isNotNull=function(object,comment){
Claim.check(typeof(object)!=null,
"isNotNull("+Claim.valueType(object)+")",
comment)}
Claim.isUndefined=function(object,comment){
Claim.check(typeof(object)=='undefined',
"isUndefined("+Claim.valueType(object)+")",
comment)}
Claim.isNotUndefined=function(object,comment){
Claim.check(typeof(object)!='undefined',
"isNotUndefined("+Claim.valueType(object)+")",
comment)}
Claim.isObject=function(object,comment){
Claim.check(!!object,
"isObject("+Claim.valueType(object)+")",
comment)}
Claim.isNumber=function(object,comment){
Claim.check(typeof(object)=="number",
"isNumber("+Claim.valueType(object)+")",
comment)}
Claim.isBoolean=function(object,comment){
Claim.check(typeof(object)=="boolean",
"isBoolean("+Claim.valueType(object)+")",
comment)}
Claim.isString=function(object,comment){
Claim.check(typeof(object)=="string",
"isString("+Claim.valueType(object)+")",
comment)}
Claim.isScalar=function(object,comment){
Claim.check(typeof(object)=="string"||typeof(object)=="number"||typeof(object)=="boolean",
"isScalar("+Claim.valueType(object)+")",
comment)}
Claim.isArray=function(object,comment){
Claim.check(object&&object.length!=undefined,
"isArray("+Claim.valueType(object)+")",
comment)}
Claim.areEqual=function(object1,object2,comment){
Claim.check(object1==object2,
"areEqual("+Claim.valueType(object1)+" ? "+Claim.valueType(object2)+")",
comment)}
Claim.isFunction=function(object,comment){
Claim.check(typeof(object)=='function',
"isFunction("+Claim.valueType(object)+")",
comment)}
Claim.preLoad=function(){
Claim.log=new Log4Js.Logger("Claim")}
PreLoad.actions.push(Claim.preLoad)
var Cookies={}
Cookies.defaultOptions={}
Cookies.rawByName={}
Cookies.valueByName={}
Cookies.set=function(name,value,options){
Claim.isString(name,"Cookies.set.name")
Claim.isObject(value,"Cookies.set.value")
var fullOptions=Cookies.fullOptions(name,options)
var raw=Cookies.toJson(value)
Cookies.valueByName[name]=value
Cookies.rawByName[name]=raw
var cookie=Cookies.fullCookie(name,raw,fullOptions)
Cookies.log.info("Set cookie: "+cookie)
document.cookie=cookie}
Cookies.get=function(name){
Claim.isString(name,"Cookies.get.name")
return Cookies.valueByName[name]}
Cookies.clear=function(name,options){
Claim.isString(name,"Cookies.clear.name")
var fullOptions=Cookies.fullOptions(name,options)
fullOptions.expires=Cookies.expiration(-1)
var cookie=Cookies.fullCookie(name,"",fullOptions)
delete(Cookies.rawByName[name])
delete(Cookies.valueByName[name])
Cookies.log.info("Clear cookie: "+cookie)
document.cookie=cookie}
Cookies.fullOptions=function(name,options){
Claim.isString(name,"Cookies.fullOptions.name")
var fullOptions=Object.extend({},Cookies.defaultOptions)
fullOptions=Object.extend(fullOptions,options||{})
if(!fullOptions.path){
var error="Set cookie name: "+name+" without a path"
Cookies.log.error(error)
throw error}
if(fullOptions.path.charAt(0)!="/"){
var error="Set cookie name: "+name+" invalid path: "+fullOptions.path
Cookies.log.error(error)
throw error}
if(!fullOptions.domain){
var error="Set cookie name: "+name+" without a domain"
Cookies.log.error(error)
throw error}
if(fullOptions.domain.charAt(0)!="."){
var error="Set cookie name: "+name+" invalid domain: "+fullOptions.domain
Cookies.log.error(error)
throw error}
return fullOptions}
Cookies.expiration=function(millis){
Claim.isNumber(millis,"Cookies.expiration.millis")
var today=new Date()
var now=Date.parse(today)
today.setTime(now+1*millis)
return today.toUTCString()}
Cookies.fullCookie=function(name,raw,options){
Claim.isString(name,"Cookies.fullCookie.name")
var cookie=name+"="+raw
$H(options).each(function(pair){
if(pair[1]!=undefined)
cookie+=";"+pair[0]+"="+pair[1]})
return cookie}
Cookies.toJson=function(object){
if(object==undefined)
return "undefined"
if(object==null)
return "null"
if(typeof(object)=="string")
return "\"" + Cookies.jsonEscape(object.toString()) + "\""
if(typeof(object)=="number"||typeof(object)=="boolean")
return object.toString()
if(object.toJson)
return object.toJson()
var json=""
var seperator=""
if(typeof object=='object'&&object.constructor.toString().match(/array/i)!=null){
$A(object).each(function(value){
json+=seperator+Cookies.toJson(value)
seperator=","})
return "["+json+"]"}
else{
var json=""
$H(object).each(function(pair){
json+=seperator+Cookies.toJson(pair[0])+":"+Cookies.toJson(pair[1])
seperator=","})
return "{"+json+"}"}}
Cookies.jsonEscape=function(text){
Claim.isString(text,"Claim.jsonEscape.text")
var escaped=""
for(var i=0;i<text.length;i++){
var code=text.charCodeAt(i)
if(code<32||code==59){
escaped+="\\u"+code.toHex(4)}
else{
var nextChar=text.charAt(i)
if(nextChar=="\"" || nextChar == "\\")
escaped+="\\"
escaped+=nextChar}}
return escaped}
Cookies.preLoad=function(){
Cookies.log=new Log4Js.Logger("Cookies")
Cookies.defaultOptions.path="/"
Cookies.defaultOptions.domain=
"."+Url.here.domain.replace(/^[a-zA-Z0-9\-]+./,'')
document.cookie.split(';').each(function(cookie){
if(!cookie){
if(Cookies.rawByName!=undefined){
Cookies.rawByName={};
Cookies.valueByName={};}
throw $break}
var name=cookie.replace(/^\s*([^=]+)=.*$/,'$1')
var raw=cookie.replace(/^[^=]*=/,'')
Cookies.rawByName[name]=raw
Cookies.log.info("Load cookie name: "+name+" value: "+raw)
try{
var value=undefined
eval("value="+raw)
Cookies.valueByName[name]=value}
catch(error){
Cookies.log.error("Invalid cookie name: "+name+" value: "+value+" error: "+error)
Cookies.valueByName[name]=null}})}
Cookies.pop=function(){
var each,s=[];
for(each in this.rawByName){
s[s.length]=each
s[s.length]=":"
s[s.length]=this.rawByName[each]
s[s.length]="\n"}
alert(unescape(s.join("")));}
PreLoad.actions.push(Cookies.preLoad)
var Log4Js={}
Log4Js.levelNames=["All","Debug","Info","Warn","Error","Fatal","None"]
Log4Js.ALL=0
Log4Js.DEBUG=1
Log4Js.INFO=2
Log4Js.WARN=3
Log4Js.ERROR=4
Log4Js.FATAL=5
Log4Js.NONE=6
Log4Js.configVersion=0
Log4Js.targetsByName={"*":[]}
Log4Js.setTargets=function(name,targets){
Claim.isString(name,"Log4Js.setTargets.name")
Claim.isArray(targets,"Log4Js.setTargets.targets")
Log4Js.targetsByName[name]=targets
Log4Js.configVersion++}
Log4Js.removeTargets=function(name){
Claim.isString(name,"Log4Js.removeTargets.name")
if(name=="*")
Log4Js.targetsByName[name]=[]
else
delete(Log4Js.targetsByName[name])
Log4Js.configVersion++}
Log4Js.getTargets=function(name){
Claim.isString(name,"Log4Js.getTargets.name")
return Log4Js.targetsByName[name]}
Log4Js.findPrefix=function(name){
Claim.isString(name,"Log4Js.findPrefix.name")
while(true){
if(name=="")
name="*"
var targets=Log4Js.targetsByName[name]
if(targets)
return name
var lastDot=name.lastIndexOf(".")
name=lastDot>0?name.substring(0,lastDot):""}}
Log4Js.findTargets=function(name){
Claim.isString(name,"Log4Js.findTargets.name")
return this.getTargets(this.findPrefix(name))}
Log4Js.toConfig=function(){
var anchorsByName={}
var targetAnchorByJson={}
var targetByAnchor={}
var nextAnchor=1
$H(Log4Js.targetsByName).each(function(pair){
var name=pair[0]
var targets=pair[1]
anchorsByName[name]=targets.inject([],function(anchors,target){
var json=target.toJson()
var anchor=targetAnchorByJson[json]
if(!anchor){
anchor=targetAnchorByJson[json]="t"+nextAnchor++
targetByAnchor[anchor]=target}
anchors.push(anchor)
return anchors})})
return{targetByAnchor:targetByAnchor,anchorsByName:anchorsByName}}
Log4Js.fromConfig=function(config){
Claim.isObject(config,"Log4Js.fromConfig.config")
Claim.isObject(config.anchorsByName,
"Log4Js.fromConfig.config.anchorsByName")
Claim.isObject(config.targetByAnchor,
"Log4Js.fromConfig.config.targetByAnchor")
var targetsByName=
$H(config.anchorsByName).inject({},function(targetsByName,pair){
var name=pair[0]
var anchors=pair[1]
targetsByName[name]=
$A(anchors).inject([],function(targets,anchor){
targets.push(config.targetByAnchor[anchor])
return targets})
return targetsByName})
Log4Js.targetsByName=targetsByName
Log4Js.configVersion++}
Log4Js.pop=function(conf){
if(!conf||typeof(conf)!='object'){
conf={anchorsByName:{"*":["t1"],Claim:["t2"]},targetByAnchor:{t1:new Log4Js.PopupTarget(Log4Js.ALL,"log4js-%U-%T",true),t2:new Log4Js.PopupTarget(Log4Js.FATAL,"log4js-%U-%T",true)}};}
Cookies.set("log4js.config",conf,{});
this.fromConfig(conf);}
Log4Js.add=function(sClassName,enLEVEL){
Claim.isString(sClassName,"Log4Js.add(sClassName, enLEVEL) - sClassName must be a string");
Claim.isString(enLEVEL,"Log4Js.add(sClassName, enLEVEL) - enLEVEL must Log Level ALL, DEBUG, WARN, ...");
var iLevel=this[enLEVEL.toUpperCase()];
Claim.isNumber(iLevel,"Log4Js.add(sClassName, enLEVEL) - Log4Js."+enLEVEL+" is not a valid warn-level");
Claim.check(iLevel>=0&&iLevel<=6,"0 <= iLevel <= 6","Log4Js.add(sClassName, enLEVEL) - Log4Js[enLEVEL must be between 0 to 6");
var conf=this.toConfig();
conf.targetByAnchor.newAnchor=new Log4Js.PopupTarget(iLevel,"log4js-%U-%T",true)
conf.anchorsByName[sClassName]=["newAnchor"];
this.pop(conf);}
Log4Js.clear=function(sClassName){
Claim.isString(sClassName,"Log4Js.clear(sClassName) - sClassName must be a string");
var conf=this.toConfig();
delete conf.anchorsByName[sClassName];
this.pop(conf);}
Log4Js.stop=function(){
var conf={anchorsByName:{"*":["t1"]},targetByAnchor:{t1:new Log4Js.PopupTarget(Log4Js.NONE,"log4js-%U-%T",true)}};
Cookies.set("log4js.config",conf,{});
this.fromConfig(conf);}
Log4Js.preLoad=function(){
var config=Cookies.get("log4js.config")
if(config)
Log4Js.fromConfig(config)
PreLoad.log.debug("Start pre-load")}
PreLoad.actions.push(Log4Js.preLoad)
Log4Js.Logger=Class.create()
Log4Js.Logger.prototype={}
Log4Js.Logger.prototype.initialize=function(name){
Claim.isString(name,"Log4Js.Logger.name")
this.name=name
this.configVersion=-1}
Log4Js.Logger.prototype.debug=function(text){
this.emit(Log4Js.DEBUG,text)}
Log4Js.Logger.prototype.info=function(text){
this.emit(Log4Js.INFO,text)}
Log4Js.Logger.prototype.warn=function(text){
this.emit(Log4Js.WARN,text)}
Log4Js.Logger.prototype.error=function(text){
this.emit(Log4Js.ERROR,text)}
Log4Js.Logger.prototype.fatal=function(text){
this.emit(Log4Js.FATAL,text)}
Log4Js.Logger.prototype.emit=function(level,text){
if(this.configVersion<Log4Js.configVersion){
this.targets=Log4Js.findTargets(this.name)
this.configVersion=Log4Js.configVersion}
if(this.targets.length>0){
Claim.isNumber(level,"Log4Js.Logger.emit.level")
Claim.isTrue(Log4Js.DEBUG<=level&&level<=Log4Js.FATAL)
Claim.isScalar(text,"text")
var event={
time:new Date().toText(),
level:level,
name:this.name,
text:text,
url:location.href}
this.targets.each(function(target){target.emit(event)})}}
Log4Js.AbstractTarget=function(){}
Log4Js.AbstractTarget.prototype={}
Log4Js.AbstractTarget.prototype.emit=function(event){
Claim.isObject(event,"Log4Js.AbstractTarget.emit.event")
Claim.isNumber(event.level,"Log4Js.AbstractTarget.emit.event.level")
if(event.level>=this.level)
this._emit(event)}
Log4Js.AlertTarget=Class.create()
Log4Js.AlertTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.AlertTarget.prototype.initialize=function(level){
Claim.isNumber(level,"Log4Js.AlertTarget.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,
"Log4Js.AlertTarget.level")
this.level=level}
Log4Js.AlertTarget.prototype._emit=function(event){
Claim.isObject(event,"Log4Js.AlertTarget._emit.event")
alert(event.time+" "+event.url+" "+Log4Js.levelNames[event.level]+" "+event.name+":\n"+event.text)}
Log4Js.AlertTarget.prototype.toJson=function(){
return "new Log4Js.AlertTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+")"}
Log4Js.TableTarget=Class.create()
Log4Js.TableTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.TableTarget.prototype.backLog=[]
Log4Js.TableTarget.prototype.initialize=function(level,table,isLastOnTop){
Claim.isNumber(level,"Log4Js.TableTarget.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,
"Log4Js.TableTarget.level")
Claim.isObject(table,"Log4Js.TableTarget.table")
Claim.isBoolean(isLastOnTop,"Log4Js.TableTarget.isLastOnTop")
this.level=level
this.isLastOnTop=isLastOnTop
if(typeof(table)=="string"){
this.name=table
this.table=$(table)}
else{
this.name=table.id
this.table=table}}
Log4Js.TableTarget.prototype.initTable=function(event){
Claim.isObject(event,"Log4Js.TableTarget.initTable.event")
this.table=this.table||$(this.name)
if(!this.table)
return false
if(this.table.rows.length>0)
return true
var row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML="Time"
row.insertCell(-1).innerHTML="Level"
row.insertCell(-1).innerHTML="Name"
row.insertCell(-1).innerHTML="Text"
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML="<hr />"
row.insertCell(-1).innerHTML="LOG4JS"
row.insertCell(-1).innerHTML=event.url
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML="<hr />"
row.insertCell(-1).innerHTML="LOG4JS"
row.insertCell(-1).innerHTML=event.url
row=this.table.insertRow(-1)
row.insertCell(-1).innerHTML="Time"
row.insertCell(-1).innerHTML="Level"
row.insertCell(-1).innerHTML="Name"
row.insertCell(-1).innerHTML="Text"
return true}
Log4Js.TableTarget.prototype._emit=function(event){
Claim.isObject(event,"Log4Js.TableTarget._emit.event")
this.backLog.push(event)
if(!this.initTable(event))
return
while(this.backLog.length>0){
var event=this.backLog.shift()
var row=this.table.insertRow(this.isLastOnTop?2:-1)
row.insertCell(-1).innerHTML=event.time
row.insertCell(-1).innerHTML=Log4Js.levelNames[event.level]
row.insertCell(-1).innerHTML=event.name
row.insertCell(-1).innerHTML=event.text}}
Log4Js.TableTarget.prototype.toJson=function(){
return "new Log4Js.TableTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+","+Cookies.toJson(this.name)+","+Cookies.toJson(this.isLastOnTop)+")"}
Log4Js.PopupTarget=Class.create()
Log4Js.PopupTarget.prototype=new Log4Js.AbstractTarget()
Log4Js.PopupTarget.windows={}
Log4Js.PopupTarget.prototype.initialize=function(level,name,isLastOnTop){
Claim.isNumber(level,"Log4Js.Prototype.level")
Claim.isTrue(Log4Js.ALL<=level&&level<=Log4Js.NONE,
"Log4Js.Prototype.level")
Claim.isString(name,"Log4Js.Prototype.name")
Claim.isBoolean(isLastOnTop,"Log4Js.Prototype.isLastOnTop")
this.name=name
name=name.replace(/%T/,new Date().toText())
name=name.replace(/%U/,location.href)
name=name.replace(/\W+/g,'_')
name=name.replace(/[_]+/g,'_')
this.windowName=name
this.level=level
this.isLastOnTop=isLastOnTop}
Log4Js.PopupTarget.prototype._emit=function(event){
Claim.isObject(event,"Log4Js.Prototype._emit.event")
if(!this.window||this.window.closed){
this.window=Log4Js.PopupTarget.windows[name]
if(!this.window||this.window.closed){
this.window=Log4Js.PopupTarget.windows[name]=
window.open("",this.windowName,
'width=640,height=480,'+'scrollbars=1,status=0,toolbars=0,resizable=1')
if(!this.window||this.window.closed){
alert("A popup window manager is blocking the logger "+"popup display.\n"+"You need to allow popups to see the logged events.")
this.emit=function(event){}
return}
this.window.document.writeln("<table id='log-table'></table>")
this.window.document.close()}
this.table=this.window.document.getElementById("log-table")
this.target=
new Log4Js.TableTarget(this.level,this.table,this.isLastOnTop)}
this.target._emit(event)}
Log4Js.PopupTarget.prototype.toJson=function(){
return "new Log4Js.PopupTarget(Log4Js."+Log4Js.levelNames[this.level].toUpperCase()+","+Cookies.toJson(this.name)+","+Cookies.toJson(this.isLastOnTop)+")"}
var Clearance={}
Clearance.MEMBER=0;
Clearance.GUEST=1;
Clearance.levelNames=["Anonymnous","Unclassified","Restricted","Confidential"]
Clearance.ANONYMOUS=0
Clearance.UNCLASSIFIED=1
Clearance.RESTRICTED=2
Clearance.CONFIDENTIAL=3
Clearance.level=undefined
Clearance.userId=undefined
Clearance.isLevel=function(level){
return Clearance.level==level}
Clearance.hasLevel=function(level){
Claim.isNumber(level,"Clearance.hasLevel.level")
Claim.isTrue(0<=level&&level<=Clearance.CONFIDENTIAL,
"Clearance.hasLevel.level")
if(Clearance.hasLoginType()==true){
return Clearance.level>=level}return false;}
Clearance.requireLevel=function(requiredLevel,loginUrl,urlParam){
Claim.isNumber(requiredLevel,"Clearance.requireLevel.requiredLevel")
var minLevel=Clearance.ANONYMOUS
var maxLevel=Url.here.protocol=="https"?Clearance.CONFIDENTIAL:Clearance.UNCLASSIFIED
Claim.isTrue(minLevel<=requiredLevel&&requiredLevel<=maxLevel,
"Clearance.requireLevel.requiredLevel")
Claim.isString(loginUrl,"Clearance.requireLevel.loginUrl")
Claim.isString(urlParam,"Clearance.requireLevel.urlParam")
Clearance.log.debug("Required: "+requiredLevel+" level: "+Clearance.level)
if(Clearance.level<requiredLevel){
var url=Url.appendParamValue(loginUrl,urlParam,location.href)
Clearance.log.info("Redirect to "+url)
location=url}}
Clearance.isUnclassified=function(){
return Clearance.isLevel(Clearance.UNCLASSIFIED)}
Clearance.hasUnclassified=function(){
return Clearance.hasLevel(Clearance.UNCLASSIFIED)}
Clearance.isGuest=function(){
var currentLoginType=Clearance.loginType();
if(currentLoginType){
if(currentLoginType==Clearance.GUEST)
return true;
return false;}}
Clearance.isMember=function(){
var currentLoginType=Clearance.loginType();
if(currentLoginType){
if(currentLoginType==Clearance.MEMBER)
return true;
return false;}}
Clearance.hasLoginType=function(){
if(Clearance.loginType())
return true;
return false;}
Clearance.loginType=function(){
var unclCookie=
Cookies.get(Clearance.cookieName(Clearance.UNCLASSIFIED,true));
if(unclCookie){
var cookieParams=unclCookie.en.toQueryParams()
if(cookieParams["LT"])
return cookieParams["LT"];}
return null}
Clearance.refresh=function(){
Cookies.preLoad();
Clearance.preLoad();}
Clearance.load=function(sessionToken){
var sessionQuerystring=sessionToken.replace(/^[^?]*\??/,'');
if(sessionQuerystring.length==0)
sessionQuerystring=sessionToken;
Url.here.params=sessionQuerystring.split("&").inject({},function(params,paramValue){
pair=paramValue.split("=")
params[pair[0]]=unescape(pair[1])
return params})
Clearance.refresh();}
Clearance.requireUnclassified=function(loginUrl,param){
Clearance.requireLevel(Clearance.UNCLASSIFIED,loginUrl,param)}
Clearance.isRestricted=function(){
return Clearance.isLevel(Clearance.RESTRICTED)}
Clearance.hasRestricted=function(){
return Clearance.hasLevel(Clearance.RESTRICTED)},
Clearance.requireRestricted=function(loginUrl,param){
Clearance.requireLevel(Clearance.RESTRICTED,loginUrl,param)}
Clearance.isConfidential=function(){
return Clearance.isLevel(Clearance.CONFIDENTIAL)}
Clearance.hasConfidential=function(){
return Clearance.hasLevel(Clearance.CONFIDENTIAL)}
Clearance.requireConfidential=function(loginUrl,param){
Clearance.requireLevel(Clearance.CONFIDENTIAL,loginUrl,param)}
Clearance.getExpiration=function(expiration){
if(typeof(expiration)!="number")
return
var dateExpiration=new Date(expiration)
var dateNow=new Date()
shouldbeexpired=Number(dateExpiration.getTime())-Number(dateNow.getTime());
if(shouldbeexpired>0)
return shouldbeexpired
else
return}
Clearance.getParams=function(level){
Claim.isNumber(level,"Clearance.getEncrypted.level")
Claim.isTrue(level>=Clearance.UNCLASSIFIED&&level<=Clearance.CONFIDENTIAL,
"Clearance.getEncrypted.level")
if(!Clearance.hasLevel(level))
return null
var params={}
params.ux=Clearance.getExpiration(Clearance.params.ux)
if(params.ux){
params.un=Clearance.params.un
params.ui=Clearance.params.ui}else{
Clearance.level=0;
return null}
if(level>=Clearance.RESTRICTED){
params.rx=Clearance.getExpiration(Clearance.params.rx)
if(params.rx)
params.rn=Clearance.params.rn}
if(level>=Clearance.CONFIDENTIAL){
params.cx=Clearance.getExpiration(Clearance.params.cx)
if(params.cx)
params.cn=Clearance.params.cn}
return params}
Clearance.getAllLevelParams=function(){
var params={}
for(level=1;level<=3;level=level+1){
Object.extend(params,Clearance.getParams(level))}
return params;}
Clearance.getMagic=function(level){
params=Clearance.getParams(level)
if(params)
return Url.appendParams("",params)
return null}
Clearance.prefix=["Oberon1.A.","Oberon1.U.","Oberon1.R.","Oberon1.C."],
Clearance.cookieName=function(level,isTimed){
Claim.isNumber(level,"Clearance.cookieName.level")
Claim.isTrue(level>=Clearance.ANONYMOUS&&level<=Clearance.CONFIDENTIAL,
"Clearance.cookieName.level")
Claim.isBoolean(isTimed,"Clearance.cookieName.isTimed")
if(level>Clearance.UNCLASSIFIED)
return Clearance.prefix[level]+(isTimed?"T":"S")
else
return Clearance.prefix[level]}
Clearance.setCookies=function(level,userId,encrypted,expires){
Claim.isNumber(level,"Clearance.setCookies.level")
Claim.isTrue(level>=Clearance.ANONYMOUS&&level<=Clearance.CONFIDENTIAL,
"Clearance.setCookies.level")
if(level!=Clearance.ANONYMOUS)
Claim.isString(userId,"Clearance.setCookies.userId")
Claim.isString(encrypted,"Clearance.setCookies.encrypted")
var value={ui:userId,en:encrypted}
if(expires){
value.ex=expires
var date=new Date()
date.setSeconds(date.getSeconds()+Math.round(expires/1000))
Cookies.set(Clearance.cookieName(level,true),value,{expires:date.toUTCString()})
if(level>Clearance.UNCLASSIFIED){
Cookies.set(Clearance.cookieName(level,false),value,{expires:undefined})}}
else{
Claim.isTrue(level==Clearance.UNCLASSIFIED||level==Clearance.ANONYMOUS,
"Clearance.setCookies.level")
Cookies.set(Clearance.cookieName(level,true),value,{expires:undefined})}}
Clearance.clearCookies=function(level){
Claim.isNumber(level,"Clearance.clearCookies.level")
Claim.isTrue(level>=Clearance.UNCLASSIFIED&&level<=Clearance.CONFIDENTIAL,
"Clearance.clearCookies.level")
Cookies.clear(Clearance.cookieName(level,false),{})
Cookies.clear(Clearance.cookieName(level,true),{})}
Clearance.forget=function(url){
Clearance.log.debug("Forget user")
Clearance.clearCookies(Clearance.UNCLASSIFIED)
Clearance.clearCookies(Clearance.RESTRICTED)
Clearance.clearCookies(Clearance.CONFIDENTIAL)
var url=Url.appendParamValue(url,"ui","none")
Clearance.log.info("Redirect to "+url)
location=url}
Clearance.params={},
Clearance.preLoad=function(){
Clearance.urlParamsToCookies()
Clearance.level=Clearance.ANONYMOUS
Clearance.log.debug("Achieved Anonymnous")
if(Clearance.processCookies(Clearance.UNCLASSIFIED,"un","ux"))
if(Clearance.processCookies(Clearance.RESTRICTED,"rn","rx"))
Clearance.processCookies(Clearance.CONFIDENTIAL,"cn","cx")}
Clearance.urlParamsToCookies=function(){
Clearance.log=new Log4Js.Logger("Clearance")
Clearance.level=Clearance.ANONYMOUS
Clearance.log.debug("Try to access current URL clearance parameters")
if(Url.here.params.an){
Clearance.setCookies(Clearance.ANONYMOUS,
Url.here.params.ui,
Url.here.params.an);}
if(Url.here.params.ui){
if(Url.here.params.un&&Url.here.params.ux)
Clearance.setCookies(Clearance.UNCLASSIFIED,
Url.here.params.ui,
Url.here.params.un,((typeof(Url.here.params.ux)=="number")?(Url.here.params.ux*1000.0):Url.here.params.ux))
else if(Url.here.params.un)
Clearance.setCookies(Clearance.UNCLASSIFIED,
Url.here.params.ui,
Url.here.params.un,
null)
else
Clearance.clearCookies(Clearance.UNCLASSIFIED)}
Clearance.log.debug("Strip clearance params from URL")
delete(Url.here.params["ui"])
delete(Url.here.params["un"])
delete(Url.here.params["ux"])
delete(Url.here.params["rn"])
delete(Url.here.params["rx"])
delete(Url.here.params["cn"])
delete(Url.here.params["cx"])
delete(Url.here.params["an"])}
Clearance.processCookies=function(level,en,ex){
Claim.isNumber(level,"Clearance.processCookies.level")
Claim.isTrue(level>Clearance.level&&level<=Clearance.CONFIDENTIAL,
"Clearance.processCookies.level")
Clearance.log.debug("Process "+Clearance.prefix[level]+" cookies")
var sessionName=Clearance.cookieName(level,false)
var timedName=Clearance.cookieName(level,true)
var session=Cookies.get(sessionName)
var timed=Cookies.get(timedName)
if(!session){
Clearance.log.debug("No "+sessionName+" cookie => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed){
Clearance.log.debug("No "+timedName+" cookie => "+Clearance.levelNames[Clearance.level])
return false}
if(!session.ui){
Clearance.log.debug("No "+sessionName+".ui => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed.ui){
Clearance.log.debug("No "+timedName+".ui => "+Clearance.levelNames[Clearance.level])
return false}
if(session.ui!=timed.ui){
Clearance.log.debug("Mismatch {"+sessionName+","+timedName+"}.ui => "+Clearance.levelNames[Clearance.level])
return false}
if(!session.en){
Clearance.log.debug("No "+sessionName+".en => "+Clearance.levelNames[Clearance.level])
return false}
if(!timed.en){
Clearance.log.debug("No "+timedName+".en => "+Clearance.levelNames[Clearance.level])
return false}
if(session.en!=timed.en){
Clearance.log.debug("Mismatch {"+sessionName+","+timedName+"}.en => "+Clearance.levelNames[Clearance.level])
return false}
if(level>Clearance.UNCLASSIFIED){
if(session.ui!=Clearance.userId){
Clearance.log.debug("Mismatch "+sessionName+".ui => "+Clearance.levelNames[Clearance.level])
return false}}
else{
Clearance.params.ui=session.ui
Clearance.userId=session.ui}
Clearance.params[en]=session.en
var dateExpired=new Date()
var millExp=timed.ex?timed.ex:1
Clearance.params[ex]=Number(dateExpired.getTime())+Number(millExp)
Clearance.level=level
Clearance.log.debug("Achieved "+Clearance.levelNames[Clearance.level])
return true}
PreLoad.actions.push(Clearance.preLoad)
var Jast={}
Jast.timeout=20000
Jast.pendingRequestByUrl={}
Jast.pendingRequestById={}
Jast.isPreLoad=true
Jast.nextRequestId=0
Jast.activeRequestCount=0
Jast.response=function(id,isOk,result,caching){
Claim.isNumber(id,"Jast.response.id")
Claim.isBoolean(isOk,"Jast.response.isOk")
request=Jast.pendingRequestById[id]
if(!request){
Jast.Request.log.warn("Unknown load request id: "+id+" isOk: "+isOk)
return}
request.loaded(isOk,result,caching)}
Jast.clearCache=function(){
$H(Cookies.valueByName).keys.each(function(name){
if(name.substr(0,5)=="Jast.")
Cookies.clear(name)})}
Jast.Request=Class.create()
Jast.Request.prototype={}
Jast.Request.stateNames=[
"Uninitialized","Loading","Loaded","Interactive","Complete"]
Jast.Request.UNINITIALIZED=0
Jast.Request.LOADING=1
Jast.Request.LOADED=2
Jast.Request.INTERACTIVE=3
Jast.Request.COMPLETE=4
Jast.Request.statusNames=[
"Create","Success","Failure","Timeout"]
Jast.Request.CREATE=0
Jast.Request.SUCCESS=1
Jast.Request.FAILURE=2
Jast.Request.TIMEOUT=3
Jast.Request.preLoad=function(){
Jast.Request.log=new Log4Js.Logger("Jast.Request")}
PreLoad.actions.push(Jast.Request.preLoad)
Jast.Request.onLoad=function(){
Jast.isPreLoad=false
var length=Jast.nextRequestId
Jast.Request.log.debug("Complete "+length+" pre-load request(s)")
length.times(function(id){
request=Jast.pendingRequestById[id]
if(request&&!request.uses)
if(request.result)
request.complete()
else{
if(request.options.timeout>0){
request.setTimeout=
setTimeout(request.timedOut.bind(request),request.options.timeout)
Jast.Request.log.debug("Reset timeout for Preloaded Request. Request id: "+request.id+" setTimeout: "+request.setTimeout)}}})}
Event.observe(window,"load",Jast.Request.onLoad)
Jast.Request.prototype.initialize=function(url,options){
Claim.isString(url,"Jast.Request.url")
this.url=url
this.options={
timeout:Jast.timeout,
toReuse:true,
unimportant:[]}
Object.extend(this.options,options||{})
var parsed=Url.parse(url)
$A(this.options.unimportant).each(function(param){
delete(parsed.params[param])})
$A(["un","ux","rn","rx","cn","cx"]).each(function(param){
delete(parsed.params[param])})
this.cacheId=Url.appendParams(parsed.base,parsed.params)
this.cacheId="Just."+this.cacheId.replace(/[=;]/g,'_')
this.usedBy=[]
this.id=Jast.nextRequestId++
this.state=-1
this.status=Jast.Request.CREATE
Jast.Request.log.debug("Create request id: "+this.id+" url: "+this.url+" unimportant: "+Cookies.toJson(this.options.unimportant)+" cacheId: "+this.cacheId+" toReuse: "+this.options.toReuse+" timeout: "+this.options.timeout)
this.advanceTo(Jast.Request.UNINITIALIZED)
this.dispatch("onCreate")
var name
var cached=Cookies.get(name=this.cacheId+".T")||Cookies.get(name=this.cacheId+".S")
if(cached){
Jast.Request.log.debug("Fetch request id: "+this.id+" from cookie name: "+name)
if(Jast.isPreLoad){
Jast.pendingRequestByUrl[this.cacheId]=this
Jast.pendingRequestById[this.id]=this}
this.loaded(cached.isOk,cached.result,undefined)
return}
var request=Jast.pendingRequestByUrl[this.cacheId]
if(request&&this.options.toReuse&&request.options.toReuse&&request.state<=Jast.Request.LOADED){
Jast.Request.log.debug("Merge request id: "+this.id+" with request id: "+request.id+" state: "+Jast.Request.stateNames[request.state]+" status: "+Jast.Request.statusNames[request.status])
this.uses=request
this.advanceTo(request.state)
this.result=request.result
this.status=request.status
request.usedBy.push(this)}
else{
this.makeRequest()}}
Jast.Request.prototype.makeRequest=function(){
this.fullUrl=Url.appendParamValue(this.url,"jastId",this.id)
Jast.Request.log.info("Make request id: "+this.id+" fullUrl: "+this.fullUrl)
this.scriptId="jast-script-"+this.id
Jast.pendingRequestByUrl[this.cacheId]=this
Jast.pendingRequestById[this.id]=this
var isHeadNotExists=(0==document.getElementsByTagName("HEAD").length);
if(Jast.isPreLoad&&isHeadNotExists){
Jast.Request.log.debug("Write script id: "+this.scriptId+" for request id: "+this.id)
document.write("<"+"script")
document.write(' id="'+this.scriptId+'"')
document.write(' type="text/javascript"')
document.write(' src="'+this.fullUrl+'"')
document.write("></"+"script"+">")}
else{
Jast.Request.log.debug("Create script id: "+this.scriptId+" for request id: "+this.id)
script=document.createElement("script")
script.setAttribute("id",this.scriptId)
script.setAttribute("type","text/javascript")
script.setAttribute("src",this.fullUrl)
$T("head").appendChild(script)
if(this.options.timeout>0){
this.setTimeout=
setTimeout(this.timedOut.bind(this),this.options.timeout)
Jast.Request.log.debug("Request id: "+this.id+" setTimeout: "+this.setTimeout)}}
this.advanceTo(Jast.Request.LOADING)}
Jast.Request.prototype.loaded=function(isOk,result,caching){
Claim.isBoolean(isOk,"Jast.Request.loaded.isOk")
if(this.state>=Jast.Request.LOADED){
Jast.Request.log.warn("Reloaded request id: "+this.id+" isOk: "+isOk)
return}
Jast.Request.log.info("Loaded request id: "+this.id+" isOk: "+isOk)
if(this.setTimeout){
clearTimeout(this.setTimeout)
Jast.Request.log.debug("Request id: "+this.id+" clearTimeout: "+this.setTimeout)
delete(this["setTimeout"])}
if(caching&&caching.expires||session){
var value={isOk:isOk,result:result}
var session=caching.session
delete(caching["session"])
if(caching.expires){
Jast.Request.log.debug("Cache in: "+this.cacheId+".T for "+caching.expires+"ms")
Cookies.set(this.cacheId+".T",value,caching)}
delete(caching["expires"])
if(session){
Jast.Request.log.debug("Cache in: "+this.cacheId+".S for rest of session")
Cookies.set(this.cacheId+".S",value,caching)}}
this.advanceTo(Jast.Request.LOADED)
this.result=result
this.status=isOk?Jast.Request.SUCCESS:Jast.Request.FAILURE
var status=this.status
this.usedBy.each(function(request){
request.result=result
request.status=status})
if(!Jast.isPreLoad)
this.complete()}
Jast.Request.prototype.timedOut=function(){
if(this.state>=Jast.Request.LOADED){
Jast.Request.log.warn("Retimedout request id: "+this.id)
return}
Jast.Request.log.info("Timedout request id: "+this.id)
this.advanceTo(Jast.Request.LOADED)
this.status=Jast.Request.TIMEOUT
this.usedBy.each(function(request){
request.status=Jast.Request.TIMEOUT})
this.complete()}
Jast.Request.prototype.complete=function(){
Jast.Request.log.debug("Complete request id: "+this.id)
this.advanceTo(Jast.Request.INTERACTIVE)
this.dispatchUsed("on"+Jast.Request.statusNames[this.status])
this.advanceTo(Jast.Request.COMPLETE)
delete(Jast.pendingRequestByUrl[this.cacheId])
delete(Jast.pendingRequestById[this.id])
this.usedBy.each(function(request){
delete(Jast.pendingRequestById[request.id])})
if(this.scriptId){
Jast.Request.log.debug("Remove script id: "+this.scriptId+" for request id: "+this.id)
var script=$I(this.scriptId)
script.parentNode.removeChild(script)}}
Jast.Request.prototype.advanceTo=function(state){
Claim.isNumber(state,"Jast.Remove.advanceTo.state")
Claim.isTrue(0<=state&&state<=Jast.Request.COMPLETE,
"Jast.Remove.advanceTo.state")
while(this.state<state){
var nextState=this.state++
this.dispatch("on"+Jast.Request.stateNames[this.state])
this.usedBy.each(function(request){
request.advanceTo(nextState)})}}
Jast.Request.prototype.dispatch=function(event){
Claim.isString(event,"Jast.Request.dispatch.event")
Jast.Request.log.debug("Dispatch event: "+event+" for request id: "+this.id)
if(this.options[event]){
try{
this.options[event](this)}
catch(e){
Jast.Request.log.warn("Exception in "+event+" for request id: "+request.id+" exception: "+e.message);}}
Jast.Responders.dispatch(event,this)}
Jast.Request.prototype.dispatchUsed=function(event){
Claim.isString(event,"Jast.Responders.dispatchUsed.event")
Jast.Request.log.debug("DispatchUsed event: "+event+" for request id: "+this.id)
this.dispatch(event)
this.usedBy.each(function(request){
request.dispatchUsed(event)})}
Jast.Responders={}
Jast.Responders.responders=[]
Jast.Responders._each=function(iterator){
Claim.isObject(iterator,"Jast.Responders._each.iterator")
this.responders._each(iterator)}
Jast.Responders.register=function(responderToAdd){
Claim.isObject(responderToAdd,"Jast.Request.register.responderToAdd")
if(!this.include(responderToAdd))
this.responders.push(responderToAdd)}
Jast.Responders.unregister=function(responderToRemove){
Claim.isObject(responderToRemove,
"Jast.Responders.unregister.responderToRemove")
this.responders=this.responders.without(responderToRemove)}
Jast.Responders.dispatch=function(event,request){
Claim.isString(event,"Jast.Responders.dispatch.event")
Claim.isObject(request,"Jast.Responders.dispatch.request")
Claim.isNumber(request.id,"Jast.Responders.dispatch.request.id")
this.log.debug("Dispatch event "+event+" for request id: "+request.id)
this.each(function(responder){
if(responder[event]){
try{
responder[event](request)}
catch(e){
this.log.warn(" Exception in "+event+" for request id: "+request.id+" exception: "+e.message);}}})}
Jast.Responders.preLoad=function(){
Jast.Responders.log=new Log4Js.Logger("Jast.Responders")}
Object.extend(Jast.Responders,Enumerable)
PreLoad.actions.push(Jast.Responders.preLoad)
Jast.Responders.register({
onCreate:function(){
Jast.activeRequestCount++
Jast.Responders.log.debug("Active requests up to "+Jast.activeRequestCount)
Claim.isTrue(Jast.activeRequestCount>=1,
"Jast.Responders.activeRequestCount")},
onComplete:function(){
Jast.activeRequestCount--
Jast.Responders.log.debug("Active requests down to "+Jast.activeRequestCount)
Claim.isTrue(Jast.activeRequestCount>=0,
"Jast.Responders.activeRequestCount")}})
$A(PreLoad.actions).each(function(action){action()})


/******************Common.js - End *********************/
/******************UA client tools - ClientDALBuilder version:1900 - Start *********************/
//UA.Utils.js
/***************************\
Contains:
	Extension:	Claim.isFunction	- assertions for functions
	Extension:	Element.setText		- sets Value/innerHTML/textContent by element type
	Function:	Serialize(obj)		- Serializable to JSON
    Extension:  Function.insert     - insert a line into the function  
    Function:   ask()               - a debug utility
\***************************/
//-----------------------------------------------------------------
Object.extend( Class, {
  isInheritable: function(parentClassName){
    if (!parentClassName) return false;

    var parentClass;
    switch(typeof(parentClassName)){
        case "function":
            parentClass = parentClassName;
            parentClassName = parentClass.toString();
            return (  !parantClassName.match(/function\(/gi)
                   && window[parentClassName] != null
                   && window[parentClassName] == eval(parentClassName)
                   );

        case "string":
            try{
                parentClass = eval(parentClassName);
            }catch(ex){return false;} 
            return  (   parentClass != null 
                    &&  typeof(parentClass) == 'function'
                     );
        default:
            return false;
    }   
  }
  ,createSubclass: function(parentClassName){
    var parentClass;

    if(!Class.isInheritable(parentClassName))
        throw "Illegal parameter for Class.createSubclass:" + parentClassName + ". Class.create accepts a valid class-name as string, or a reference to the class if the class has a static override for the toString(), providing its class name as string.";

    if(typeof(parentClassName) == 'string'){
        parentClass = eval(parentClassName);
    }else{
        parentClass = parentClass;
        parentClassName = parentClass.toString();
    }

    Claim.isString(parentClassName,"Class.createSubclass(parentClassName)");
    Claim.check( typeof(parentClass) == 'function' &&
                 typeof(parentClass.prototype.initialize) == 'function'  
               , "typeof(eval(parentClassName).prototype.initialize) == 'function'"
               , "Class.createSubclass(parentClassName): parentClassName is not inheritable using the createSubclass mechanizm." );

    var f = new Function(parentClassName + ".prototype.initialize.apply(this, arguments);\n" 
                         + "this.initialize.apply(this, arguments)" );

    return f;
  }
});
//-----------------------------------------------------------------
Object.extend(Claim, {
	isFunction: function(object, comment)
	{{
        Claim.check(typeof(object) == 'function',
                                "isFunction(" + Claim.valueType(object) + ")",
                             comment)
	}}
});
//-----------------------------------------------------------------
Object.extend(Element, {
    log: new Log4Js.Logger("Element")
	,setText: function(e,sText){
		var tag = e.tagName.toUpperCase();
		switch(tag){
			case "INPUT":
			case "TEXTAREA":
				e.value = sText;
				break;
			case "SELECT":
				//TODO: - decide what to do if the sText doesnt match any value of the select element
				e.value = sText;
				break;
			default:/*DIV, SPAN, TD, A, H1-H5, and all the rest*/
				try{
					e.innerHTML = sText;
				}catch(ex){
					try{
						if(typeof e.innerText == 'undefined')
							e.textContent = sText;
						else
							e.innerText = sText;
					}catch(ex){
					    this.log.error("Element.setText: failed to set to element the text: " + sText);
					}
				}
		}
	}
});
//-----------------------------------------------------------------
Serialize = function(obj){
	if (!obj) return 'null';

	var str = '';
	var psik = '';
	for (each in obj){
		str += psik; psik = ","; //adds a comma from 2nd time only
		str += each +":"
		switch(typeof(obj[each])){
			case 'function': 
				break;
			case 'object':
				str += Serialize(obj[each]);
				break;
			case 'string':
			    str += '"' + obj[each].replace(/\"/,"\"") + '"';
			    break;
			default:
				str += obj[each];
		} 
	}
	return "{" + str + "}";
}
//-----------------------------------------------------------------
Function.prototype.insert = function(sCodeLine){
	var a = this.toString().split("{");
	a[1] = "\n\t" + sCodeLine + a[1];
	return (eval("a = " + a.join("{")));
}
//-----------------------------------------------------------------
Glossary =	{ _terms:	{}
			, addPair:	function addPair(key, value){ this._terms[key] = value; }
			, term:		function term(key){ return this._terms[key]; }
			};
//TODO: replace the term identifiers with term GUID
Glossary.addPair('{JAST_REQUEST_TIMEOUT_DEF_MSG}','Problems connecting to the server.');
Glossary.addPair('{JAST_REQUEST_REFUSED_DEF_MSG}','Server failes the request');
//-----------------------------------------------------------------
function ask(){
	var s = '';
	while(s!= "STOP"){
		s = prompt('To close - enter "STOP"',s);
		if (s == "STOP") return;
		alert(eval(s));
	}
}

function CreateHiddenInput(sName, sValue)
{
	var input = document.createElement("input");
	input.setAttribute("type", "hidden");
	input.setAttribute("name", sName);
	input.setAttribute("value", sValue);
	return input;
}

//This method facilitates posting data without refreshing the current window.
function PostIframeRequest(form, callback) { 
    
    var parts = window.location.hostname.split(".");
    document.domain = parts[parts.length - 2] + "." + parts[parts.length - 1];
    var remotingDiv = document.createElement("div"); 
    document.body.appendChild(remotingDiv); 
    remotingDiv.id = "remotingDiv"; 
    remotingDiv.innerHTML = "<iframe name='remotingFrame' id='remotingFrame' style='border:0;width:0;height:0;'></iframe>"; 
    remotingDiv.iframe = document.getElementById('remotingFrame'); 
    remotingDiv.form = form; 
    remotingDiv.form.setAttribute('target', 'remotingFrame'); 
    remotingDiv.form.target = 'remotingFrame'; 
    remotingDiv.appendChild(remotingDiv.form); 
    remotingDiv.callback = callback; 
    remotingDiv.form.submit(); 
}

function InvokeCallback(returnStatus){
    try
    {
        document.getElementById('remotingDiv').callback(returnStatus);
    }
    catch(ex){}
}

//=== Class UserUtils
if(!window.UA) 	UA = {};
UA.UserUtils = Class.create();
UA.UserUtils.prototype.Callback;

// UA Login and Initialization
// numOfTicks must be a positive integer
// tickInterval must be positive (milliseconds)
// paramsList must be in form of "Param1:value1,Param2:value2".
UA.UserUtils.DoLogIn = function(tickInterval, numOfTicks, callback, paramsList){
    UA.UserUtils.prototype.Callback = callback;
	UserLogIn();   //This method should be declared by each channel, and its path will be kept in the channel propeties table. 
    
    UA.UserUtils.runPolling(tickInterval, numOfTicks, paramsList);
}

UA.UserUtils.DoLogOut = function(callback){
    UserLogOut();
}

UA.UserUtils.DoRegister = function(callback){
    UserRegister();
}

UA.UserUtils.DoEndGameFlow = function(launcherObjects){
    EndGameFlow(launcherObjects);
}

UA.UserUtils.runPolling = function(tickInterval, numOfTicks, paramsList){
    var funcStringBuilder = "UA.UserUtils.polling(" + tickInterval + "," + numOfTicks;
    if(paramsList != null && paramsList != undefined)
        funcStringBuilder += ( ",'" + paramsList + "')" );
    else
        funcStringBuilder += ")";

    setTimeout(funcStringBuilder, tickInterval);
}

UA.UserUtils.polling = function( tickInterval, numOfTicks, paramsList){
    if(numOfTicks == 0)
    {
        //tell the caller that the polling ended with no success
        UA.UserUtils.prototype.Callback("User is still Logged off.");
        return;
    }

    if(!UA.User.prototype.IsLoggedOn())
    {
        numOfTicks = numOfTicks - 1;
        UA.UserUtils.runPolling(tickInterval, numOfTicks, paramsList);
        return;
    }
    //Perform InitializeUA()
    UA.UserUtils.InitializeUA(UA.UserUtils.prototype.Callback, paramsList);    
}

//paramsList ->In order to send parameters use this syntax: paramsList = "Param1:value1,Param2:value2";
UA.UserUtils.InitializeUA = function(callback, paramsList){
    var methodsArr = new Array( UA.User.Methods.ISSUBSCRIBED,
                                UA.User.Methods.GETUSER, 
                                UA.User.Methods.HASFREETRIAL,
                                UA.User.Methods.GET_OBERON_CLIENT_USERID, 
                                UA.User.Methods.GET_PARTNER_PROGRAM_ID);
    if (paramsList == undefined)
        paramsList = null;
    else
        methodsArr.push(UA.User.Methods.ISAUTHORIZED); //Harpoon new function.

    UA.UserUtils.prototype.Callback = callback;
    UA.User.prototype.GetData(methodsArr, paramsList, InitializeUASuccess, InitializeUAFail, InitializeUATimeout);
}

function InitializeUASuccess(request){
    var user = {};
    user.IsSuccessful = true;
    user.IsCompleted = true;
    
    if(request.IsAuthorized != undefined){ 
        if(request.IsAuthorized.Status != "ACCOUNT_ERROR")
            user.IsAuthorized = request.IsAuthorized.Data.isAuthorized;
        else
            user.IsCompleted = false;
    }
    
    if(request.IsSubscribed.Status != "ACCOUNT_ERROR")
        user.IsSubscribed = (request.IsSubscribed.Data.isSubscribed == "True") ? true : false;
    else
        user.IsCompleted = false;
       
    if(request.HasFreeTrial.Status != "ACCOUNT_ERROR")
        user.HasFreeTrial = (request.HasFreeTrial.Data.hasFreeTrial == "True") ? true : false;
    else
        user.IsCompleted = false;
        
    if(request.GetOberonClientUserId.Status != "ACCOUNT_ERROR")
        user.OberonClientUserId = request.GetOberonClientUserId.Data.userGuid;
    else
        user.IsCompleted = false;
        
    if(request.GetPartnerProgramId.Status != "ACCOUNT_ERROR")
        user.PartnerProgramId = request.GetPartnerProgramId.Data.ProgramId;
    else
        user.IsCompleted = false;

    if(request.GetBasicUserDetails.Status != "ACCOUNT_ERROR"){
        user.Nickname   = request.GetBasicUserDetails.Data.Nickname;
        user.AvatarURL  = request.GetBasicUserDetails.Data.AvatarURL;
        user.AvatarName = request.GetBasicUserDetails.Data.AvatarName;
    }
    else
        user.IsCompleted = false;

    UA.UserUtils.prototype.Callback(user);
}

function InitializeUAFail(request){
    var user = {};
    user.IsSuccessful = false;
    user.ErrorMessage = request.Status;
    UA.UserUtils.prototype.Callback(user);
}

function InitializeUATimeout(request){
    var user = {};
    user.IsSuccessful = false;
    user.ErrorMessage = "Timeout";
    UA.UserUtils.prototype.Callback(user);
}
//=== Class UserUtils


/**
 * Expects a number of Numbers of arguments.
 * Treats every number as a number of days since 1-1-1970
 * and returns an array with as many elements as the provided arguments
 * in which every element is a Data-Object, based on the number of days
 * from 1-1-1970 to its responsive argument
 * @param {Number} D1_D2__Dn
 * @private
 */
UA.daysToDate = function( /*d1,d2,d3...*/){

    var i,arr = [];

    for (i = 0; i < arguments.length ; i++)
        arr[i] = new Date(arguments[i] * 86400000);

    return arr;

}


//UA.Request.js
/**
 * @namespace
 * UserAccounts
 **/
if(!window.UA) 	UA = {};
//======================================================================================
/**
 * @abscract-class 
 * It is a base-class of request worker-objects.
 * The goal of this classes is to allow multiple asyncronous calls on the same 
 * caller-object-instance, and aid in making the Asyncronous work as transparent as 
 * possible, means to make the callback functions run on the caller-object-instance,
 * A.K.A - this.boss.
 *
 * Jast.Request calls the event handlers on the carrier object they are delivered on. 
 * This class decendents pass thier calls to thier "boss" - the caller-instance.
 *
 * To send the request - the caller class calls the apply method.
 **/

UA.Request = Class.create();

/*    static members	*/
//-------------------------------------------------------------
/**
 * Status OK for OK Jast requests
 **/
UA.Request.STATUS_OK = "OK";
/**
 * Status GENERAL_ERROR
 **/
UA.Request.STATUS_GENERAL_ERROR = "GENERAL_ERROR";
/*    static members	*/
//-------------------------------------------------------------
/**
 * overrides object.toString() as a static member to provide the class name
 **/
UA.Request.toString = function(){
    return "UA.Request";
}
/**
 * returns a stub instance, handy only to be a prototype instance
 **/
UA.Request.AsPrototype = function(){
    return new UA.Request({},new Function());
}
/*    Constructors  	*/
//-------------------------------------------------------------
/**
 * 
 **/
UA.Request.prototype.initialize = function( oBoss	, fSuccessCallback , fFailCallback, fTimeoutCallback){
    this.log = Object.extend({},this.log);
   	this.boss = this.log.boss = oBoss;
	/**
	 * Event handler stacks
	 **/
	this.successCallbacks = [];
	this.failiorCallbacks = [];
	this.timeoutCallbacks = [];

    Claim.isFunction(fSuccessCallback, "fSuccessCallback not provided in constructor for: " + this.toString() );
	this.successCallbacks.push(fSuccessCallback);

    if( !fFailCallback ) fFailCallback = oBoss.defaultOnFailior; 
    if( typeof(fFailCallback) == 'function') this.failiorCallbacks.push( fFailCallback );
    
    if( !fTimeoutCallback ) fTimeoutCallback = oBoss.defaultOnTimeout; 
    if( typeof(fTimeoutCallback) == 'function') this.timeoutCallbacks.push( fTimeoutCallback );
    
    this.parameters = {};
}

/*    instance members	*/
//-------------------------------------------------------------
/*
	--	@private	{[object]}	log
	--	@private	{string}	url
	--				{boolean}	isSent
	--				{[Array]}	successCallbacks
	--				{[Array]}	failiorCallbacks
	--				{[Array]}	timeoutCallbacks
*/
/**
 * @private 
 * passes log calls to the log of the "boss"
 **/
UA.Request.prototype.log =  { emit:	 function(iLevel,sText){
										if(this.boss.log && typeof(this.boss.log.emit) == 'function'){
											this.boss.log.emit(iLevel, sText);
										}else 
											this.log.error("Cannot log for caller-object: " + this.boss.toString() + ". Level: " +iLevel+ ", Message: " + sText);
									 } 
							, fatal: function(sText){ this.emit(Log4Js.FATAL, sText); }
							, error: function(sText){ this.emit(Log4Js.ERROR, sText); }
							, warn:	 function(sText){ this.emit(Log4Js.WARN , sText); }
							, info:	 function(sText){ this.emit(Log4Js.INFO , sText); }
							, debug: function(sText){ this.emit(Log4Js.DEBUG, sText); }
							, log: new Log4Js.Logger("UA.Request.log")
							, boss: null
							, toString: function(){ return "UA.Request.log"; }
							}
/**
 * @private {string}
 * The url for the Just request
 * Its expected to be initiated in the overriding "initialize(boss)" method.
 **/
UA.Request.prototype.url = "UNSET-VALUE";

/**
 * States if the current instance was sent.
 **/
UA.Request.prototype.isSent = false;



/*    private functions	*/
//-------------------------------------------------------------
/*
	--	dispatch
*/
/**
 * @private
 * sends events to the 'boss' object
 **/
UA.Request.prototype.dispatch = function request_Dispatch(retObj, arrHandlers, sEventName){
	if(arrHandlers.length == 0){
		this.log.info(sEventName + ' from ' + this.toString() + ' contained no handlers.');
		return;
	}
	this.log.info('Dispatching ' + sEventName + ' from ' + this.toString());

	var i, cb;
	for (i = 0; i <  arrHandlers.length; i++){
		cb = arrHandlers[i];
		if (cb && typeof(cb) == 'function'){
			cb.call(this.boss, retObj, this.parameters);
		}
	}
}

/*    public methods	*/
//-------------------------------------------------------------
/*
	-- toString()
	-- onSuccess(request)
	-- onFailure(request)
	-- onTimeout(request)
	-- apply()
*/
/**
 * Overrides Object.toString
 **/
UA.Request.prototype.toString = function(){
	return "[UA.Request(" + this.id + ")] of " + this.boss.toString();
}

/**
 * The Jast.Request invokes this 3 calls when its call succeeds|fails|times-out.
 * The method passes the call to Game isntance that created it.
 *
 * @param {Jast.Request} request
 *  The request object that is passed to the handler.
 **/
UA.Request.prototype.onSuccess = function(request){
	this.dispatch(request.result.Data, this.successCallbacks, "onSuccess");
}
UA.Request.prototype.onFailure = function(request){
    this.log.error("Failed on request of: " + this.boss.toString() + " to url: " + this.urlWithParams + ", Status: " + request.result.Status );
	this.dispatch(request.result, this.failiorCallbacks, "onFailure");
}
UA.Request.prototype.onTimeout = function(request){
    this.log.error("Timeout on request of: " + this.boss.toString() + " to url: " + this.urlWithParams );
	this.dispatch(request, this.timeoutCallbacks,"onTimeout");
}
/**
 * This method sends the request.
 **/
UA.Request.prototype.apply = function(){
	//single-shot mechanizm
	if (this.isSent) 
		return;
	this.isSent = true;
	
    if (Clearance.level >= Clearance.UNCLASSIFIED)
        this.parameters.cookieData = Clearance.getMagic(Clearance.UNCLASSIFIED);

	var url = Url.appendParams(this.url, this.parameters);
	//url = prompt(url,url);
	this.urlWithParams = url;
	this._JAST = new Jast.Request( url, this );
}
//UA.Game.js
//\\//=== configuration constants ===\\//\\

var EMPTY_RESULT = "EMPTY_RESULT";
window.OK = "OK";

//====== Namespace UA
if(!window.UA) UA = {};
//=== Class Game
UA.Game = Class.create();
/*    static members	*/
//-------------------------------------------------------------
/**
 * @private
 * holds references to all requests sent by this instance
 **/
UA.Game.Requests = [];

UA.Game.Methods =	{   GAMEHIGHSCORES:	    "GetGameHighScores",    //1400::"GameHighScores"
					    USERSCORE:			"GetUserScoreData",     //1400::"UserScore"
                        SESSION_CERT:       "GetSingleSessionCert",
                        GRACE_CERTS:        "GetGraceCerts",
                        GETGAMEEVERHIGHSCORES:      "GetGameEverHighScores",
                        GETGAMEWEEKLYHIGHSCORES:    "GetGameWeeklyHighScores",
                        GETGAMEHOURLYHIGHSCORES:    "GetGameHourlyHighScores" 
                    }

UA.Game.Scores = {};
UA.Game.Scores.Periods = {};
UA.Game.Scores.Periods.WEEK = "WEEK";
UA.Game.Scores.Periods.HOUR = "HOUR";
UA.Game.Scores.Periods.EVER = "EVER";

// Avatar sizes - matches Avatar.Dimentions class of Application Libraries.
UA.Game.Avatar = {};
UA.Game.Avatar.Size = {};
UA.Game.Avatar.Size.Size150x200 = "Size150x200";
UA.Game.Avatar.Size.Size65x87 = "Size65x87";
UA.Game.Avatar.Size.Size86x115 = "Size86x115";
UA.Game.Avatar.Size.Size98x131 = "Size98x131";
UA.Game.Avatar.Size.Size124x165= "Size124x165"; 
UA.Game.Avatar.Size.Size24x24 =  "Size24x24";  
UA.Game.Avatar.Size.Size48x48 = "Size48x48"; 


/*    members			*/
//-------------------------------------------------------------
UA.Game.prototype.SEND_GAME_DATA_POST_URL = "UNSET_VALUE"; 

UA.Game.prototype.isCachedResponse = false;

/*	  Constructors		*/
//-------------------------------------------------------------
UA.Game.prototype.initialize = function(p_sku){
	//Claim.isNumber(p_sku ,"UA.Game(Sku): Sku should be a number.");
	//Claim.check(p_sku > 0 && parseInt(p_sku) == p_sku, "UA.Game(Sku)", "Game Sku must be an integer, bigger then 0");

	this._prv = {	Sku: p_sku
				,	scores: {}	
				};
	this.log = new Log4Js.Logger(this.toString())
	this.log.info("UA.Game(" + p_sku + ") initiated.");
}


/*    inner class		*/

/* -- start inner class : UA.Game.GameRequest   --*/

/**
 * @class 
 * The goal of this class is to allow multiple calls on the same Game object-instance,
 * and aid in making the Asyncronous work as transparent as possible. 
 * 
 * This inner class extends the "abstract"-class UI.Request
 *
 * The GameRequest prepare the parameters stack based on the Game's Sku.
 * The Jast.Request expects handlers. Assuming that in most cases there will be nothing
 * important to say on case of time-out or of failior, the class provides almost empty 
 * default event-handler stubs. 
 * To make the calls look as if they were called on the UA.Game object, 
 * these stubs pass on the call to the Game Object - if in deed the caller-instance 
 * defined handlers for those cases. 
 **/
UA.Game.GameRequest = Class.createSubclass("UA.Request");
UA.Game.GameRequest.prototype = UA.Request.AsPrototype()
//UA.Game.GameRequest.prototype = new UA.Request();
/*	  --- Constructors		*/
/**
 *  @param {oGame} UA.Game
 *      The game-instance that uses the request 
 *
 *  @param {function(result)} fSuccessCallback
 *      Callback function for Success
 * 
 *  @param-optional {function(request)} fFailCallback
 *      Callback function for Fail
 *      If the parameter is not supplied, the oGame.defaultOnFailior is used
 *
 *  @param-optional {function(request)} fTimeoutCallback
 *      Callback function for Timeout
 *      If the parameter is not supplied, the oGame.defaultOnTimeout is used

 **/
UA.Game.GameRequest.prototype.initialize = function gameCtor( oGame	, fSuccessCallback , fFailCallback, fTimeoutCallback){
    if (oGame.isCachedResponse){
        this.url = this.boss.USER_CACHED_HANDLER_URL
    }else{
	    this.url = this.boss.PRIME_HANDLER_URL;
	}
	this.parameters = {	Sku: oGame._prv.Sku,
						Period: "",
						Mode: "" };
}

/* -- end inner class : UA.Game.GameRequest   --*/

/*	private functions	*/
//-------------------------------------------------------------


/**
 * @private
 * Sets up a GameRequest
 *
 * @param {function(result)} fSuccessCallback
 *   Callback function for Success
  * 
 * @param-optional {function(request)} fFailCallback
 *   Callback function for Fail
 *   If the parameter is not supplied, the UA.Game.defaultOnFailior is used
 *
 * @param-optional {function(request)} fTimeoutCallback
 *   Callback function for Timeout
 *   If the parameter is not supplied, the UA.Game.defaultOnTimeout is used
 *  
 */
UA.Game.prototype.getGameRequest = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.Game.GameRequest(this,fSuccessCallback, fFailCallback, fTimeoutCallback);

	r.id = UA.Game.Requests.length;
	UA.Game.Requests[ r.id ] = r;

	return r;
}

/*	public methods	*/
//-------------------------------------------------------------
/**
 * Default failure handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.Game.prototype.defaultOnFailior = null;
/**
 * Default timeout handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.Game.prototype.defaultOnTimeout = null;

/**
 * Overrides Object.toString() 
 **/
UA.Game.prototype.toString = function gameToString(){
	return "[UI.Game(" + this._prv.Sku + ")]";
}

/**
 * Gets the user high-score in the appointed game-mode.
 * Returns the score to the callback function on the UC.Game instance, with the score.
 *
 * @param {int} iMode
 *  The game mode  (examples of what mode means: arcade, journy, survival, sudden-death)
 *
 * @param {function(result)} fSuccess
 *	The callback function that is expected to be called on success with 'request.result.Data' as a 
 *  as passed argument.
 * 
 * @param {function(result)} fFailure
 *	The callback function that is expected to be called on failure with 'request.result' as the 
 *  passed argument.
 * 
 * @param {function(result)} fTimeout
 *	The callback function that is expected to be called on timeout with 'request' as the 
 *  passed argument.
 * 
 **/
UA.Game.prototype.GetUserHighScore = function(iMode, fSuccess, fFailure, fTimeout){
    //default values for optional parameters
    if(iMode == null || isNaN(iMode)) iMode = 0;

	
	//apply a request
	var r = this.getGameRequest(fSuccess, fFailure, fTimeout);
	r.parameters.Mode = iMode;
	r.parameters.MethodName = UA.Game.Methods.USERSCORE;
	r.apply();
	return r;
}

/**
 * Gets the single session certification key.
 * Returns the key to the callback function on the UA.Game instance. 
 * The method will be Invoked with the GETDATA() mechanism (see UA.User.prototype.GetData)
 **/
UA.Game.prototype.GetSingleSessionCert = function(iMode, fSuccess, fFailure, fTimeout){
	//apply a request
	var r = this.getGameRequest(fSuccess, fFailure, fTimeout);
	r.parameters.methodName = UA.User.Methods.GETDATA;
	r.parameters.MethodList = UA.Game.Methods.SESSION_CERT;
	r.apply();
	return r;
}

/**
 * Gets the single session certification key.
 * Returns the key to the callback function on the UA.Game instance. 
 * The method will be Invoked with the GETDATA() mechanism (see UA.User.prototype.GetData)
 **/
UA.Game.prototype.GetGraceCerts = function(iMode, fSuccess, fFailure, fTimeout){
	//apply a request
	var r = this.getGameRequest(fSuccess, fFailure, fTimeout);
	r.parameters.MethodName = UA.User.Methods.GETDATA;
	r.parameters.MethodList = UA.Game.Methods.GRACE_CERTS;
	r.apply();
	return r;
}

/**
 * @param {int} iMode
 *  The game mode  (examples of what mode means: arcade, journy, survival, sudden-death)
 *
 * @param {int} iAmount
 *  The top results count
 *
 * @param {} ePeriod
 *	The argument ePeriod can be one from the next values:
						UA.Game.Scores.Periods.WEEK
						UA.Game.Scores.Periods.HOUR
						UA.Game.Scores.Periods.EVER
 *
 * @param {function(result)} fSuccess
 *	The callback function that is expected to be called on success with 'request.result.Data' as a 
 *  as passed argument.
 * 
 * @param {function(result)} fFailure
 *	The callback function that is expected to be called on failure with 'request.result' as the 
 *  passed argument.
 * 
 * @param {function(result)} fTimeout
 *	The callback function that is expected to be called on timeout with 'request' as the 
 *  passed argument.
 * 
 **/

UA.Game.prototype.GetGameHighScores = function(iMode, iAmount, ePeriod, fSuccess, fFail, fTimeout, eSize){
    var r = this.getGameRequest(fSuccess, fFail, fTimeout);
    r.parameters.Mode = iMode;    
    r.parameters.TopScores = iAmount;
    r.parameters.Period = ePeriod;
    if(eSize == null || eSize == undefined) 
        delete r.parameters.Size;
    else
        r.parameters.Size = eSize;
	r.parameters.MethodName = UA.Game.Methods.GAMEHIGHSCORES;
    r.apply();
}

// Send game data with POST
UA.Game.prototype.SendGameData = function(gameData, callback){
	var formSendGameData = document.createElement("form");
	formSendGameData.setAttribute("method", "POST");
	formSendGameData.setAttribute("action", UA.Game.prototype.SEND_GAME_DATA_POST_URL);
	formSendGameData.appendChild(CreateHiddenInput("GameData", gameData));
	formSendGameData.appendChild(CreateHiddenInput("channel", UA.CHANNEL));
	PostIframeRequest(formSendGameData, callback);
}
//UA.User.js
//====== Namespace UA
if(!window.UA) 	UA = {};

//=== Class StaticUser
UA.StaticUser = Class.create();
//=== Class StaticUser

//=== Class User
UA.User = Class.create();
/*    static members	*/
//-------------------------------------------------------------
/**
 * @private
 * holds references to all requests sent by this instance
 **/
UA.User.Requests = [];
/**
 * @private
 * holds all method names that are used with the object's handler
 **/
UA.User.Methods =   { GETUSERDETAILS: "GetUserDetails"
                    , GETALLSCORES: "GetAllScores"
                    , GETUSERGAMES:	"GetUserGames"
                    , HASFREETRIAL: "HasFreeTrial"
                    , ISSUBSCRIBED: "IsSubscribed"
                    , ISAUTHORIZED: "IsAuthorized"                                  //Harpoon
                    , GETCURRENTPERMITTEDSKUS: "GetCurrentPermittedSKUs"            //Harpoon
                    , GETPLANNEDPERMITTEDSKUS: "GetPlannedPermittedSKUs"            //Harpoon
                    , GETPACKAGEEXPIRATIONUTCDATE: "GetPackageExpirationUTCDate"    //Harpoon
                    , ISNICKNAMEAVAILABLE: "IsNicknameAvailable"
                    , GETAVATARXML: "GetAvatarXml"
                    , GETWARDROBEXML: "GetWardrobeXml"
                    , ISUSERNAMEAVAILABLE: "IsUsernameAvailable"
                    , ISCAPTCHAMATCH: "IsCaptchaMatch"
                    , GETUSERTOKENS: "GetUserTokens"
                    , GETUSERLOGINDAYS: "GetUserLoginDays"
                    , GETHIGHESTMEDAL: "GetHighestMedal"
                    , GETPERSONADATABYNICKNAME : "GetPersonaDataByNickname"
                    , GETDATA : "GetData"
                    , GET_OBERON_CLIENT_USERID : "GetOberonClientUserId"
                    , GET_PARTNER_PROGRAM_ID: "GetPartnerProgramId"
                    }
/*    members			*/
//-------------------------------------------------------------
UA.User.USER_HANDLER_URL = "UNSET-VALUE";
UA.User.POST_DATA_REDIRECT_URL = "UNSET-VALUE";

UA.User.LOGGED_IN = "LoggedIn";
UA.User.ANONYMOUS = "Anonymous";
/*	  Constructors		*/
//-------------------------------------------------------------
/**
 * public constructor.
 * Sends an ISLOGGEDIN request if the user is logged in to populate user details.
 * No parameters: UserGuid is taken from cookie by Jast.Request.
 **/
UA.User.prototype.initialize = function(){
    this.log = new Log4Js.Logger("[UA.User]");
    this.params = {};
}

//function IsLoggedOn(reloadCookies): checks if the user has unclassified cookie.
//      dontReloadCookies: avoid reload cookies and rebuild Clearance or not.
// You can also invoke this method without parameters: UA.User.prototype.IsLoggedOn()
UA.User.prototype.IsLoggedOn = function(dontReloadCookies){
    if(dontReloadCookies == undefined || dontReloadCookies == false)
        Clearance.refresh();
    return Clearance.hasUnclassified();
}

//function isGuest(reloadCookies): checks if the user is authenticated as guest.
//      dontReloadCookies: reloadCookies reloading cookies and rebuild Clearance or not.
// You can also invoke this method without parameters: UA.User.prototype.isGuest()
UA.User.prototype.isGuest = function(dontReloadCookies){
    return ( !UA.User.prototype.IsLoggedOn(dontReloadCookies) || Clearance.isGuest() );
}

UA.User.prototype.LogOff = function(){ 
    Clearance.forget( Url.relativeUrl( { withClearanceParams: false, withHereParams: true } ) ); 
}

UA.User.prototype.getCookieData = function(isEscaped){ 
    var cookieData = Clearance.getMagic(Clearance.UNCLASSIFIED);
    if(isEscaped)
        cookieData = escape(cookieData);
    return cookieData;
}


/*    inner class		*/
//-------------------------------------------------------------

/* --- start inner class : UA.User.UserRequest   --*/
/**
 * @class 
 * The goal of this class is to allow multiple calls on the same User object-instance,
 * and aid in making the Asyncronous work as transparent as possible. 
 * 
 * This inner class extends the "abstract"-class UI.Request
 *
 * ...
 **/
UA.User.UserRequest = Class.createSubclass("UA.Request");
UA.User.UserRequest.prototype = UA.Request.AsPrototype()

UA.User.UserRequest.prototype.initialize = function userReqCTor(oUser, fSuccessCallback, fFailCallback, fTimeoutCallback){
	
	var curUrl = this.boss.USER_HANDLER_URL;
	if( (oUser.params.isSecured) && (curUrl.indexOf('HTTPS') == -1) && (curUrl.indexOf('https') == -1) )
        curUrl = curUrl.replace('HTTP', 'HTTPS').replace('http', 'https');
	this.url = curUrl;
	
    delete oUser.params.isSecured;
    this.boss = this.log.boss = oUser;
    this.parameters = Object.extend({}, this.boss.params);
}

UA.User.UserRequest.prototype.addParameter = function(key, val){
    this.parameters[key] = val;
}

/* --- end inner class : UA.User.UserRequest   --*/

// Diamond version of GetDetails.
// Returns comprehensive data: nickname, gender, birthday splitted to day, 
// month and year, country, region, acceptedTermsAndConditions (True/False), 
// termsAndConditionsVersion, emailOptIn (send news letters - True/False), zipCode. 
UA.User.prototype.GetUserDetails = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERDETAILS;
	r.apply();
}

/**
 * Gets the user recent games along with their details and the user achievements.
 * Returns the SKUs and optionally their top scores and the user's high score, rank and last play time.
 *  Sample of use:
 *      var u = new UA.User()
 *      u.params.maxGames = 20; //optional parameter (the default is all games)
 *      u.params.bitmask = 15;  //optional parameter (the default is all fields)
 *      u.GetUserGames(GetUserGames_onSuccess, GetUserGames_onFailer, OnTimeout);
 *
 *
 * @param {function(result)} fSuccess
 *	The callback function that is expected to be called on success with 'request.result.Data' as a 
 *  as passed argument.
 * 
 * @param {function(result)} fFailure
 *	The callback function that is expected to be called on failure with 'request.result' as the 
 *  passed argument.
 * 
 * @param {function(result)} fTimeout
 *	The callback function that is expected to be called on timeout with 'request' as the 
 *  passed argument.
 * 
 **/
UA.User.prototype.GetUserGames = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERGAMES;
	r.apply();
}

// Diamond.
// Tells whether the given nickname is available for the given community (the community is retrieved according to the channel code).
// In addition, a profanity check is being performed, for which the nickname language is needed.
// Returns true if nickname is valid and available for use. False otherwise.
UA.User.prototype.IsNicknameAvailable = function(sNickname, sLanguage, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.Nickname = sNickname;
    r.parameters.Language = sLanguage;
	r.parameters.methodName = UA.User.Methods.ISNICKNAMEAVAILABLE;
	r.apply();
}

// Gizmo.
// Tells whether the given username is available for the given authentication namespace (retrieved according to the channel code).
// Returns true if username is available for use. False otherwise.
UA.User.prototype.IsUsernameAvailable = function(sUsername, sLanguage, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.Username = sUsername;
    r.parameters.Language = sLanguage;
	r.parameters.methodName = UA.User.Methods.ISUSERNAMEAVAILABLE;
	r.apply();
}

// Gizmo.
// Tells whether the given username and random number match the given captcha text, case insensitive.
// Returns true if they match. False otherwise.
UA.User.prototype.IsCaptchaMatch = function(sUsername, sRandomNum, sCaptchaUserText, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.username = sUsername;
    r.parameters.randomNum = sRandomNum;
    r.parameters.captchaUserText = sCaptchaUserText;
	r.parameters.methodName = UA.User.Methods.ISCAPTCHAMATCH;
	r.apply();
}

// Avatar sizes - matches Avatar.Dimentions class of Application Libraries.
//UA.User.Avatar = {};
//UA.User.Avatar.Size = {};
//UA.User.Avatar.Size.Size150x200 = "Size150x200";
//UA.User.Avatar.Size.Size65x87 = "Size65x87";
//UA.User.Avatar.Size.Size86x115 = "Size86x115";
//UA.User.Avatar.Size.Size98x131 = "Size98x131";
//UA.User.Avatar.Size.Size124x165= "Size124x165"; 
//UA.User.Avatar.Size.Size24x24 =  "Size24x24";  
//UA.User.Avatar.Size.Size48x48 = "Size48x48";      

// Get The current tiny-avatar XML of a user (if the nickname parameter is supplied - of the required persona, otherwise - the authenticated user)
UA.User.prototype.GetAvatarXml = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.methodName = UA.User.Methods.GETAVATARXML;
	r.apply();
}

// Get wardrobe XML for the authenticated user
UA.User.prototype.GetWardrobeXml = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
    r.parameters.methodName = UA.User.Methods.GETWARDROBEXML;
	r.apply();
}

// Get the user's total tokens number
UA.User.prototype.GetUserTokens = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERTOKENS;
	r.apply();
}

// Get the user's login days
UA.User.prototype.GetUserLoginDays = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
    if(this.isGuest()){
        var data = {};
        data.Status = "ACCOUNT_NOT_CREATED";
        fFailCallback(data);
        return;
    }
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETUSERLOGINDAYS;
	r.apply();
}

// Get user's highest medal.
// Returns game sku and user ranking.
UA.User.prototype.GetHighestMedal = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETHIGHESTMEDAL;
	r.apply();
}

// Obsolete Method - will be remove in UA1800
UA.User.prototype.GetPersonaDataByNickname = function(nickname, avatarSize, sku, fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	if (nickname != null)
        r.parameters.Nickname = encodeURIComponent(nickname);
    r.parameters.AvatarSize = avatarSize;
    r.parameters.Sku = sku;
	r.parameters.methodName = UA.User.Methods.GETPERSONADATABYNICKNAME;
	r.apply();
}

// Returns a persona's data : Avatar-Xml, Game's data (if a nickname is not supplied, the data will be returned for the authenticated user)
//A mandatary parameter is sku.
UA.User.prototype.GetPersonaData = function(fSuccessCallback, fFailCallback, fTimeoutCallback){
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	r.parameters.methodName = UA.User.Methods.GETPERSONADATABYNICKNAME;
	r.apply();
}

/**
 * Get the captcha image URL.
 * The return captcha image will be in corelated to the username and the given (random) number.
 *
 * @param {string} username
 *	The username.
 *
 * @param {int} randomNum
 *	A random number.
 */
UA.User.prototype.GetCaptchaUrl = function(username, randomNum){
    var url;
    url = UA.User.prototype.CAPTCHA_IMAGE_URL;
    url = Url.appendParamValue(url, "username", username);
    url = Url.appendParamValue(url, "randomNum", randomNum);
    return  url; 
}

UA.User.ReportAbuse = function(abusingNickname, description, utcTime, retURL){
    var formReportAbuse = document.createElement("form");
	formReportAbuse.setAttribute("method", "POST");
	formReportAbuse.setAttribute("action", UA.User.POST_DATA_REDIRECT_URL);
	
	cookieData = Clearance.getMagic(Clearance.UNCLASSIFIED);
    formReportAbuse.appendChild(CreateHiddenInput("cookieData", cookieData));

	formReportAbuse.appendChild(CreateHiddenInput("abusingNickname", abusingNickname));	
	formReportAbuse.appendChild(CreateHiddenInput("description", description));
	formReportAbuse.appendChild(CreateHiddenInput("utcTime", utcTime));
	formReportAbuse.appendChild(CreateHiddenInput("retUrl", retURL));
	formReportAbuse.appendChild(CreateHiddenInput("failUrl", Url.here.full));

	formReportAbuse.appendChild(CreateHiddenInput("methodName", "ReportAbuse"));
    formReportAbuse.appendChild(CreateHiddenInput("channel", UA.CHANNEL));	
	
	document.body.insertBefore(formReportAbuse, null);
	formReportAbuse.submit();
}

//-------------------------------------------------------------
/**
 * Default failure handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.User.prototype.defaultOnFailior = null;
/**
 * Default timeout handler for all requests
 * Possible to be overriden in projectile code
 *
 * @type function
 **/
UA.User.prototype.defaultOnTimeout = null;

/**
 * Overrides the Object.toString()
 **/
UA.User.prototype.toString = function(){
    return "[User: " + this.Nickname + "]";
}
/**
 * Gets a UserRequest object, ready to be filled with parameters, and be applied.
 **/
UA.User.prototype.getUserRequest = function(fSuccessCallback){
	var r = new UA.User.UserRequest(this,fSuccessCallback);

	r.id = UA.User.Requests.length;
	UA.User.Requests[ r.id ] = r;

	return r;
}

//This method facilitate the invocation of one or more processing methods (handlers) as a batch
//That is the prefered way to invoke server-side processing methods
// methodsArr: an array of server-side methods (one or more) to be invoked.
// paramsList: a string of parameters for the methods in the format of "Param1:value1,Param2:value2", or null.
// OnSuccess The method return a <complex JASON> object like 
//              {"method1": {sub-jason1}, "method2": {sub-jason2}, "method3":{sub-jason3} ��,"methodN": {sub-jasonN} }  
// OnFailure The method return a JASON object like 
//  {{Status: '<Cause>' }, {Data: {<complex JASON>} } 
UA.User.prototype.GetData = function(methodsArr, paramsList, fSuccessCallback, fFailCallback, fTimeoutCallback){
	if(methodsArr.length == 0){
	    return;
	}
	var r = new UA.User.UserRequest(this, fSuccessCallback, fFailCallback, fTimeoutCallback);
	

        r.parameters.methodName = UA.User.Methods.GETDATA;	    
	    //Chaining the methods to invoke as one string
	var methodsStr = methodsArr[0];
	for(var i = 1 ; i < methodsArr.length ; i++)
	    {
	    methodsStr += ( "," + methodsArr[i] );
	    }
	    r.parameters.MethodList = methodsStr;
	
  	//Adding the parameters that needs to be sent. 
  	if(paramsList != null)
  	{
  	    var paramsArr = paramsList.split(",");
	    for(var i = 0 ; i < paramsArr.length ; i++)
	    {
	        var kNv = paramsArr[i].split(":");  //key and value
	        r.addParameter(kNv[0], kNv[1]);
	    }
	}
	r.apply();
}

/**
 * Get cached data. Search for the data in the cookie, and if not available,
 * retrives the data from the server.
 *
 * @param {function(result)} fSuccess
 *	The callback function that is expected to be called on success with 'cachedData' as 
 *  passed argument, that contains:
 *  <dl compact>
 *   <dt>gender</dt><dd>
 *    The users gender (Male / Female).
 *   </dd>
 *   <dt>birthYear</dt><dd>
 *    The year in which the user was born (YYYY).
 *   </dd>
 *   <dt>zipCode</dt><dd>
 *    Zip code (ZZZZZ).
 *   </dd>
 *  </dl>
 * 
 * @param {function(result)} fFailure
 *	The callback function that is expected to be called on failure with 'request.result' as the 
 *  passed argument (resulted from {@link User#GetUserDetails}).
 * 
 * @param {function(result)} fTimeout
 *	The callback function that is expected to be called on timeout with 'request' as the 
 *  passed argument (resulted from {@link User#GetUserDetails}).
 */
UA.User.prototype.getCachedData = function(fSuccessCallback, fFailCallback, fTimeoutCallback)
{
    UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME = 'uaCachedData';
    this.getCachedData_OnSuccess = fSuccessCallback;

    this.log.debug('getCachedData - Searching for cached data in cookie.');
    this.cachedData = Cookies.get(UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME);
    if(this.cachedData != undefined && this.cachedData != null)
    {
        this.log.debug('getCachedData - Cached data found in cookie.');
        this.getCachedData_OnSuccess(this.cachedData);
    }
    else
    {
        this.log.debug('getCachedData - No cached data in cookie. Retreiving data from server.');
        this.GetUserDetails(UA.User.prototype.getCachedData_OnSuccess, fFailCallback, fTimeoutCallback);
    }
}

/**
 * @private
 * The callback function that is expected to be called on success of {@link User#GetUserDetails}
 * that is called by {@link User#getCachedData}.
 * Created the Actually make the request for data to the server. This is done by writing a
 * script tag 'cachedData' object, set the cookie and call the success callback function
 * defined in {@link User#getCachedData}.
 *
 * @param {Object} userDetails
 *  The server-provided result (request.result.Data) returned from {@link User#GetUserDetails}.
 */
UA.User.prototype.getCachedData_OnSuccess = function(userDetails)
{
    this.cachedData = {};
    this.cachedData.gender = userDetails.gender;
    this.cachedData.birthYear = parseInt(userDetails.birthYear);
    this.cachedData.zipCode = parseInt(userDetails.zipCode);
    
    this.log.debug('getCachedData - Writing cached data in cookie.');
    Cookies.set(UA.User.prototype.getCachedData.CACHED_DATA_COOKIE_NAME, 
                this.cachedData, 
                {expires:Cookies.expiration(86400000)}); //86400000 = 24h*60m*60s*1000ms
    
    this.getCachedData_OnSuccess(this.cachedData);
}

/**
 * Set Data, send the POST data and redirecting.
 * The parameters are taken from the user params,
 * so prior to calling this methods, one should call user.params.paramName = paramValue.
 *
 * @param {string} methodName
 *	The method to be executed.
 */
UA.User.prototype.PostData = function(methodName){
	var form = document.createElement("form");
	form.setAttribute("method", "POST");
	form.setAttribute("action", UA.User.POST_DATA_REDIRECT_URL);
    form.appendChild(CreateHiddenInput("methodName", methodName));

	//Adding the parameters that should be sent. 
  	if(this.params != null)
	    for(var paramName in this.params)
	        form.appendChild(CreateHiddenInput(paramName, this.params[paramName]));

	document.body.insertBefore(form, null);
	form.submit();
}

/******************UA client tools - ClientDALBuilder version:1900 - End *********************/
/******************UA client tools configuration  - ClientDALBuilder version:1900 - Start *********************/
try{
  UA.Game.prototype.PRIME_HANDLER_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/ProcessJAccount.ashx?channel=110167437';
  UA.Game.prototype.SEND_GAME_DATA_POST_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/SendGameData.ashx';
  UA.User.POST_DATA_REDIRECT_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/PostData.ashx';
  UA.User.prototype.USER_HANDLER_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/ProcessJAccount.ashx?channel=110167437';
  UA.User.prototype.USER_LOGIN_REDIRECT_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/LoginRedirect.ashx';
  UA.User.prototype.SAVE_AVATAR_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/SetAvatar.ashx';
  UA.User.prototype.GET_AVATAR_URL = 'https://secure-proc.betaregion.omiverify.com/UserAccount/Processing/3000/APP/AvatarXML.ashx';
  UA.Game.prototype.USER_CACHED_HANDLER_URL = 'http://userassets.apizone.betaregion.oberon-media.com/UserAccount/Processing/3000/APP/ProcessJAccount.ashx?channel=110167437';
  UA.User.prototype.GET_CACHED_AVATAR_URL = 'http://userassets.apizone.betaregion.oberon-media.com/UserAccount/Processing/3000/APP/AvatarXML.ashx';
  UA.UserUtils.IFrameLoginURL = '';
  UA.CHANNEL = 110167437;
}
catch (e) {}

/******************UA client tools configuration  - ClientDALBuilder version:1900 - End *********************/
/******************Project General scrips - Start *********************/
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}  	

/* ----------------------------------------------------------------------------------------------------- */

function PreloadUserRegistrationImages()
{
	var str="";
	
	str += ' "../images/general/ifMenuRegItemBGI.gif" '
	str += ' ,"../images/general/ifMenuSelItemBGI.gif" '
		
	str = 'document.onload=MM_preloadImages(' + str + ')'
	
	eval(str);
}



/* Top Navigation Menu ------------------------------------------------------------------------------------ */

	function TopNavTabOnMouseOver(objTab)
	{
		objTab.getElementsByTagName("A")[0].className = "topNavNormalTabLinkMouseOver";
	}

	function TopNavTabOnMouseOut(objTab)
	{
		objTab.getElementsByTagName("A")[0].className = "topNavNormalTabLink";
	}

	function TopNavTabOnClick(strURL)
	{
		top.location.href = strURL;
	}
	function Partner_TopNavTabOnClick(strURL)
	{
		location.href = strURL;
	}
/* -------------------------------------------------------------------------------------------------------- */

/* Side Navigation Menu ------------------------------------------------------------------------------------ */

	function SideMenuOnMouseOver(menuItem)
	{
		//menuI/tem.getElementsByTagName("A")[0].className = "sideMenu1LinkMouseOver";
		menuItem.getElementsByTagName("TD")[3].className = "sideMenu1ItemCountMouseOver";
	}

	function SideMenuOnMouseOut(menuItem)
	{		
		//menuItem.getElementsByTagName("A")[0].className = "sideMenu1Link";
		menuItem.getElementsByTagName("TD")[3].className = "sideMenu1ItemCount";		
	}

	function SideMenuOnClick(strURL)
	{
		top.location.href = "http://" + location.host + strURL;
	}

/* -------------------------------------------------------------------------------------------------------- */

/* Inner Frame Navigation Menu ------------------------------------------------------------------------------------ */

	function IFNavMenuMouseOver(menuItem)
	{
		menuItem.className = "ifNavMenuRegItemMouseOver";
	}

	function IFNavMenuMouseOut(menuItem)
	{
		menuItem.className = "ifNavMenuRegItem";
	}

	function IFNavMenuClick(strURL)
	{
		location.href = strURL + "?" //+ location.search.substring(1);
	}

/* -------------------------------------------------------------------------------------------------------- */

/* User Portlet ------ ------------------------------------------------------------------------------------ */
	
	function ChooseChatTextColor(color, key){

		var selectedColorItemKey = document.getElementById("availableColors").selectedColorItemKey;
		if(selectedColorItemKey != null){
			if(selectedColorItemKey != key){
				document.getElementById("colorItem_" + selectedColorItemKey).className = "upColorItem";
			}
		}
		document.getElementById("colorItem_" + key).className = "upColorItemSelected";
		document.getElementById("availableColors").selectedColorItemKey = key;
		document.getElementById("chatTextColor").value = color;
	}

	function MaxMinUPChat(imgObj)
	{
		if (imgObj.src.indexOf("handle_up.gif")>=0)	
		{
			document.getElementById("upChatContainer").className = "upChatMaximized";
			imgObj.src = "images/userPortlet/handle_down.gif";
			
		}
		else	
		{
			document.getElementById("upChatContainer").className = "upChatMinimized";
			imgObj.src = "images/userPortlet/handle_up.gif";
			//objOpenCloseImg.alt = "Open";
			
		}
	}	
	
	function ShowUPInfoWindow(divID)
	{
		document.getElementById(divID).className = "upInfoWindowVisible";
	}
	
    function HideUPInfoWindow(divID)
	{
		document.getElementById(divID).className = "upInfoWindowHidden";
	}
	
	function PreloadUserPortletImages()
	{
		var str="";
		
		str += ' "../images/userPortlet/handle_down.gif" '
		str += ' ,"../images/userPortlet/handle_up.gif" '
			
		str = 'document.onload=MM_preloadImages(' + str + ')'
		
		eval(str);
	}
	/*for GameShell */
	function TopLineIconMouseOver(imgObj)
	{
		
		var ID = imgObj.id.split("_")[1];
		document.getElementById("topLineMessage_" + ID).className="showObj";
		imgObj.className="ppTopLineIcon1_r";
			
	}
	/*for GameShell */
	function TopLineIconMouseOut(imgObj)
	{
		var ID = imgObj.id.split("_")[1];
		document.getElementById("topLineMessage_" + ID).className="hideObj";
		imgObj.className="ppTopLineIcon1";
	}


   function ShowHideAutoPlay(divID,skuCode,LobbyURL)
   {
		var oGame = TC.SKUs[skuCode];
   
		
	  if (document.getElementById(divID).style.display== 'block')
	  {
		// hide Auto Play 
		HideAutoPlay(divID);
	  }
	  else
	  {
		// Show Auto Play 
		// Set LobbyURL
		var urlGameNameAddition = ""
		if (oGame != undefined && oGame != null)
			urlGameNameAddition = "&gamename="+ replaceAll(oGame.name.toLowerCase()," ","-")
		
		document.getElementById("lobby_url").href = LobbyURL + urlGameNameAddition;
		
		var oLobby = PresenceCatalog.Lobbies.All.BySku[skuCode];
		if (oLobby) /*if oLobby is undefined it means that there is no Lobby for this game, and the link will be empty*/
		{
			var iMaxLobbyPlayers = oLobby.MaxLobbyPlayers || Project.defaultMaxPlayersForLobbies;

			if( oLobby.NumberOfPlayers > iMaxLobbyPlayers)
			{
				location.href = "/FullRoom.aspx?lobby=" + Url.parse(LobbyURL).params.lobby + urlGameNameAddition;
				return;
			}
			

			// Build Play Now 
			if (Project.isMember())
			{
				// Create Autoplay for members
				// open room
				if(oLobby.MembersRoomURL=='no_room')
				{
					// When no rooms available - move to full-rooms message
					location.href = "/FullRoom.aspx?lobby=" + Url.parse(LobbyURL).params.lobby + urlGameNameAddition;
					return;
				}
				else
				{
					// open room
					document.getElementById("play_now_url").href = "Javascript:Project.openRoom('" + oLobby.MembersRoomURL + urlGameNameAddition + "',null,null,true);"
				}
			}
			else
			{
				// Create Autoplay for non members
				if(oLobby.NonMembersRoomURL=='no_room')
				{
					// When no rooms available - move to full-rooms message
					location.href = "/FullRoom.aspx?lobby=" + Url.parse(LobbyURL).params.lobby;
					return;
				}
				else
				{
					// open room
					document.getElementById("play_now_url").href = "Javascript:Project.openRoom('" + oLobby.NonMembersRoomURL.replace("refid=&","") + urlGameNameAddition + "');"
				}
			}
		}
		else
		{
		/*if oLobby is undefined it means that there is no Lobby for this game, and the link will be empty*/
			document.getElementById("play_now_url").href ="";
			document.getElementById("lobby_url").href ="";
		}
		ShowAutoPlay(divID);
		
	  }
	}
	  
/* This function will find position of the TD Element (used in Auto play)*/
	function findPos(obj) 
	{
		var curleft = curtop = 0;
		if (obj)
		{
			if (obj.offsetParent) 
			{
				curleft = obj.offsetLeft
				curtop = obj.offsetTop
				while (obj = obj.offsetParent) 
				{
					curleft += obj.offsetLeft
					curtop += obj.offsetTop
				}
			}
		}
		return [curleft,curtop];
	}

   /*
   * IFrame Resize function (Get Document Hight)
   */
    function getDocHeight(doc) 
		{
              var docHt = 0, sh, oh;
              if (doc.height) docHt = doc.height;
              else if (doc.body) 
              {
                if (doc.body.scrollHeight) docHt = sh = doc.body.scrollHeight;
                if (doc.body.offsetHeight) docHt = oh = doc.body.offsetHeight;
                if (sh && oh) docHt = Math.max(sh, oh);
              }
              return docHt;
            }
	/*
    * IFrame Resize function (Set Iframe Height)
    */
    function setIframeHeight(iframeName) 
    {
        setTimeout("", 500);
        //var iframeWin = window.frames[iframeName];
        var iframeEl = document.getElementById? document.getElementById(iframeName): document.all? document.all[iframeName]: null;
        if ( iframeEl ) 
        {
			iframeEl.style.height = "auto"; // helps resize (for some) if new doc shorter than previous  
			var docHt = getDocHeight(iframeEl.contentWindow.document);
			// need to add to height to be sure it will all show
			if (docHt) iframeEl.style.height = docHt + 0 + "px";
        }
        
    }
/* -------------------------------------------------------------------------------------------------------- */
	function ShowFeatureExplText(path,imgObj)
	{	
		var ID = imgObj.id.split("_")[1];
		document.getElementById("featureExplSpacer").className="hideObj";
		document.getElementById("featureExpl_" + ID).className="showObj";
		imgObj.src = path+"/buttons/" + ID + "_r.gif";
	}
	
	function HideFeatureExplText(path,imgObj)
	{	
		var ID = imgObj.id.split("_")[1];
		document.getElementById("featureExpl_" + ID).className="hideObj";
		document.getElementById("featureExplSpacer").className="showObj";
		imgObj.src = path+"/buttons/" + ID + ".gif";
	}
function setRefIdCookie(name,val,expiration)
{		
	var domain = location.host;	
	try {
		var strValue = val;
		var today = new Date();
		var expiry = new Date(today.getTime() + expiration * 24 * 60 * 60 * 1000); 
		if (strValue != null && strValue != "") {			
			document.cookie=name + "=" + strValue;
			//document.cookie=name + "=" + strValue + "; domain=" + domain + "; expires=" + expiry.toGMTString();
		}
	}
	catch(e){}
}


function replaceAll(text, strA, strB) 
{
    while ( text.indexOf(strA) != -1)
    {
        text = text.replace(strA,strB);
    }
    return text;
}


function getRefIdCookie(name) 
{ 
	var index = document.cookie.indexOf(name + "=");
	if (index == -1) return null;
	index = document.cookie.indexOf("=", index) + 1;
	var endstr = document.cookie.indexOf(";", index);
	if (endstr == -1) endstr = document.cookie.length;
	return unescape(document.cookie.substring(index, endstr));
}

function checkOutPageUrl(url)
{
    location.href = url + "&refid=" + getRefIdCookie("refID");
}

////////////////////////////////////////////////////////////////
///set refid cookie for omniture campaign data ////////////////
///////////////////////////////////////////////////////////////
if(getRefIdCookie("refID")== null)
{
	if(Url.here.params.refid)
		setRefIdCookie("refID",Url.here.params.refid,1);
	else if(Url.here.params.RefId)
		setRefIdCookie("refID",Url.here.params.RefId,1);
	else
		setRefIdCookie("refID","favorites",1);
	
}

// utils
function Point(x, y)
{
	this.x = parseInt(x);
	this.y = parseInt(y);
}

var Utils = new function()
{
	this.getMouseXY = function(ev)
	{
		var posx = 0;
		var posy = 0;
		
		if (!ev) 
			var ev = window.event;
		
		if (ev.pageX || ev.pageY)
		{
			posx = ev.pageX;
			posy = ev.pageY;
		}
		else
		if (ev.clientX || ev.clientY)
		{
			posx = ev.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = ev.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}
		
		return new Point(posx, posy);
	}
};

//=============================================================
// POPUP UTILS
//-------------------------------------------------------------
/**
 * opens a schreenshot popup from Game-page
 *
 * @param {number} gCode
 * The product-code of the product of the screenshot. Used to present the name of the game.
 *
 * @param {string} imgName
 * The image name of the screen-shot - used on embedded as src of IMG
 *
 * @param {number} imgWidth
 * The width of the popped up window
 *
 * @param {number} imgHeight
 * The height of the popped up window
 *
 */
function popScreenshot(gCode,imgName, imgWidth, imgHeight)
{
	window.open("screenshot.aspx?code=" + gCode + "&src="+imgName, "screenshot", "toolbar=no, status=no, resize, width=" + imgWidth + ", height=" + imgHeight + " ")
	return;
}
/**
 * opens an online-game popup
 *
 * @param {string} gameUrl
 * The url of the play-online game page with no parameters
 *
 * @param {number} gameCode
 * The product-code of the product of played game
 *
 * @param {string} origin
 * orign - indicator of the pressed link (for means tracking)
 *
 * @param {number} imgWidth
 * The width of the popped up window
 *
 * @param {number} imgHeight
 * The height of the popped up window
 *
 */
function popOnlineExt(gameUrl, gameCode, origin, width, height) {    
    window.open(gameUrl + "?code=" + gameCode, "online", "width=" + width + ", height=" + height);
    return;
}
/**
 * opens an online-game popup
 *
 * @param {number} gCode
 * The product-code of the product of played game
 *
 * @param {number} imgWidth
 * The width of the popped up window
 *
 * @param {number} imgHeight
 * The height of the popped up window
 *
 */
 function popPlayOnline(gCode, gWidth, gHeight){
	if (window != top)
		top.popPlayOnline(gCode, gWidth, gHeight);

	var oWidth, oHeight, oWindow
	oWidth = parseInt(gWidth) +80
	oHeight = parseInt(gHeight) - 250
	oWindow=window.open("/PlayOnline.aspx?code="+gCode,'null',"width=" + oWidth + ",Height=" + oHeight + ",status=no,toolbar=no,menubar=no,location=no,resizeable=yes")
	oWindow.focus()
}
/**
 * opens an online-game popup
 *
 * @param {string} gameUrl
 * The url of the play-online game page with no parameters
 *
 * @param {number} gCode
 * The product-code of the product of played game
 *
 * @param {number} imgWidth
 * The width of the popped up window
 *
 * @param {number} imgHeight
 * The height of the popped up window
 *
 */
 function popPlayOnline2(gameUrl, gCode, gWidth, gHeight){
	if (window != top)
		top.popPlayOnline2(gameUrl, gCode, gWidth, gHeight)
		
	var oWidth, oHeight, oWindow
	oWidth = parseInt(gWidth) +80
	oHeight = parseInt(gHeight) - 250
	oWindow=window.open(gameUrl + "?code=" + gCode,'null',"width=" + oWidth + ",Height=" + oHeight + ",status=no,toolbar=no,menubar=no,location=no,resizeable=yes")
	oWindow.focus()
}
//=============================================================
// IFRAME UTILS
/**
 * returns true if the provided window does not exist or closed.
 *
 * @param {object} w
 * the tested window instance
 *
 * @returns if the provided window/iframe is closed or not exists
 * @type Boolead
 */
function isWindowClosed(w){
    if(!w) return true;
    try{
        return w.closed;
    }catch(ex){
        return true;
    }
}
/**
 * sends the opener window/iframe to the provided url
 * used to manipulate the main window of a popup
 *
 * @param {string0} url
 * the URL to send the opener window to 
 *
 */
function sendOpenerToUrl(url)
{
	if( null == window.opener || isWindowClosed(window.opener) )
	{
		var iWidth = screen.availWidth - 10;
        var iHeight = screen.availHeight - 150;
        window.open(url,'_blank',"width=" + iWidth + ",Height=" + iHeight + ",top=0,left=0,status=yes,toolbar=yes,menubar=yes,location=yes,resizable=yes,scrollbars=yes,maximize=yes");
    }
    else
    {
		
		opener.location=url;
        opener.focus();
    }
}
/**
 * sends the opener of the opener window/iframe to the provided url
 * used to manipulate the main window of a 2nd generation popups
 *
 * @param {string0} url
 * the URL to send the opener window to 
 *
 */
function sendOpenerOpenerToUrl(url)
{

	if( null == window.opener || isWindowClosed(window.opener) || null == window.opener.opener || isWindowClosed(window.opener.opener) )
	{
		var iWidth = screen.availWidth - 10;
        var iHeight = screen.availHeight - 150;
        window.open(url,'_blank',"width=" + iWidth + ",Height=" + iHeight + ",top=0,left=0,status=yes,toolbar=yes,menubar=yes,location=yes,resizable=yes,scrollbars=yes,maximize=yes");
    }
    else
    {
		
		opener.opener.location=url;
        opener.opener.focus();
    }
    return undefined;
}

//=============================================================
// MISC UTILS
//-------------------------------------------------------------

/**
 * If the game of the provided sku is installed - it invokes its launcher using the Oddesy active-X
 *
 * @param {numner} sku
 * the SKU of the game to launch
 */
function runApp(sku)
{
	objActiveX = document.getElementById('objActiveX');
    if(ODCinstalled==1) {
        objActiveX.launchGame(sku);
        self.location.reload()
    }
    return
}
/**
 * Calls the code provided as string untill it passes with no errors.
 * If error occured - sets a timeout to call it again.
 * Usefull to make sure that a code line that depends on DOM elements will gets executed by the nearest interval that its DOM is available.
 *
 * @param {string} sCode
 * The dangerous code line to call
 */
function safeCall(sCode,iTimeout)
{
    if ( !iTimeout ) iTimeout = 250;
    try
    {
        (new Function(sCode))();
        return true;
    }
    catch(ex)
    {
        setTimeout("safeCall(\"" + sCode.replace(/\"/g,"\\\"") + "\"," + iTimeout + ");", iTimeout);
    }
    return false;
}
//=============================================================
// COOKIES UTILS
//-------------------------------------------------------------
/**
 * returns the cookie by the provided name
 *
 * @param {string} name
 * The name of the sought cookie
 *
 * @returns the cookie by the provided name
 * @type string
 */
function getCookie(name) 
{ 
	var index = document.cookie.indexOf(name + "=");
	if (index == -1) return null;
	index = document.cookie.indexOf("=", index) + 1;
	var endstr = document.cookie.indexOf(";", index);
	if (endstr == -1) endstr = document.cookie.length;
	return unescape(document.cookie.substring(index, endstr));
}

/**
* @param {string} name 
* the name of cookie
*
* @param {string} value 
* the value of the cookie
*
* @param {number(optional)} expiration 
* the expiration period of the cookie (in days)
*
* @param {string(optional)} domain
* the domain to write the cookie in
*/
function setCookie(name, value, expiration, domain) 
{ 
	if(domain == null)
		domain = location.host;	
	
	try {
		var strValue = asCookieValue(value);
		var today = new Date();
		var expiry = new Date(today.getTime() + expiration * 24 * 60 * 60 * 1000); 
		if (strValue != null && strValue != "") {
			document.cookie=name + "=" + strValue + "; domain=" + domain+ "; expires=" + expiry.toGMTString();
		}
	}
	catch(e){}
}
/**
 * returns the supplied value, encoded as cookie value
 * 
 * @param {string} value
 * the value to be encoded
 * 
 * @returns the supplied value, encoded as cookie value
 * @type string
 */
function asCookieValue(value){
	var strValue = new String();
	strValue = value.toString();
	//replace all chars with URL encoding
	while (strValue.indexOf(" ") != -1) {
		strValue = strValue.replace(" ","%20");
	}
	strValue = strValue.replace(/\:/g,"%3A");
	strValue = strValue.replace(/\+/g,"%2B");
	strValue = strValue.replace(/\-/g,"%2D");
	return strValue;
}

/******************Project General scrips - End *********************/
/******************Game Catalog - GameCatalog.js  - Start *********************/
//TODO: add claims and Log4Js.Loggers
//---------------------------------------------------------------------------------
/**
 * Enhance system class: Function
 *  - is done here untill it will enter the infra client-tools.
 */
Function.prototype.getArgNamesArray = function(){
	try{
		return /function[^\(]*\(([^\)]*)\)/.exec(this.toString())[1].replace(/\s*/g,"").split(",");
	}catch(ex){
		return [];
	}
}
//---------------------------------------------------------------------------------

//---------------------------------------------------------------------------------
/**
 * Enhance system class: Array
 *  - is done here untill it will enter the infra client-tools.
 */

/**
 * @param {number} iStart
 * @param {number} iCount
 *
 * @type Array
 */
Array.prototype.cut = function(iStart, iCount)
{
	var iEnd = undefined;
	if(iStart==undefined) iStart = 0;
	iEnd = (iCount==undefined)? this.length : iStart + iCount;
	return this.slice(iStart, iEnd);
}
/**
 * @param {number} iPage
 * @param {number} iItemsInPage
 *
 * @type Array
 */
Array.prototype.page = function(iPage, iItemsInPage)
{
	return this.cut( iPage * iItemsInPage, iItemsInPage );
}
//---------------------------------------------------------------------------------

//=================================================================================

/**
 * @namespace GameCatalog
 *
 * Classes:
 * @see GameCatalog.Game
 * @see GameCatalog.Tag
 * 
 * API:
 * @see: GameCatalog.addGame
 * @see: GameCatalog.addTag
 * @see: GameCatalog.TagSkuLinks
 * @see: GameCatalog.SkuTagLinks
 */
if(window.GameCatalog == null) 
	GameCatalog = {};
	
	// Constants
GameCatalog.PRODUCT_CODE_VARNAME = "code";
GameCatalog.LANGUAGE_VARNAME = "lc";
GameCatalog.CHANNEL_VARNAME = "channel";
GameCatalog.BILLING_CNTRY_VARNAME = "BillingCountry";
GameCatalog.LOBBY_VARNAME = "lobby";

// Prperties
GameCatalog.language = "";
GameCatalog.channelCode = -1;
GameCatalog.baseBuyURL = "";
GameCatalog.baseGamePageURL = "";
GameCatalog.baseLobbyURL = "";
GameCatalog.billingCountry = "";


GameCatalog.millisPerDay = 24 * 60 * 60 * 1000;

//--- Class: GameCatalog.TagSkuLinks ---------------------------
//TBD: replace with Class.createArrayDecendent();
//	   currently, the Class.create() mechanizm does not allow inheritance from 
//	   system objects. It has to be done manually, by defining 
//	   constructor functions directly.
//		TBD is untill infra will overcome this
/**
 * @class GameCatalog.TagSkuLinks
 */
GameCatalog.TagSkuLinks = function()
{
	this.initialize();

	var e,a = new Array()
	for (e in this) a[e] = this[e];
	for (e = 0; e < arguments.length; e++)	a[e] = arguments[e];

	return a;
}
/**
 * @constructor
 */
GameCatalog.TagSkuLinks.prototype.initialize = function()
{
	this.dictionary = {}
}
/**
 * @param {number} iStart
 * @param {number} iCount
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.TagSkuLinks.prototype.byWeight = function(iStart, iCount, isForceSort)
{ 
	if(!this._byWeight || isForceSort)
	{
		this._byWeight = this.concat().sort(	
											function(a,b)
											{
												return b.weight - a.weight;
											}
										  );
	}
	return this._byWeight.cut(iStart, iCount);
}
/**
 * @param {string} sSkuProp
 * @param {boolean(optional)} isDescSort
 * @param {number(optional)} iStart
 * @param {number(optional)} iCount
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.TagSkuLinks.prototype.bySkuProperty = function(sSkuProp, isDescSort, iStart, iCount, isForceSort)
{
	if(!this["_sku_" + sSkuProp] || isForceSort){
	    var orderVar = -1;
	    if(isDescSort)
	        orderVar = 1;
		this["_sku_" + sSkuProp] = this.concat().sort(
										function(a,b){
											if (b.sku[sSkuProp] == a.sku[sSkuProp]) return 0;
											return (b.sku[sSkuProp] > a.sku[sSkuProp]) ? orderVar : ( orderVar*(-1) ) ;
										}
									 );
	}
	return this["_sku_" + sSkuProp].cut(iStart, iCount);
}
//--- End Class: GameCatalog.TagSkuLinks ---------------------------

//--- Class: GameCatalog.SkuTagLinks -------------------------------
//TBD: replace with Class.createArrayDecendent();
//	   currently, the Class.create() mechanizm does not allow inheritance from 
//	   system objects. It has to be done manually, by defining 
//	   constructor functions directly.
//		TBD is untill infra will overcome this
GameCatalog.SkuTagLinks = function()
{
	this.initialize();

	var e,a = new Array()
	for (e in this)a[e] = this[e];
	for (e = 0; e < arguments.length; e++)	a[e] = arguments[e];

	return a;
}
/**
 * @constructor
 */
GameCatalog.SkuTagLinks.prototype.initialize = GameCatalog.TagSkuLinks.prototype.initialize;
/**
 * @param {number} iStart
 * @param {number} iCount
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.SkuTagLinks.prototype.byWeight = GameCatalog.TagSkuLinks.prototype.byWeight;
/**
 * @param {string} sTagProp
 * @param {boolean(optional)} isDescSort
 * @param {number(optional)} iStart
 * @param {number(optional)} iCount
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.SkuTagLinks.prototype.byTagProperty = function(sTagProp, isDescSort, iStart, iCount, isForceSort)
{
	if(!this["_tag_" + sTagProp] || isForceSort){
	    //if(typeof(sTagProp) == 'object') arguments = arguments[0];
		var orderVar = -1;
	    if(isDescSort)
	        orderVar = 1;
		var arr = this.concat().sort(
										function(a,b){
											if (b.tag[sTagProp] == a.tag[sTagProp]) return 0;
											return (b.tag[sTagProp] > a.tag[sTagProp])? orderVar : ( orderVar*(-1) ) ;
										}
									 );
		this["_tag_" + sTagProp] = arr;
	}
	return this["_tag_" + sTagProp].cut(iStart, iCount);
}
//--- End Class: GameCatalog.SkuTagLinks ---------------------------



//---- Class: GameCatalog.Category ---------------------------------
/**
 * @class GameCatelog.Category
 */
GameCatalog.Category = Class.create();
/**
 * @constructor
 */
GameCatalog.Category.prototype.initialize = function(code,name,internalName,categoryURL)
{
	var params = this.initialize.getArgNamesArray();
	for(var i=0; i < params.length; i++)
		if(arguments[i] !== undefined) this[params[i]] = arguments[i];
	
	this.games = {};
	this.games.All = [];
	this.games.All.bySkuProperty = GameCatalog.Game.All.bySkuProperty
}
GameCatalog.Category.All = [];
GameCatalog.Category.All.byCategoryProperty = function(sPropName,iStart, iCount, isForceSort){
	if(!this[0] || undefined === this[0][sPropName] ) 
		return this;

	if(!this["_" + sPropName] || isForceSort )
	{
		this["_" + sPropName] = this.concat().sort(
													function(a,b)
													{
														if (a[sPropName] == b[sPropName]) return 0;
														return (a[sPropName] < b[sPropName])?-1:1;
													}
												  );
	}

	return this["_" + sPropName].cut(iStart, iCount);
}
GameCatalog.Category.ByCode = {};
//---- End Class: GameCatalog.Category ---------------------------

//---- Class: GameCatalog.Game -----------------------------------
/**
 * @class GameCatalog.Game
 */
GameCatalog.Game = Class.create();
/**
 * @static
 * All Games array
 * @type Array
 */
GameCatalog.Game.All = [];

/**
 * @param {string} sPropName
 * @param {number} iStart
 * @param {number} iCount
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.Game.All.bySkuProperty = GameCatalog.Category.All.byCategoryProperty;
/**
 * @static
 * All Games dictionary by Sky
 * @type Object
 */
GameCatalog.Game.All.dictionary = {};
GameCatalog.Game.All.BySku = GameCatalog.Game.All.dictionary;
/**
 * @contstructor
 *
 * @param {number} sku
 * @param {string} name
 * @param {string} gamePageURL
 * @param {string} smallThumbnail
 * @param {string} categoryLocalizedName
 * @param {string} categoryCode
 * @param {boolean} isNew
 * @param {Date} publishDate
 * @param {string} lobbyURL
 */
GameCatalog.Game.prototype.initialize = function(sku, name, smallThumbnail, categoryCode, productCode, lobbyUID, isMultiPlayer, thumbnail16x16,  isNew, publishDate, thumbnail100x75, thumbnail179x135, thumbnail320x240, isLocalized, thumbnail130x75, downloadURL, oneThirdDesc, twoThirdsDesc, isOnline, isSupportingTokens, isEventSupporting, reportName )
{
	//support single array as a single parameter, or argument-list
	if(typeof(arguments[0]) == 'object') arguments = arguments[0];

	//init all data-properties declared in constructor
	var params = this.initialize.getArgNamesArray();
	for(var i=0; i < params.length; i++)
		if(arguments[i] !== undefined ) this[params[i]] = arguments[i];
	this['publishDate'] = new Date(this['publishDate'] * GameCatalog.millisPerDay); //'daysSince70'
	
	this['gamePageURL']=GameCatalog.Game.generateGamePageURL(this['productCode']);
	this['buyURL']=GameCatalog.Game.generateBuyURL(this['productCode']);
	this['lobbyURL']=GameCatalog.Game.generateLobbyURL(this['lobbyUID'], this['productCode']);
	this['categoryLocalizedName'] = GameCatalog.Category.ByCode[categoryCode].name
	
	
	
	//init tags collection
	this.tagLinks = new GameCatalog.SkuTagLinks();
}

/**
 * provides an array of most recent new games, sorted by the publish date in a descending order
 *
 * @param {number} count
 *
 * @type Array
 */
GameCatalog.Game.prototype.getRecentGames = function(count){
    var isNew = "isNew", pDate = "publishDate";
    var a = GameCatalog.Game.All.bySkuProperty(isNew).concat();
    var arr = [];
    for (var i = a.length-1; i >= 0; i--) {
        if(a[i].isNew == false)
            break;
        arr.push(a[i]);
    }
    arr = arr.sort  (   function(a,b)
						{
						    if (a[pDate] == b[pDate]) return 0;
							    return (a[pDate] > b[pDate])?-1:1;
						}
				    );
    return arr.cut(0, count);
}


/**
 * creates a link, adds it to the tags object, and returns it.
 */
GameCatalog.Game.addTag = function(oTag, dblWeight){
	if(this.tagLinks.dictionary[ oTag.internalName ])
		return this.tagLinks.dictionary[ oTag.internalName ];

	return this.addTagLink(	{ weight	: dblWeight
							, tag		: oTag 
							, sku		: this
							} 
						   );
}
/**
 * adds a tag to the tags object and returns it.
 */
GameCatalog.Game.prototype.addTagLink = function(oLink){
	if( !this.tagLinks.dictionary[ oLink.tag.internalName ] )
		this.tagLinks[ this.tagLinks.length ] =	
			this.tagLinks.dictionary[ oLink.tag.internalName ] = 
				oLink;

	if(!oLink.tag.skuLinks.dictionary[this.sku])
		oLink.tag.addSkuLink( oLink );

	return oLink;
}
//---- End Class: GameCatalog.Game  -----------------------------------



//---- Class: GameCatalog.Tag  ----------------------------------------
/**
 * @class GameCatalog.Tag
 */
GameCatalog.Tag = Class.create();

GameCatalog.Tag.keyProperty = "internalName";  //The key in the tags dictionary.
GameCatalog.Tag.propertyList = "name, count";  //default properties. May change with the server response.

/**
 * @constructor
 *
 * @param {string} internalName
 * @param {string} name
 * @param {number} count
 * @param {boolean} isFullyLoaded
 * @param {Date} publishDate
 */
GameCatalog.Tag.prototype.initialize = function(/*internalName, name, count, isFullyLoaded, publishDate*/)
{
	//support single array as a single parameter, or argument-list
	if(typeof(arguments[0]) == 'object') args = arguments[0];
	
	//init the 1st property (dictionary key)
	this[GameCatalog.Tag.keyProperty] = args[0];

	//init all data-properties declared in propertyList
	var prop = GameCatalog.Tag.propertyList.replace(/\s*/g,"").split(","); //this.initialize.getArgNamesArray();
	
	this.tagPageURL = GameCatalog.URLs.tagPageURL.replace(/TAG_INTERNAL_NAME/g, args[0]);
	
	for(var i=0 ; i < prop.length; i++)
		if(args[i+1] !== undefined)
		{
		    var val = args[i+1];
		    if(prop[i].indexOf('Date') != -1)    //'daysSince70'
		        val = new Date(val * GameCatalog.millisPerDay)
		    this[prop[i]] = val;
		}

	this.skuLinks = new GameCatalog.TagSkuLinks();
}
/**
 * adds the link to the skus array and dictionary collection.
 * the method keeps the array always sorted by weight
 */
GameCatalog.Tag.prototype.addSkuLink = function(oLink)
{
	if( !this.skuLinks.dictionary[ oLink.sku.sku ] )
		this.skuLinks.dictionary[ oLink.sku.sku ] = 
			this.skuLinks[	this.skuLinks.length ] = oLink;

	if(!oLink.sku.tagLinks.dictionary[this.internalName])
		oLink.sku.addTagLink( oLink );
}
/**
 * create a link between the tag and the sku by weight, 
 * and pefroms the linking using this.addSkuLink
 */
GameCatalog.Tag.prototype.addSku = function(sku, dblWeight){
	if(typeof(sku) == 'number') sku = GameCatalog.Game.All.dictionary[sku];
	if (!sku) return; //TODO: add Log4Js logging

	this.addSkuLink(	{	weight	:	dblWeight
						,	sku		:	sku
						,	tag		:	this
						}
					);
}
/**
 * adds skus with unlimited parameters array, 
 * while every 2 parameters is a sku and its link-weight.
 * @param {arguments} sku,weight pairs
 */
GameCatalog.Tag.prototype.addSkus = function(/*sku1,weight1, sku2,weight2, sku3,weight3, ... */)
{
	var i = 0;
	while( i < arguments.length){
		this.addSku(arguments[i++], arguments[i++]);
	}
}
/**
 * returns true when the Tag is loaded with all of its children
 * based on the children-count provided by the server, and the 
 * count of the initiated linkes on the client
 *
 * @type boolean
 */
GameCatalog.Tag.prototype.isFullyLoaded = function()
{
	return this.count == this.skuLinks.length;
}
/**
 * All Tags Array
 * @type Array
 */
GameCatalog.Tag.All = [];

/**
 * provides an array of all the tags on the client, sorted by the provided tag-property.
 *
 * @param {string} sProp
 * @param {boolean(optional)} isDescSort
 * @param {iStart(optional)} number
 * @param {iEnd(optional)} number
 * @param {boolean(optional)} isForceSort
 *
 * @type Array
 */
GameCatalog.Tag.All.byTagProperty = function(sProp, isDescSort, iStart, iCount, isForceSort)
{ 
	if(!this["_by_" + sProp] || isForceSort)
	{
	    var orderVar = -1;
	    if(isDescSort)
	        orderVar = 1;
		this["_by_" + sProp] = this.concat().sort(	
													function(a,b)
													{
														if((b[sProp] == a[sProp])) return 0;
														return (b[sProp] > a[sProp]) ? orderVar : ( orderVar*(-1) ) ;
													}
												  );
	}
	return this["_by_" + sProp].cut( iStart, iCount );
}
/**
 * All Tags collection by name
 * @type Object
 */
GameCatalog.Tag.All.dictionary = {}

//--- End Class: GameCatalog.Tag  -----------------------------------






GameCatalog.URLs =	{ gamePageURL: '/Deluxe.aspx?code=GAME_SKU&lc=en&channel=110167437'
					, gameImageBase: '/images/games/'
					, buyURL: 'http://Jeuxentelechargement-beta.jeu.orange.fr/Checkout.asp?code=CHECKOUT_SKU&channel=110167437&lc=fr&BillingCountry=FR'
					, lobbyURL: '/Lobby.aspx?lobby=LOBBY_ID&channel=110167437&lc=en'
					, categoryURL: '/Category.aspx?code=CATEGORY_CODE'
					, tagPageURL : '/Tag.aspx?tag=TAG_INTERNAL_NAME&ln=en'
					};

/**
 * @param {numbner} code
 * @param {string} name
 * @param {string} internalName
 *
 * @type GameCatalog.Category
 */
GameCatalog.addCategory = function(code,name,internalName)
{
	var categoryURL = GameCatalog.URLs.categoryURL.replace(/CATEGORY_CODE/g, code);
	var category = new GameCatalog.Category( code, name, internalName, categoryURL);
	
	GameCatalog.Category.ByCode[ code ] = 
		GameCatalog.Category.All[ GameCatalog.Category.All.length ] = 
			category;
	return category;
}
GameCatalog.addGame = function(sku, name, smallThumbnail, categoryCode, productCode, lobbyUID, isMultiPlayer, thumbnail16x16, isNew, publishDate, thumbnail100x75, thumbnail179x135, thumbnail320x240, isLocalized, thumbnail130x75,  downloadURL, oneThirdDesc, twoThirdsDesc, isOnline, isSupportingTokens, isEventSupporting, reportName )

{
	var newGame = new GameCatalog.Game(sku, name, smallThumbnail, categoryCode, productCode, lobbyUID, isMultiPlayer, thumbnail16x16, isNew, publishDate, thumbnail100x75, thumbnail179x135, thumbnail320x240, isLocalized, thumbnail130x75,  downloadURL, oneThirdDesc, twoThirdsDesc, isOnline, isSupportingTokens, isEventSupporting, reportName )
	
    GameCatalog.Game.All[GameCatalog.Game.All.length] = newGame;
	GameCatalog.Game.All.BySku[newGame.sku] = newGame;
    
    return newGame;
}

/**
 * @param {string} internalName
 * @param {string} same
 * @param {string} images
 * @param {string} shortDesc
 * @param {string} desc
 *
 * @type GameCatalog.Tag
 */
GameCatalog.addTag = function(/*internalName,...*/){
    
	var tag = this.Tag.All.dictionary[arguments[0]];
	if (  tag )  return tag;

	var newTag = new this.Tag(arguments/*internalName,... */);
    

	this.Tag.All[this.Tag.All.length] = newTag;
	this.Tag.All.dictionary[arguments[0]] = newTag; //arguments[0] is the key in the dictionary (tag's internalName)

	return newTag;
	
}
// Supposedly a static function which generates the GamePage URL
// params:  
//          --productCode : The product code
GameCatalog.Game.generateGamePageURL = function(productCode)
{
    var gamePageURLBuilder = new Array();
    gamePageURLBuilder = gamePageURLBuilder.concat(GameCatalog.baseGamePageURL, "?", 
    GameCatalog.PRODUCT_CODE_VARNAME, "=", productCode, "&", 
    GameCatalog.LANGUAGE_VARNAME, "=", GameCatalog.language, "&", 
    GameCatalog.CHANNEL_VARNAME, "=", GameCatalog.channelCode);
    
    return gamePageURLBuilder.join("");
}

// Supposedly a static function which generates the Checkout Page URL
// params:  
//          --productCode   : The product code
GameCatalog.Game.generateBuyURL = function(productCode)
{
    var buyURLBuilder = new Array();
    buyURLBuilder = buyURLBuilder.concat(GameCatalog.baseBuyURL, "?", 
            GameCatalog.PRODUCT_CODE_VARNAME, "=", productCode, "&", 
            GameCatalog.CHANNEL_VARNAME, "=", GameCatalog.channelCode, "&", 
            GameCatalog.LANGUAGE_VARNAME, "=", GameCatalog.language, "&", 
            GameCatalog.BILLING_CNTRY_VARNAME, "=", GameCatalog.billingCountry);
            
    return buyURLBuilder.join("");
}

// Supposedly a static function which generates the lobby URL
// params:  
//          --lobbyUID    : The product code
GameCatalog.Game.generateLobbyURL = function(lobbyUID, productCode)
{
    if (lobbyUID != "")
    {
        var lobbyURLBuilder = new Array();
        lobbyURLBuilder = lobbyURLBuilder.concat(GameCatalog.baseLobbyURL, "?", 
                GameCatalog.LOBBY_VARNAME, "=", lobbyUID, "&", 
                GameCatalog.PRODUCT_CODE_VARNAME, "=", productCode, "&",
                GameCatalog.CHANNEL_VARNAME, "=", GameCatalog.channelCode, "&", 
                GameCatalog.LANGUAGE_VARNAME, "=", GameCatalog.language);
            
        return lobbyURLBuilder.join("");
    }
    
    return "";
}
/******************Game Catalog - GameCatalog.js  - End *********************/
/******************community scripts Flash.js version:1900.0 - Start *********************/
Flash = Class.create();


/**
 * a list of all settings that are not coppied directly from the 
 * settings object to the rendered output, 
 * either because they are syntax related, or because they are for 
 * internal use
 */
Flash.nonAttributeSettings = ['targetElement', 'log', 'id'
							 ,'classid','codebase','type','pluginspage', 'src'
							 ];
/**
 * a list of all settings that must be presented as <param> in <object> syntax
 * @type Array
 */
Flash.objectParams = ['bgcolor','quality','wmode','base','menu'
                     ,'scale','swremote','loop','salign'
                     ,'devicefont','embedmovie','seemlesstabbing'
                     ,'allowFullScreen'
					 ,'flashvars','allowscriptaccess'];

/**
 * default settings 
 * @type Object
 */
Flash.defaultSettings = 
	{	classid		: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
	,	codebase	: "http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"
	,	type		: "application/x-shockwave-flash"
	,	pluginspage	: "http://www.macromedia.com/go/getflashplayer"
	}

/**
 * @param {String} sSwfUrl 
 *  The Url to the presented swf file
 * @param {Object(optional)} oSettings 
 *	Supports the folowing settings<ol>
 *  <li>height
 *  <li>width
 *  <li>menu
 *  <li>wmode
 *  <li>quality
 *  <li>allowScriptAccess
 *  <li>wmode
 *  <li>base 
 *  </ol>
 * @param {String(optional)} sNoSettingsAttributes
 * This optional parameter allows the oSettings parameter to be provided 
 * with properties that should not be copied as flash settings. <br>
 * The usage is when the passed object is used as a setting object for other uses,
 * and contain attributes that must not be coppied to the flash object
 */
Flash.prototype.initialize = function(sSwfUrl, oSettings, sNoSettingsAttributes)
{
	/**
	 * The displayed movie
	 * @type String
	 */
	this.swfUrl = sSwfUrl;
	/**
	 * the settings object
	 * @type Object
	 */
	this.settings = Object.extend({}, this.constructor.defaultSettings);
	sNoSettingsAttributes = "," + sNoSettingsAttributes + ",";
	var each;
	for(each in oSettings)
		if (sNoSettingsAttributes.indexOf("," + each + ",") == -1)
			this.settings[each] = oSettings[each];

	/**
	 * The logger
	 * @type Log4Js.Logger
	 */
	this.log = this.settings.log || new Log4Js.Logger(this.settings.id || this.settings.targetElement &&  this.settings.targetElement != document || this.swfUrl || "Blank Flash instance")
	delete this.settings.log;

	/**
	 * the target DOM Container (or its ID as a string)
	 * @type DOMContainer|String
	 */
	this.targetElement = this.settings.targetElement;
	delete this.settings.targetElement;

	/**
	 * Holds the syntax to use ( object | embed ), based on the detected browser type
	 * <code>object</code> syntax is used on IE based browsers, on Windows only, except Opera.<br>
	 * The var is initiated in {@link Flash#render} method.
	 * @type String
	 */
	this.useSyntax = null;

	/**
	 * The HTML prepared and returned by {@link Flash#render}
	 * @type String
	 */
	 this.HTML = null;

	/**
	 * Holds all the key-values of all attributes for the tag.
	 * key-value pairs are collected by the used syntax (object or embed)
	 * @type prototype:Hash
	 */
	this.attributes = $H();

	/**
	 * Holds all the key-values of all params for the tag
	 * key-value pairs are collected by the used syntax
	 * @type prototype:Hash
	 */
	this.params = $H();

	//if the targetElement and the swf are provided - perform the render 
	if (this.targetElement && this.swfUrl) 
	{
		this.render(this.targetElement);
	}

}
/**
 * returns the syntax for the run-time environment.
 * <code>object</code> syntax is used on IE based browsers, on Windows only, except Opera.<br>
 * @type String
 * @returns 'object' or 'embed', depening on the run-time environment
 * @overridable
 */
Flash.prototype.getTagSyntax = function()
{
	var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
	var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
	var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;

	return (isIE && isWin && !isOpera)? 'object': 'embed';
}

/**
 * copy all supported attributes that are populated in settings to attributes
 * @private
 */
Flash.prototype.prv_prepareAttributes = function()
{
	var attribute; 
	for(attribute in this.settings)
	{
		if(Flash.nonAttributeSettings.indexOf(attribute) != -1) continue;
		this.attributes[attribute] = this.settings[attribute];
	}
}

/**
 * move attributes to param for '<object>' syntax
 * @private
 */
Flash.prototype.prv_moveAttributesToParams = function()
{

	var attribute;
	for (attribute in this.attributes)
	{
		if (typeof(this.attributes[attribute]) == 'function' ) continue;
		if( Flash.objectParams.indexOf( attribute.toLowerCase() ) != -1)
		{
			this.params[attribute] = this.attributes[attribute];
			delete this.attributes[attribute];
		}
	}
}

/**
 * emmits into the provided <codE>out</code> array the output of the 
 * attributes prepared at this.attributes according the prepared syntax
 * @private
 */
Flash.prototype.prv_renderAttributes = function(out)
{
	this.attributes.each(
		function(kv,i)
		{
			out[out.length] = ' ';
			out[out.length] = kv[0];
			out[out.length] = '="';
			out[out.length] = kv[1];
//			out[out.length] = escape(kv[1]);
			out[out.length] = '"';
		}
	);
	out[out.length] = ">\n";
}
/**
 *
 */
Flash.prototype.prv_renderParams = function(out)
{
	if(this.useSyntax != 'object') return;
	this.params.movie = this.swfUrl;
	this.params.each(
		function(kv,i)
		{
			out[out.length] = '<param name="';
			out[out.length] = kv[0];
			out[out.length] = '" value="';
			out[out.length] = kv[1];
			//out[out.length] = escape(kv[1]);
			out[out.length] = '"/>\n';
		}
	);
}
/**
 * bag of method references used to open the tag, according to the required syntax
 * on the constructor, the bag is overriden by the reference of the method that implements the required syntax.
 * @private
 */
Flash.prototype.prv_renderOpenTag = 
{	object: function(out)
			{
				out[out.length] = '<object classid="';
				out[out.length] = this.settings.classid;
				out[out.length] = '"\n\t codebase="'; 
				out[out.length] = this.settings.codebase;
				out[out.length] = '"\n\t id="'; 
				out[out.length] = this.objectID;
				out[out.length] = '"\n\t';
			}
,	embed : function(out)
			{
				out[0] = out[1] = out[2] = "";
				out.push('<embed type="');
				out.push(this.settings.type);
				out.push('" pluginspage="');
				out.push(this.settings.pluginspage);
				out.push('" name="');
				out.push(this.objectID);
 				out.push('" src="');
				out.push(this.swfUrl);
				out.push('"');
			}
}

/**
 * bag of method references used to close the tag, according to the required syntax
 * on the constructor, the bag is overriden by the reference of the method that implements the required syntax.
 * @private
 */
Flash.prototype.prv_renderCloseTag = 
{	object: function(out)
			{
				out[out.length] = "</object>";
			}

,	embed : function(out)
			{
				out.push("</embed>");
			}
}


/**
 * returns the HTML for the flash-tag in the syntax relevant for the run-time environment 
 * if target element is provided - renders the HTML into it.<br>
 * <code>targetElement</codE> can be provided as an argument, or as entry on <code>settings</code> arguments to the constructor.
 * The returned HTML is also kept on {@link Flash#HTML}.
 *
 * @param {String} targetElement
 * the ID of the DOM Container to render the Flash tag into.<br>
 * When not provided - <code>this.settings.targetElement</code> is used.
 *
 * @type String
 * @returns the prepared HTML for the flash tag
 */
Flash.prototype.render = function(targetElement)
{
	//detect the right syntax
	this.useSyntax = this.getTagSyntax();

	//get browser-dependent open and close tag method-references
	if(typeof(this.prv_renderOpenTag  ) != 'function') this.prv_renderOpenTag = this.prv_renderOpenTag[this.useSyntax];
	if(typeof(this.prv_renderCloseTag ) != 'function') this.prv_renderCloseTag = this.prv_renderCloseTag[this.useSyntax];

	//copy all supported attributes that are populated in settings to attributes
	this.prv_prepareAttributes();

	//move attributes to param for '<object>' syntax
	if (this.useSyntax == 'object')	this.prv_moveAttributesToParams();

	//find the target element;	
	if (!targetElement) 
		targetElement = 
			this.targetElement = 
				this.settings.targetElement || this.targetElement;

	//if the object is not in the DOM yet 
	if( targetElement && !$(targetElement) )
	{
		//if the name exists in postLoadRender collection - we're on the onLoad already
		if(!Flash.postLoadRender[targetElement])
		{
			Flash.postLoadRender[targetElement] =
				Flash.postLoadRender[Flash.postLoadRender.length] =
					this;
			return;
		}
	}

	//get the object
	targetElement = $(targetElement);

	//get or create objectID
	this.objectID = this.settings.id || ((targetElement)? targetElement.id + "_Flash" : "avatar_Flash");

	var out = [];
	this.prv_renderOpenTag(out);
	this.prv_renderAttributes(out);
	this.prv_renderParams(out);
	this.prv_renderCloseTag(out);

	out = out.join("");

	var o = $(this.objectID);
	if (o)
	{
		o.parentNode.removeChild(o);
	}

	if( targetElement === document)
		document.write(out);
	else if( $(targetElement) )
		targetElement.innerHTML = out;

	this.HTML = out;

	return out;
}
/**
 * a collection of all Flash instances that were provided 
 * a target-element and a swf name, but thier target was not 
 * found in the dom by the time of the eval of this file.
 * @type Array
 * @private
 */
Flash.postLoadRender = [];

/**
 * fires on load of the window. 
 * attached by Event.observe with the eval of this file
 */
Flash.renderPostLoad = function()
{
	var arr = Flash.postLoadRender;
	for(var i = 0 ; i < arr.length; i++) arr[i].render();
}
Event.observe(window, "load", Flash.renderPostLoad);


/**
 * gets a reference to the node in the dom of the <code>object</code> or <code>embed</code>
 *
 * @param {String(optional)} movieName
 * The ID of the object tag to retrieve. When not provided - assumes the current objectID.
 */
Flash.prototype.getFlashMovieObject = function (movieName)
{
	if( !movieName ) movieName = this.objectID;

	if (window.document[movieName]) 
	{
		return window.document[movieName];
	}
	if (navigator.appName.indexOf("Microsoft Internet")==-1)
	{
		if (document.embeds && document.embeds[movieName])
			return document.embeds[movieName]; 
	}
	else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
	{
		return document.getElementById(movieName);
	}
}
/******************community scripts Flash.js version:1900.0 - End *********************/
/******************community scripts GameCatalog.AvatarViewer.js version:1900.2 - Start *********************/
if(!window.GameCatalog) GameCatalog = {};

GameCatalog.AvatarViewer = Class.create("UA.User");

/**
 * The defaults for the instance-setting object.
 * <ul>Public settings:
 * <li><code>nickname</code> - the nickname, in case the viewer is not for the current-user or shouldn't use the cookie-data</li>
 *	   <br>
 *     Flash settings:<br> 
 *	   Any other setting is passed on to the flash worker object.<br>
 *	   Examples for flash settings:
 *	  <small>(settings that have default values are noted here first)</small><ul>
 * <li><code>height</code> - default 200
 * <li><code>width</code> - default 150
 * <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>
 * <li><code>style</code></li>
 *	   <br>
 *    Internal settings:
 * <li><code>tinyAvatarCashedURL</code> - The base URL on the cached domain to retrieve the user-avatar XML from 
 * <li><code>tinyAvatarLiveURL</code> - The base URL on the live domain to retrieve the user-avatar XML from 
 * <li><code>movie</code> - The URL for the viewer binaries (swf)
 * <li><code>logger</code> - an instance of {@link Log4Js.Logger} or a string to construct one with
 * <li><code>cookieData</code> - the authentication cookie-data. When not provided - assumed the current user, and Clearance.getMagic(Clearance.UNCLASSIFIED) is used
 * </ul>
 * @type Object
 */
GameCatalog.AvatarViewer.defaultSettings = {/* Internal settings*/
											 movie				: "/Community/avatars/2.0/FAV.swf"
										   , tinyAvatarCashedURL: undefined
										   , tinyAvatarLiveURL	: undefined
											/* Flash Settings */
										   , height : 200
										   , width	: 150
										   , wmode	: "transparent"
										   , base	: ""
										   , quality: "high"
										   , bgcolor: "#ffffff"
										   , menu	: false
										   , allowscriptaccess: true
										   , showTypes : ""
										   }

/**
 * a comma delimited string of all internal setting attribute-names
 * @private
 */
GameCatalog.AvatarViewer.internalSettings = 'channel,targetElement,nickname,cookieData,log,guestAvatarXML,tinyAvatarCashedURL,tinyAvatarLiveURL,movie,showTypes'

/**
 * Constructs the GameCatalog.AvatarViewer object
 * 
 * @param {Object} oSettings
 * Any settings that should be passed to the Flash, or internal setting
 *
 * @class
 * A utility class to render an avatar-viewer, or retrieve the HTML needed to render it.
 * 
 * @constructor
 */
GameCatalog.AvatarViewer.prototype.initialize = function( oSettings )
{
	/**
	 * The instance settings based on the {@link GameCatalog.AvatarViewer#defaultFlashSettings defaultFlashSettings} and the <code>oSettings</code> parameter.
	 * @type Object
	 */
	this.settings = Object.extend(GameCatalog.AvatarViewer.defaultSettings);
	this.settings = Object.extend(this.settings, oSettings || {} );

	Claim.isString( this.settings.tinyAvatarCashedURL, "default setting [tinyAvatarCashedURL] is not initiated and not provided on oSettings constructor argument.")
	Claim.isString( this.settings.tinyAvatarLiveURL	 , "default setting [tinyAvatarLiveURL] is not initiated and not provided on oSettings constructor argument.")
	Claim.isString( this.settings.guestAvatarXML	 , "default setting [guestAvatarXML] is not initiated and not provided on oSettings constructor argument.")

	/**
	 * 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("AvatarViewer");

	Claim.isTrue(this.log instanceof Log4Js.Logger, "settings.log can be ither a Log4Js.Logger or a string to be used as logger-name" );


	this.log.debug("creating Flash worker-instance");
	/**
	 * The {@link Flash} worker object
	 * @type Flash
	 */
	this.fav = new Flash(this.settings.movie , this.settings, GameCatalog.AvatarViewer.internalSettings );
}


/**
 * returns true if the setting name is internal, and should not pass to the {@link Flash} worker instance.
 * @private
 */
GameCatalog.AvatarViewer.prototype.prv_isInternalSettings = function(sSettingName)
{
	return -1 != GameCatalog.AvatarViewer.internalSettings.indexOf(',' + sSettingName.toLowerCase() + ',');
}

/**
 * gets the cookie-data for the current user
 * @private
 */
GameCatalog.AvatarViewer.prototype.getCookieData = function()
{
	return Clearance.getMagic(Clearance.UNCLASSIFIED);
}
/**
 * return true for viewer for current user, and false for any other user<br> 
 * 
 * @type bool
 * @private
 */
GameCatalog.AvatarViewer.prototype.useLiveProcessing = function()

{
	if( this.settings.nickname )
	{
		return false;
	}
	else
	{
		return true;
	}
}
/**
 * return the provided URL, appended with the user identification.<br>
 * The user-identification can be nick-name and channel, if nickname is provided 
 * in the constructor settings, or cookie-data (if provided - from the settings, 
 * elsewise - from Clearance.getMagic(iLevel).
 * 
 * @type String
 * @private
 */
GameCatalog.AvatarViewer.prototype.appendUserIdentification = function(baseUrl)

{
	if( this.settings.nickname )
	{
		this.log.debug("nickname found on settings object: " + this.settings.nickname);
		baseUrl = Url.appendParamValue(baseUrl, "channel", this.settings.channel);
		//baseUrl = Url.appendParamValue(baseUrl, "nickname", this.settings.nickname);  //RUINING the unicode characters
		baseUrl += ("&nickname=" + encodeURIComponent(this.settings.nickname));         //keeping the unicode characters
	}
	else
	{
		var magic = this.settings.cookieData || this.getCookieData();
		
		if (!magic)
		{
			this.log.debug("no credentials nor nickname provided - guest avatar assumend");
			return this.settings.guestAvatarXML;
		}
		
		this.log.debug("cookieData: " + magic);
		baseUrl = Url.appendParamValue(baseUrl, "cookiedata", magic);
	}
	return baseUrl;
}

/**
 * returns the HTML for the viewer using the worker instance {@link GameCatalog.AvatarViewer#fav}.<br>
 * See {@link Flash#render}.
 *
 * @param {String} targetElement
 * the ID of the DOM Container to render the Flash tag into.<br>
 * When not provided - <code>this.settings.targetElement</code> is used.
 *
 * @type String
 * @returns the prepared HTML for the flash tag
 */
GameCatalog.AvatarViewer.prototype.render = function( targetElement )
{
    if(!targetElement) targetElement = this.settings.targetElement;
    targetElement = $(targetElement);
    
	///////////////////////////////////////////////////////////////////
	//TODO: INSTEAD OF THE HARDCODED true BELLOW
	//      use cached avatar whenever the user hasn't saved his  
	//		avatar using the avatar-studio, noted in session cookie
	//      (or live avatar if he has)
	///////////////////////////////////////////////////////////////////
	//var isAvatarChanged = true;
	///////////////////////////////////////////////////////////////////
    //debugger;
    var useLiveProcessingURL = this.useLiveProcessing();
    var avatarBaseURLSetting = (useLiveProcessingURL) ? "tinyAvatarLiveURL" : "tinyAvatarCashedURL" ;

	//var avatarBaseURLSetting = (isAvatarChanged) ? "tinyAvatarLiveURL" : "tinyAvatarCachedURL" ;
	var avatarURL = this.settings[avatarBaseURLSetting];
	this.log.debug("Selected avatarBaseURL : " + avatarURL );
	//this.log.debug("Avatar changed: [" + isAvatarChanged + "], selected avatarBaseURL : " + avatarURL );

	avatarURL = this.appendUserIdentification(avatarURL);
	this.log.debug("avatarURL : " + avatarURL );

	this.fav.settings.flashvars = ["CurrentAvatarUrl=" , escape( avatarURL)
	                              ,"&showmytypes="     , escape( this.settings.showTypes )
	                              ].join("");
								  
	this.log.info("prepared flashvars: " + this.fav.settings.flashvars );

	this.fav.settings.flashvars = this.fav.settings.flashvars.replace(/https/gi, 'http');
    this.log.info("flashvars:" + this.fav.settings.flashvars );

	//this.dispatch("onRender");
	this.HTML = this.fav.render( targetElement );

	this.log.debug("avatar viewer HTML: " + this.HTML.replace(/\</g,"&lt;"));
	return this.HTML;
}
/******************community scripts GameCatalog.AvatarViewer.js version:1900.2 - End *********************/
/******************community scripts GameCatalog.AvatarStudio.js version:1900.0 - Start *********************/
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.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().");
	}
}
/******************community scripts GameCatalog.AvatarStudio.js version:1900.0 - End *********************/
/******************community scripts calendar.js version:1900.0  - Start *********************/
if(!window.GameCatalog)  GameCatalog = {};

GameCatalog.Calendar = Class.create();
/**
 *
 *
 */                                     /* internal settings */
GameCatalog.Calendar.defaultSettings =  {   skinPath    :   null
                                        ,   rssBaseUrl  :   null
                                        ,   movie       :   null
                                        ,   languageCode:   null
                                        ,   channel     :   null
                                        /* flash settings */
                                        ,   width       :   300
                                        ,   height      :   290
                                        ,   quality     :   'high'
                                        ,   align       :   'middle'
                                        ,   salign      :   ''
                                        ,   loop        :   'true'
                                        ,   play        :   'true'    
                                        ,   scale       :   'showall'
			                            ,   wmode       :   'window'
			                            ,   devicefont  :   'false'
			                            ,   bgcolor     :   '#ffffff'
			                            ,   menu        :   'true'
			                            ,	allowFullScreen     : 'false'
			                            ,   allowScriptAccess   : 'sameDomain'
                                        }

/**
 * @private
 */
GameCatalog.Calendar.internalSettings = ",movie,rssBaseUrl,skinPath,languageCode,channel,"

/**
 * @constructor
 */
GameCatalog.Calendar.prototype.initialize = function(targetElement, oSettings)
{
	/**
     * The current isntance settings object
     * @type Object
     */
    this.settings = Object.extend({}, GameCatalog.Calendar.defaultSettings);
    Object.extend(this.settings, oSettings);

    Claim.isScalar(this.settings.skinPath, "[skinPath] must be provided as oSettings entry or as a Query-String parameter");
    Claim.isScalar(this.settings.rssBaseUrl, "[rssBaseUrl] must be provided as oSettings entry or as a Query-String parameter");
    Claim.isScalar(this.settings.rssBaseUrl, "[languageCode] must be provided as oSettings entry or as a Query-String parameter");
    Claim.isScalar(this.settings.rssBaseUrl, "[channel] must be provided as oSettings entry or as a Query-String parameter");
    Claim.isString(this.settings.movie, "[movie] setting is missing. It's expected to be initiated by the script reference src='CatalogConfig/ChannelConfig.aspx' or provided as attribute on [oSettings] object");
    
    /**
	 * 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("Calendar");

    /**
     * the Flash worker object that writes the Calendar flash tag
     * @type Flash
     */
    this.calendar = new Flash(this.settings.movie, this.settings, GameCatalog.Calendar.internalSettings);

    /**
     * The target element to render the ticker into
     * @type String
     */
    this.targetElement = targetElement
}

/**
 * 
 */
GameCatalog.Calendar.prototype.render = function(targetElement)
{
    targetElement = targetElement || this.targetElement;
    Claim.isTrue(!!targetElement, "Calendar.render cannot be called without targetElement");
    
    this.calendar.settings.flashvars = 
    this.settings.flashvars = [ 'OSkin='     , this.settings.skinPath  
                              , '&OEvents='  , this.settings.rssBaseUrl
                              ].join("");

	this.log.debug("flash vars: " + this.calendar.settings.flashvars );
    
     //render to the provided target element
    this.calendar.render(targetElement);
    this.HTML = this.calendar.HTML;
    this.log.debug("Calendar HTML:" + this.HTML);
}   
    
/**
 * 
 */
GameCatalog.Calendar.WriteCalendar = function(targetElement, oSettings) 
{
    var c = new GameCatalog.Calendar(targetElement, oSettings);
    c.render(targetElement);
    return c;
}
/******************community scripts calendar.js version:1900.0  - End *********************/
/******************community scripts ChannelConfig.aspx - Start *********************/

initLogger = new Log4Js.Logger("Catalog.Congfig"); //----------------------------------------------------------------------------

try{ 
	Claim.isObject(GameCatalog.AvatarStudio, "the script that defines GameCatalog.AvatarStudio must be called before the call to the script that configs catalog utils"); 
	Claim.isObject(GameCatalog.AvatarStudio.defaultSettings,"the script that defines GameCatalog.AvatarStudio.defaultSettings must be called before the call to the script that configs catalog utils"); 
	Object.extend( 
		GameCatalog.AvatarStudio.defaultSettings
		, {FVAR_ColorsXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=colors&code=colors"
		,FVAR_LayoutXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=layout&code=layout"
		,FVAR_LocalizationXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=dictionary&code=dictionary"
		,FVAR_ItemLibraryXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=itemLibrary&code=itemLibrary"
		,FVAR_OmnitureXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=omniture&code=omniture"
		,FVAR_PromotionsXML : "http://userassets.apizone.betaregion.oberon-media.com/CatalogConfig/2000/App/ConfigXML.ashx?type=promotions&code=promotions"
		
		,FVAR_LoadingSceneURL : "/community/avatars/skins/wanadoo//config/preloader.swf"
		,FVAR_ProgressURL : "/community/avatars/skins/wanadoo//config/progress.swf" 
		
		,genericErrorMsg : "AVATAR_STUDIO_GENERIC_ERROR_MESSAGE" 
		,defaultLanguageCode : "fr" 
		,base : "/Community/Avatars/2.2/" 
		,studioSWF : "/Community/Avatars/2.2/as.swf" 
		
		,FVAR_DEBUG : "1"
		,FVAR_LogLevel : "3" 
		,FVAR_showMyTypes: "~glasses~hair~face~skull~shirt~beard~background~body~jewelry~hats~" 
		,FVAR_AvatarSaveURL: UA.User.prototype.SAVE_AVATAR_URL 
		,channel : UA.CHANNEL 
		,fullAvatarBaseURL : Url.appendParamValue(UA.User.prototype.GET_AVATAR_URL,"type", "full") 
		,tinyAvatarBaseURL : Url.appendParamValue(UA.User.prototype.GET_AVATAR_URL,"type", "tiny") 
		} 
	); 
	
	GameCatalog.AvatarStudio.initated = true; 
}
catch(e){ 
	initLogger.warn("Failed initiating GameCatalog.AvatarStudio: " + Serialize(e) )} 
	
	//----------------------------------------------------------------------------

try{ 
	Claim.isObject(GameCatalog.AvatarViewer, "the script that defines GameCatalog.AvatarStudio must be initiated before the call to the script that configs catalog utils"); 
	Claim.isObject(GameCatalog.AvatarViewer.defaultSettings,"the script that defines GameCatalog.AvatarStudio.defaultSettings must be initiated before the call to the script that configs catalog utils"); 
	Object.extend
	( 
		GameCatalog.AvatarViewer.defaultSettings , 
		{
			tinyAvatarLiveURL : Url.appendParamValue(UA.User.prototype.GET_AVATAR_URL , "type","tiny") 
			,tinyAvatarCashedURL: Url.appendParamValue(UA.User.prototype.GET_CACHED_AVATAR_URL, "type", "tiny") 
			,guestAvatarXML : "/community/avatars/skins/wanadoo//config/NoAvatar.xml"
			,showTypes : "~glasses~hair~face~skull~shirt~beard~background~body~jewelry~hats~"
			,movie : "/Community/Avatars/2.2/FAV.swf" ,channel : UA.CHANNEL 
		} 
	);

	GameCatalog.AvatarViewer.initiated = true; 
	}
	catch(e){ initLogger.warn("Failed initiating GameCatalog.AvatarViewer: " + Serialize(e) )
} 
//----------------------------------------------------------------------------

try{ 
	Claim.isObject(GameCatalog.Calendar, "the script that defines GameCatalog.Calendar must be initiated before the call to the script that configs catalog utils"); 
	Claim.isObject(GameCatalog.Calendar.defaultSettings, "the script that defines GameCatalog.Calendar.defaultSettings must be initiated before the call to the script that configs catalog utils"); 
	
	GameCatalog.Calendar.defaultSettings.movie = "calendar.swf"; 
	GameCatalog.Calendar.defaultSettings.rssBaseUrl = ""; 
	GameCatalog.Calendar.defaultSettings.skinPath = ""; 
	GameCatalog.Calendar.defaultSettings.languageCode = "fr"; 
	GameCatalog.Calendar.defaultSettings.channel =	110167437 ; 
	}
	catch(e){ initLogger.warn("Failed initiating GameCatalog.Calendar: " + Serialize(e))
}

/******************community scripts ChannelConfig.aspx - End *********************/
/******************presence Js - Start *********************/
// Presence catalog namespace
if (window.PresenceCatalog == null) 
	PresenceCatalog = {};

// Lobby / Lobbies
PresenceCatalog.Lobbies = {};

PresenceCatalog.Lobbies.All = [];
PresenceCatalog.Lobbies.All.ByLobby = {};
PresenceCatalog.Lobbies.All.BySku = {};
PresenceCatalog.addLobby = function( lobbyID, numberOfPlayers )
{
	var newLobby = 
			{ 
				LobbyID : lobbyID,
				NumberOfPlayers : numberOfPlayers
			};
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.ByLobby[newLobby.LobbyID] = newLobby;
}

PresenceCatalog.addLobbySku = function( sku, lobbyID, numberOfPlayers )
{
	var newLobby = 
			{ 
				LobbyID : lobbyID,
				NumberOfPlayers : numberOfPlayers
			};
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.BySku[sku] = newLobby;
}

PresenceCatalog.addLobbySku2 = function( sku, lobbyID, numberOfPlayers, membersAutoPlayRoomURL, nonMembersAutoPlayRoomURL )
{
    var newLobby = 
            {
                LobbyID             : lobbyID,
				NumberOfPlayers     : numberOfPlayers,
				MembersRoomURL      : membersAutoPlayRoomURL,
                NonMembersRoomURL   : nonMembersAutoPlayRoomURL
            }
    this.Lobbies.All[this.Lobbies.All.length] = newLobby;
    this.Lobbies.All.BySku[sku] = newLobby;
}

// Room / Rooms
PresenceCatalog.Rooms = {};

PresenceCatalog.Rooms.All = [];
PresenceCatalog.Rooms.All.ByRoom = {};
PresenceCatalog.addRoom = function( roomID, numberOfPlayers )
{
	var newRoom = 
			{
				RoomID : roomID,
				NumberOfPlayers : numberOfPlayers
			};

    this.Rooms.All[this.Rooms.All.length] = newRoom;
    this.Rooms.All.ByRoom[newRoom.RoomID] = newRoom;
}

PresenceCatalog.Rooms.All.ByCategory = {};
PresenceCatalog.addCategory = function( categoryCODE,numberOfPlayers )
{
	var newCategory = 
			{
				CategoryCODE : categoryCODE,
				NumberOfPlayers : numberOfPlayers
			};

    this.Rooms.All.ByCategory[categoryCODE] = newCategory;
}

PresenceCatalog.getTopPlayedSkus = function(iTop) 
{
    var topSkus = new Array();
    var allSkus = new Array();
    for (sku in this.Lobbies.All.BySku)
    {
        var currElement = 
            {
                Sku             : sku,
                NumberOfPlayers : this.Lobbies.All.BySku[sku].NumberOfPlayers
            };
        allSkus[allSkus.length] = currElement;
    }
    allSkus.sort(PresenceCatalog.getTopPlayedSkus.sortSkus);
    
    for (index = 0; index < allSkus.length && index < iTop; ++index)
    {
        topSkus[topSkus.length] = allSkus[index].Sku;
    }
    return topSkus;
}

PresenceCatalog.getTopPlayedSkus.sortSkus = function(a, b)
{
    return b.NumberOfPlayers - a.NumberOfPlayers;
}

// place holder (the whole community)
PresenceCatalog.NumberOfPlayers = 0;

/******************presence Js - End *********************/
/****************** TC.Utils.js - Start *********************/
/* === TMP FIXES ON PRODUCT UTILS === */
//-=-=-=-=-=- Enhances on Object -=-=-=-=-=-
Object.clone = function(obj)
{
	return this.extend( {} , obj);
}
/**
 * @param {variant} value
 * @returns pseodo-JSON serialization of the variant
 * @type string
 */
Object.serialize = function(value)
{	
	var arrObjs = [];
	// ser is defined here so it could see arrObjs, 
	// and make sure there is no endless recursion, 
	// or objects that are serialized twice in a same tree
	function ser(v){
		switch(typeof(v))
		{
			case 'NaN'		:	return "NaN";
			case 'undefined':	return "undefined";
			case 'boolean'	:	return (v).toString();
			case 'number'	:	return (isFinite(v))? (v).toString() : "\"Infinity\"" ;
			case 'string'	:	return "\"" + v.replace(/\"/g ,"\\\"") + "\"";
			case 'function'	:	return "{function}";
		}
		// handle objects
		if(v == null)			return "null";
		if(v instanceof Date)	return "new Date(" + v.getTime() + ")"; 
		if(v instanceof Array)
		{
			var i, arr = [];

			if (  GameCatalog.TagSkuLinks 
			   && v.byWeight == GameCatalog.TagSkuLinks.prototype.byWeight 
 			   )
			  return "[GameCatalog.TagSkuLinks,length: " + v.length + "]";

			if (  GameCatalog.SkuTagLinks
			   && v.byWeight == GameCatalog.SkuTagLinks.prototype.byWeight )
			  return "[GameCatalog.SkuTagLinks,length: " + v.length + "]";
			
			for(i = 0; i < v.length; i++)
				arr[arr.length] = ser(v[i]);
				
			return "[" + arr.toString() + "]";
		}
		
		//serialize an unknown object
		// - prevent recursive serialization
		if ( arrObjs.indexOf(v) != -1 )
		{
			return "\"*ref" + (  (v.id)? "-id:" + v.id : (  (v.name) ? "-name:" + v.name : ":" + v.toString()  )   ) + "\"";
		}
		arrObjs[arrObjs.length] = v;


		//handle html-dom-nodes
		if( v.parentNode && v.attributes && (v.children || v.childNodes) && v.tagName)
		{
			var i, e =  { tagName	: v.tagName
						, parent	: v.parentNode.tagName 
						, innerHTML : "\"" + v.innerHTML.replace(/"/g,"\\\"").replace(/</g, "&lt;") + "\""
						}; 
			for(i = 0; i < v.attributes.length; i++)
				if(v.attributes[i].value && v.attributes[i].value != "null")
					e[v.attributes[i].name] = v.attributes[i].value;
					
			return ser(e);
		}

		// - do the serializing...
		var each, arr  = [];
		// Note: the for-each could throw for activeX objects and such
		try
		{
			for(each in v)
			{
				if(null !== v[each])
					arr[arr.length] = each + ":" + ser(v[each]);
			}
			return "{" + arr.toString() + "}";
			
		}catch(ex){
			return "\"-error in serializing: " + ex.message + "-\""
		}
	}

	return ser(value);
}

/**
 * copies properties to destination from source only when they are totally undefined on the destination.
 *
 * @param {object} destination
 *
 * @param {object} source
 */
Object.safeExtend = function(destination, source) {
  for (property in source) {
	if(undefined === destination[property])
		destination[property] = source[property];
  }
  return destination;
}

//-=-=-=-=-=- /Enhances on Object -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Class -=-=-=-=-=-
/**
 * Creates a constructor function.
 * When provided a parent - it createa a subclass of the provided parent,
 * or throws an error.
 * 
 * @param {string|function(optional)} parent
 *  The parent class name in string, or a reference to the parent class constructor
 */
// - fix: allow it to accept (parent) and link inheritance.
Class.create = function(parent)
{
    var fConstr = function()
    {
		var arrCtors = [];
		var fConstructor = this.constructor;
		do
		{
			//fConstructor could be a system class that doesn't implement initialize
			if('function' == typeof(fConstructor.prototype.initialize))
				arrCtors[arrCtors.length] = fConstructor.prototype.initialize;
			fConstructor = fConstructor.parentConstructor;
		}
		while(typeof(fConstructor) == 'function');

		for(var i = arrCtors.length; i-- > 0; ) 
		{
			arrCtors[i].apply(this, arguments);
		}
    }

	if(parent)
	{ 
		return Class.linkInheritance(parent, fConstr);
	}

	return fConstr;
}
/**
 * @param {function|object|string} parent
 *  A parent class, an instance of it, or a string representing its class name
 *
 * @param {function} subclass
 *  The subclass function
 */
// - new.
Class.linkInheritance = function(parent, subclass){
	if(typeof(parent)=='string')
		parent = eval(parent);
	Claim.check(	typeof(parent) == 'object' 
			   ||	typeof(parent) == 'function'
			   , "'parent' is a function or an object"
			   , "Class.linkInheritance(parent)")
	Claim.isFunction(subclass,"Class.linkInheritance(subclass)");

    //copy all static members
    subclass = Object.extend( subclass , parent );
	delete subclass.AsPrototype;

	//keep the parent constructor in parentConstructor
	subclass.parentConstructor = parent;

	//--THROWS FRIENDLY ERRORS WHEN MISUSED--
    subclass.prototype = Class.AsPrototype(parent);

	//override the 'constructor' attribute on the new prototype instance 
    //(originally it was the parent constructor)
    subclass.prototype.constructor = subclass ;

    return subclass;
}
/**
 * Mostly for internal use, but can be used to determine wether a class is inheritable.
 * When the provided parameter is not inheritable - it throws an error.
 *
 * @param {string|function|object} fClass
 *  A string evaluates to a class or a the class itselfs
 *
 * Function:
 *  if
 *		can be instantiated using a default constructor
 * 			OR
 * 		parent.AsPrototype() returns a valid instance
 * 			OR
 * 		parent === Object
 *	  creates an instance, and puts initialize_base on it.
 *
 * String:
 *  if	
 *		evaluates to a valid class name
 * 	carrSuperclasss recursively on evaluation's returned value
 *
 * Object: 
 *  creates a shellow copy, and puts initialize_base on it.
 */
// - new.
Class.AsPrototype = function(fClass){
	switch(typeof(fClass)){
		case 'string':
			if (  window[fClass] != null
			   && window[fClass] === eval(fClass) )
			{
				if( typeof(eval(fClass)) != 'function') throw new Error("'" + fClass + "' does not evaluates to a valid class");
				return Class.AsPrototype(eval(fClass));
			}
		case 'function':
			var oProto;
			if (fClass === Object) return {};

			if	(typeof(fClass.AsPrototype) == 'function')
			{
				oProto = fClass.AsPrototype();
				if (typeof(oProto) != 'object') throw new Error("provided class implements.AsPrototype() but it did not return an instance.");
			}
			else
			{
				try{
					oProto = new fClass();
				}
				catch(ex)
				{
					throw new Error("Class.AsPrototype(fClass) Failed to instantiate 'fClass' with default constructor. \n\nError message: " + ex.message );
				}
			}
			return oProto;

		case 'object':
			return Object.extend({}, fClass);

		default:
			throw new Error("A prototype can be extracted only from one of the followings: \n\t- an object instance \n\t- a valid constractor function \n\t- a string evaluates to ither one of the above");
	}
}

/**
 *
 */
Class.enhancePrototype = function(fClass, oInterface)
{
	Claim.check( typeof(fClass) == 'function' 
				, "Class.enhancePrototype(fClass,oInterface) - fClass"
				, "fClass must be a function"
				);
	Claim.check( oInterface && typeof(oInterface) == 'object'
				, "Class.enhancePrototype(fClass,oInterface) - oInterface"
				, "oInterface must be an object"
				);
				
	return Object.extend( fClass.prototype, oInterface );
}

/**
 *
 */
Class.enhanceSingleton = function(oSingleton, oInterface)
{
	Claim.check( oTargetClass && typeof(oTargetClass) == 'object' || typeof(oTargetClass) == 'function'
				, "Class.enhance(oSingleton)"
				, "oTargetClass must be a function"
				);
	Claim.check( oInterface && typeof(oInterface) == 'object'
				, "Class.enhancePrototype(fClass,oInterface) - oInterface"
				, "oInterface must be an object"
				);
				
	return Object.extend( oSingleton, oInterface );
}
Class.enhance = function(fClass /*, param1, param2, param3 ... */)
{
	var oInterface;
	for(var i = 1; i < arguments.length ; i++)
	{
		oInterface = arguments[i];
		try { fClass = this.enhanceSingleton(fClass, oInterface); } catch(ex) {}
		try { fClass.prototype = this.enhancePrototype(fClass, oInterface); } catch(ex) {}
	}
	return fClass;
}
//-=-=-=-=-=- /Enhances on Class -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Element -=-=-=-=-=-
/**
 * sets the text of the provided element, according to its tag-name
 * input fields, text-area  - by .value
 * the rest - innerHMTL
 *
 * @param {Element} e - the DOM element ID
 * @param {string}	sText
 */
Element.setText = function(e,sText)
{
	var tag = e.tagName.toUpperCase();
	switch(tag)
	{
		case "INPUT":
		case "TEXTAREA":
			e.value = sText;
			break;
		case "SELECT":
			//TODO: - decide what to do if the sText doesnt match any value of the select element
			e.value = sText;
			break;
		default:/*DIV, SPAN, TD, A, H1-H5, and all the rest*/
			try{
				e.innerHTML = sText;
			}catch(ex){
				try{
					if(typeof e.innerText == 'undefined')
						e.textContent = sText;
					else
						e.innerText = sText;
				}catch(ex){
					this.log.error("Element.setText: failed to set to element the text: " + sText);
				}
			}
	}
}
/**
 * gets the text of the provided element, according to its tag-name
 * input fields, text-area  - by .value
 * the rest - innerHMTL
 *
 * @param {Element} oElement - the DOM element ID
 */
Element.getText = function(oElement)
{
	switch(oElement.tagName)
	{
		case "INPUT":
			if(oElement.type == "checkbox")
				return (oElement.checked)? oElement.value : "";
			//no break! deliberated case sliding!
		case "TEXTAREA":
		case "SELECT":
			strTemplate = oElement.value;
			break;
		default:/*DIV,SPAN,H1-6,TD,CETNER,B,I,U,and all the rest*/
			strTemplate = oElement.innerHTML;
	}
}
//-=-=-=-=-=- /Enhances on Element -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Log4Js -=-=-=-=-=-
/**
 * Initiates a general cookie.
 * To be pasted in the address bar like this:
 *    Javascript:Log4Js.pop();
 *
 * @param {object(optional)} conf 
 * The configuration object. When not provided - initiates a default one for popup.
 */
// - new.
Log4Js.pop = function(conf){
    if(!conf || typeof(conf) != 'object')
	{
		conf =  { anchorsByName:  { "*"  : ["t1"]
                                  , Claim: ["t2"]
                                  }
                , targetByAnchor: { t1: new Log4Js.PopupTarget(Log4Js.ALL  ,"log4js-%U-%T",true)
                                  , t2: new Log4Js.PopupTarget(Log4Js.FATAL,"log4js-%U-%T",true)
                                  }
                };
    }
    Cookies.set("log4js.config", conf, {});
    this.fromConfig(conf);
}
/**
 * Adds a logging anchor by name
 *
 * @param {string} sClassName
 * The name of the logged element
 * 
 * @param {string} enLEVEL
 * The "enum" name of the warn level
 */
// - new.
Log4Js.add = function(sClassName, enLEVEL){
	Claim.isString(sClassName, "Log4Js.add(sClassName, enLEVEL) - sClassName must be a string");
	Claim.isString(enLEVEL, "Log4Js.add(sClassName, enLEVEL) - enLEVEL must Log Level ALL, DEBUG, WARN, ...");
	var iLevel = this[enLEVEL.toUpperCase()];
	Claim.isNumber(iLevel, "Log4Js.add(sClassName, enLEVEL) - Log4Js." + enLEVEL + " is not a valid warn-level");
	Claim.check(iLevel >= 0 && iLevel <=6, "0 <= iLevel <= 6", "Log4Js.add(sClassName, enLEVEL) - Log4Js[enLEVEL must be between 0 to 6");
	
	var conf = this.toConfig();
	conf.targetByAnchor.newAnchor = new Log4Js.PopupTarget(iLevel ,"log4js-%U-%T",true)
	conf.anchorsByName[sClassName] = ["newAnchor"];
	this.pop(conf);
}
/**
 * Removes an anchor by name
 *
 * @param {string} sClassName
 * The name of the logged element
 */
// - new.
Log4Js.clear = function(sClassName){
	Claim.isString(sClassName, "Log4Js.clear(sClassName) - sClassName must be a string");
	var conf = this.toConfig();
	delete conf.anchorsByName[sClassName];
	this.pop(conf);
}
/**
 * stops the logging by clearing the log4js configuration.
 * Done by setting the configuration to a single anchor - all, pointed to NONE.
 *
 */
// - new.
Log4Js.stop = function(){
    var conf =  { anchorsByName:  { "*"  : ["t1"]
                                  }
                , targetByAnchor: { t1: new Log4Js.PopupTarget(Log4Js.NONE  ,"log4js-%U-%T",true)
                                  }
                };
    Cookies.set("log4js.config", conf, {});
    this.fromConfig(conf);
}
//-=-=-=-=-=- /Enhances on Log4Js -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Claim -=-=-=-=-=-
/**
 * Claims the provided object to be a function
 * Throws an error if its not
 *
 * @param {object} object
 * The tested object
 *
 * @param {string} comment
 * String comment for the Error and for the log
 */
 // - new.
Claim.isFunction = function(object, comment)
{{
    Claim.check(typeof(object) == 'function'
               ,"isFunction(" + Claim.valueType(object) + ")"
               ,comment)
}}
Claim.isLiveObject = function(object, comment)
{
	Claim.check(	null != object 
				&&	typeof(object) == 'object'
				, "isLiveObject(" + object + ")"
				, comment)
}
//-=-=-=-=-=- /Enhances on Claim -=-=-=-=-=-
//-=-=-=-=-=- Enhances on Cookies -=-=-=-=-=-
Cookies.pop = function(){
	var each, s = [];
	for(each in this.rawByName){
		s[s.length] = each 
		s[s.length] = ":"
		s[s.length] = this.rawByName[each]
		s[s.length] = "\n"
	}
	alert(unescape(s.join("")));
}
//-=-=-=-=-=- /Enhances on Cookies -=-=-=-=-=-
/* === /TMP FIXES ON PRODUCT UTILS === */

// --- Enhance String.prototype -----------------------------------
/**
 * An empty string constant
 */
String.empty = String.Empty = "";
/**
 * Populates a template: replaces all provided place-holders in a string, with values.
 *
 * @param {object} oMapping
 * A hash in which every key represents a place-holder in the string to be replaced with its correlating value
 */
String.prototype.populateTemplate = function(oMapping)
{
	Claim.isObject(oMapping, "String.populateTemplate(..,oMapping,..)");

	var sTemplate, placehoder, replacement;

	sTemplate = String(this);

	for(placeholder in oMapping)
	{
		replacement = oMapping[placeholder];
		sTemplate = sTemplate.replace(new RegExp(placeholder,"g"), replacement);
	}
	return sTemplate;
}
String.prototype.beutifySerialization = function()
{
	var out = []
	  , indent = ""
	  , i
	  , arr = this.split("");
	  
	for(i = 0; i < arr.length; i++){
		switch(arr[i]){
			case "{":
				indent += "\t";
				out[out.length] = "\n" + indent;
				out[out.length] = arr[i] + "\t";
				break;
			case "}":
				out[out.length] = "\n" + indent;
				out[out.length] = arr[i] + "\t";
				indent = indent.substr(1);
				break;
			case "[":
				indent += "\t";
				out[out.length] = "\n" + indent;
				out[out.length] = arr[i] + "\t";
				break;
			case "]":
				out[out.length] = "\n" + indent;
				out[out.length] = arr[i] + "\t";
				indent = indent.substr(1);
				break;
			case ",":
				out[out.length] = "\n" + indent;
				out[out.length] = arr[i] + "\t";
				break;
			default:
				out[out.length] = arr[i];
		}
	}	
	return out.join("");	
}
/**
 * Binds a template: replaces all indicated placeholders with data. 
 * Data comes from data-properties on the oDataSource, 
 * and the mapping between placeholders in the string and the data-properties 
 * is provided in the oMapping parameter.
 *
 * @param {object} oMapping
 * A hash, in which every key is a placeholder in the string, 
 * and its correlating value can be:
 * - A string representing a data-property on the data-srource in oDataSource
 * - A function that returns value as a function of the oDataSource
 * - Any other value will be casted to string to return the value, and the returned value will be used, regardles to the data-source.
 *
 * @param {object} oDataSource
 * A data-object by which to bind the template
 *
 * @param {object(optional)} oLog
 * When provided - the logging of this execution is emitted to the provided instance.
 * Otherwise - to a casual instance, named "String.bindTemplate".
 */
String.prototype.bindTemplate = function(oMapping, oData, oLog)
{
	Claim.isObject(oMapping, "String.bindTemplate(..,oMapping,..)");
	Claim.isObject(oData , "String.bindTemplate(..,oData)");

	var oDataSource = ('object' == typeof(oData.dataItem))? oData.dataItem : oData;

	var sTemplate, placehoder, attribute, replacment;
	var log = (oLog && oLog instanceof Log4Js.Logger)? oLog : new Log4Js.Logger("String.bindTemplate");
	
	sTemplate = this.toString();
	
	for(placehoder in oMapping)
	{
		if( this.indexOf(placehoder) == -1){
			log.debug("in bindTemplate(...) - placeholder '" + placehoder + "' is not found in bound template");
			continue;
		}

		attribute = oMapping[placehoder];
		if(undefined == attribute || null == attribute){
			log.warn("in bindTemplate(...) oMapping dictionary specifies a placeholder without providing its data-attribute name: " + placehoder);
			continue;
		}
		
		switch(typeof(attribute))
		{
			case 'function':
				try
				{
					replacement = attribute(oDataSource, log);
				}catch(ex){
					log.error("String.bindTemplate - Error in mapping-handler for " + placehoder + " : " + attribute.toString() );
					throw ex;
				}
				break;
				
			case 'string':
				replacement = oDataSource[attribute];
				if('function' == typeof(replacement))
				{
					replacement = replacement.apply(oDataSource);
				}
				else if(null == replacement)
				{
					if(oData != oDataSource && null != oData[attribute])
					{
						replacement = oData[attribute];	
						if('function' == typeof(replacement))
						{
							replacement = replacement.apply(oData)
						}
						
					}
					
					if(null == replacement)
					{
					log.warn("in bindTemplate(...) oMapping dictionary specifies a property that does not exist on the provided oDataSource. Placehoder: " + placehoder +", using the name of the attribute: " + attribute);
					replacement = attribute;
				}

				}
				break;
			
			default:
				replacement = String(attribute);
			
		}
		
		//replacment = replacment.replace(/\$/g,"");
		sTemplate = sTemplate.replace(new RegExp(placehoder,"g"), replacement);
	}
	return sTemplate;
}
/**
 * returns the string without spaces in the start or at the end.
 */
String.prototype.trim = function(){
	var iStart = -1, iEnd = this.length;
	while (this.charAt(++iStart) == ' ');
	while (this.charAt(--iEnd) == ' ');
	if (iStart == iEnd && this.charAt(iStart) != ' ' ) return this.substr(iStart,1);
	return this.substring(iStart, iEnd + 1);
}

/**
 * returns the current string padded on the left with the provided padding char to the specified length
 * @param {string} c - the padding char
 * @param {number} iLength - the length the padded string should reach
 */
String.prototype.leftPad = function(c,iLength)
{
	s = this.toString();
	while(s.length < iLength) s = c + s;
	return s;
}
/**
 * @param {String} substr The string to search
 */
String.prototype.contains = function(substr)
{
	if(substr === undefined || substr === null) return false;
	return this.indexOf(substr) != -1;
}
// --- /Enhance String.prototype -----------------------------------

// --- Enhance Number.prototype -----------------------------------
//TODO: handle formatting of decimals. (0.34874873)
/**
 * returns the formatted string swith comas.
 **/
Number.milleSeperator = ",";
//Number.fragmentsSeperator = ".";
Number.prototype.format = function()
{
	var iNumber = this;
    var sFormatted = "", psik = ""; 
    var s3Digits, i3Digits;
    while (iNumber > 0)
    {
        i3Digits = iNumber % 1000;

		s3Digits = String(i3Digits)

		iNumber = Math.floor(iNumber / 1000);
		if (iNumber > 0) 
		{		
			if(i3Digits < 100) 
			{
				s3Digits = "0" + s3Digits;
				if(i3Digits < 10) 
				{
					s3Digits = "0" + s3Digits;
				}
			}
		}
        
        sFormatted = s3Digits + psik + sFormatted;
        psik = Number.milleSeperator;

    }
    
    return (sFormatted.length)? sFormatted: "0";    
}

/**
 * returns the current number padded on the left with the provided padding char to the specified length
 * @param {string} c - the padding char
 * @param {number} iLength - the length the padded string should reach
 * @param {number} iBase - the count base to format by it to string 
 */
Number.prototype.leftPad = function(c, iLength, iBase)
{
	if(iBase === undefined) return this.toString().leftPad(c,iLength);
	
	iBase == parseInt(iBase);
	if(!iBase || iBase == NaN || iBase < 2) iBase == 10;
	
	return this.toString( iBase ).leftPad(c,iLength);
}
// --- /Enhance Number.prototype -----------------------------------

// --- Enhance Array.prototype------------------------------------------------------------
/**
 * gets a part of the array of a maximum size.<br>
 * <a target="_blank" href="/Js/units/reference/_Infra/Array.htm#cut">see Ref-Impl</a>
 * @returns a slice of the array, starting in the provided iStart, and of maximum iCount elements.
 *
 * @param {number} iStart    index to start from 
 * @param {number} iCount    maximum elements to fetch
 * 
 * @type Array
 */
Array.prototype.cut = function(iStart, iCount)
{
    var iEnd = undefined;
    if(iStart==undefined) iStart = 0;
    iEnd = (iCount==undefined)? this.length : iStart + iCount;
    return this.slice(iStart, iEnd);
}
// --- /Enhance Array.prototype------------------------------------------------------------

if(!window.Const) Const = {};
Object.extend(	Const,	
				{	UNSET_STRING: "-UNSET-STRING-"
				,	UNSET_NUMBER: NaN	
				,	UNSET_OBJECT: undefined 
				}
			 );



/* === TC Namesapce ============================================================ */
if(!window["TC"])
	window.TC = {};

/**
 * Synonym for accessing the catalog by-sky hash
 */
TC.SKUs = GameCatalog.Game.All.BySku;

/**
 * Synonym for accessing the catalog all-games-on-client array
 */
TC.SKUs.All = GameCatalog.Game.All;


/**
 * Expects a data-object, with a property named "sku".
 * If such sku exists in the catalog - it copies all game properties 
 * from the catalog game instance to the provided object.
 *
 * @param {object} oTarget
 * The data-object to extend
 *
 * @param {number(optional)} sku
 * When no property "sku" defined on parameter oTarget - used as the sku to search by 
 *
 * @returns the enhanced object, or null when the sku does not exist in the catalog
 */
TC.SKUs.extendDataFromSKU = function(oTarget, sku)
{
	if(oTarget.sku) sku = oTarget.sku;
	Claim.isNumber(parseInt(sku), 'TC.SKUs.extendDataFromSKU(...) - the sku of the game to enhance from should be provided ither as a property "sku" on the provided oTarget, or as a second parameter');
	
	var oGame = this[sku];
	if ( !oGame )
		return null;

	return Object.extend( oTarget, oGame );
}	



/**
 * Synonym for accessing the catalog tags by internal-name hash
 */
if( GameCatalog.Tag ) TC.Tags = GameCatalog.Tag.All;



// --- TC.OnlinePlayers -----------------------------------
/**
 *
 */
TC.OnlinePlayers = {}
/**
 *
 */
TC.OnlinePlayers.log = new Log4Js.Logger("TC.OnlinePlayers");
/*
* Defaults settings of the behavious of this component. For customization override
* the required property in the projectal phase
*/	
TC.OnlinePlayers.settings = { onlinePlayersUnavailable: "N/A"
							};
/**
 *
 */
TC.OnlinePlayers.writeCommunity = function()
{
	this.prv_writeOnlineNumber(PresenceCatalog);
}
/**
 *
 */
TC.OnlinePlayers.writeByCategory = function(categoryCode){
	var oByCat;
	try
	{
		oByCat = PresenceCatalog.Rooms.All.ByCategory[categoryCode];
	}
	catch(ex)
	{
		this.log.error("Exception in access to PresenceCatalog.Rooms.All.ByCategory[" + categoryCode + "]: " + ex.message);
	}
	this.prv_writeOnlineNumber(oByCat);
	
}
/**
 *
 */
TC.OnlinePlayers.writeBySku = function(skuCode)
{
	var oBySku;
	try
	{
		oBySku = PresenceCatalog.Lobbies.All.BySku[skuCode];
	}
	catch(ex)
	{
		this.log.error("Exception in access to PresenceCatalog.Lobbies.All.BySku[" + skuCode +" ]: " + ex.message);
	}

	this.prv_writeOnlineNumber(oBySku);
	
}
/**
 *
 */
TC.OnlinePlayers.prv_writeOnlineNumber = function(oDataObject)
{
	var sOut = this.settings.onlinePlayersUnavailable
	if(oDataObject && null != oDataObject.NumberOfPlayers)
	{
		sOut = oDataObject.NumberOfPlayers;
		this.log.info("Number Of ActivePlayers: " + sOut);
	}
	else
	{
		this.log.info("Number Of ActivePlayers not found. oDataObject:"  + Object.serialize(oDataObject) );
	}
	
	document.write(sOut);
}
TC.OnlinePlayers.writeByRoom = function(roomGuid)
{{
	var oByRoom;
	try
	{
		oByRoom = PresenceCatalog.Rooms.All.ByRoom[roomGuid];
	}
	catch(ex)
	{
		this.log.error("Exception in access to PresenceCatalog.Rooms.All.ByRoom[" + roomGuid + "]: " + ex.message);
	}
	this.prv_writeOnlineNumber(oByRoom);
}}
//----------------------------------------------------------------------------
TC.Omniture = {}
TC.Omniture.trackRemoteUrl = Const.UNSET_STRING;
//----------------------------------------------------------------------------


/**
 * @requires Class => from prototype
 * @requires Log4Net.Logger => from common
 * @requires Object.serialize => currenly a projectile cross-project enhancement (attached).
 * @interface
 * Interface-implementation to enhance classes with event dispathching mechanism.
 * The mechanism allows a single handler that returns a value, or an event stack.
 * The mechanism has an error capturing mechanism that directs them to log.
 *
 * @CodeSampleStart
 * //Usage:
 * MyEventingClass = Class.create();
 * MyEventingClass.prototype = Object.extend(MyEventingClass.prototype, IEventDispatcher);
 *
 * MyEventingClass.doSomethingThreeTimes = function(i)
 * {
 *	   i = (i)?i:0;
 
 *     this.dispatch("onSomething",i);
 *     this.dispatch("onSomething",i + 1, i);
 *     this.r = this.dispatch("onSomething",i + 2, i + 1, i);
 *	   this.dispatch("onFinish", this.r);
 * }
 * //example 1:
 * obj = new MyEventingClass();
 * obj.onSomething = function(){
 *	  alert(arguments.toString());
 *    return arguments[2];
 * }
 * obj.onFinish = function(result){
 *    if(0 == result % 2 )
 *		this.r += 1;
 *
 *	  alert("finishing with : "  + this.r);
 * }
 * obj.doSomethingThreeTimes( 23 );
 *
 * //example 2:
 * obj = new MyEventingClass();
 * obj.attachEvent("onSomething", function(){ alert("handler 1: " + arguments.toString());} );
 * obj.attachEvent("onSomething", function(){ alert("handler 2: " + arguments.toString());} );
 *
 * obj.doSomethingThreeTimes( 23 );
 * @CodeSampleEnd
 */

IEventDispatcher = {};

/**
 * Accept the event name as the first parameter, and dispatches it with the rest of the arguments stack.
 * Check for a registered event handler. 
 * A handler could be a simple handler, or a handlers-stack.
 * When the event has a single handler  it can return value.
 *
 * Execution flow:
 * When no event handler is found - nothing is done, and null is returned.
 * When event handler is found -
 * 1 - convert all arguments without the event name to a new array
 * 2 - execute the handler with all the arguments on the new array
 * 3 - when an event returns a value - it returns it.
 *
 * Throws: when the execution of the handler throws, what the handler thew.
 *
 * When the dispatched object features a Log4Js.Logger, 
 * the following log entries are written on the objects logger:
 *   - [info] no event handler is found
 *	 - [info] success of the dispathed event, 
 *	 - [error] error on execution of the event handler, 
 *
 * TODO: allow the event be not only a hanler but a handlers array too
 *
 * @param {string} sEventName
 * The name of the hadler-reference property
 *
 * @param {*} arguments[1],arguments[2],arguments[3]...
 * The arguments for the event handler
 */
IEventDispatcher.dispatch = function(sEventName/*, param1, param2, param3 ... */)
{
	Claim.isString(sEventName, "IEventDispatcher.dispatch(sEventName, ...) - sEventName must be a string"  );
	
	//check for a registered event handler
	var fEventHandler  = this[sEventName];
	var isHandlerStack =	'object' == typeof( fEventHandler ) 
						&&	fEventHandler.constructor == Array;
	
	
	if	(  'function' != typeof( fEventHandler ) && !isHandlerStack )
	{
		if(this.log instanceof Log4Js.Logger) this.log.info("Dispatch: Event " + sEventName + " is not implemented.");
		return;
	}

	//when event handler is found - convert all arguments without the event name to a new array
	var args = [];
	for(var i=1; i < arguments.length; i++) 
	{
		args[i-1] = arguments[i];
	}

	// if the found handler is an event-stack - dispatch all of them, and there is no returned value.		
	if ( isHandlerStack )
	{
		this.log.info("detected handlers stack for event: " + sEventName);
		for(var i = 0; i < fEventHandler.length; i++)
		{
			this.dispatchHandler(sEventName, fEventHandler[i], args);			
		}
		return;
	}

	// if the found handler is a single function-reference - dispatch it, and there is no returned value.
	return this.dispatchHandler(sEventName, fEventHandler, args);			
}
/**
 * @private
 * applies the provided handler on the current instance, with the provided argument-stack
 * Errors and exceptions buble up, however, before that, if the current instance has a this.log as Log4Js.Logger - they are written to that log.
 *
 * @param {function} fEventHandler
 * The function-reference to apply on the current instance
 *
 * @param {object} args
 * The arguments stack of the function * 
 */
IEventDispatcher.dispatchHandler = function(sEventName, fEventHandler, args)
{
	// execute the handler with all the rest of the arguments
	try
	{
		var retVal = fEventHandler.apply(this, args );
		if(this.log instanceof Log4Js.Logger) this.log.info("after event " +sEventName+ ": " + Object.serialize(args) + ". returned value: " + retVal);
		return retVal;
	}
	catch(ex)
	{
		if(this.log instanceof Log4Js.Logger) this.log.error("event " + sEventName + " failed:" + Object.serialize(ex) );
		if(this.ignoreEventErrors == true) return;
		throw ex;
	}	
}

/**
 * attaches the hanlder to the named event, using an event stack.
 * The IEventDispatcher.dispatch knows to recognize this, and 
 * applies the event stack by its registration order (LIFO).
 * 
 * @param {string} sEventName
 * The name of the event
 *
 * @param {function} fHandler
 * The handler function
 */
IEventDispatcher.attachEvent = function(sEventName, fHandler)
{
	Claim.isString(sEventName, "IEventDispatcher.attachEvent(sEventName,..) - sEventName is expected to be a string representing the event name");
	Claim.isFunction(fHandler, "IEventDispatcher.attachEvent(...,fHandler) - fHandler is expected to be the event handler function");
	var oEvent = this[sEventName];
	
	if(oEvent === undefined || oEvent === null)
	{
		this[sEventName] = fHandler;
		return;
	}
	
	switch( typeof( oEvent ) )
	{
		case 'function':
			oEvent = this[sEventName] = [ this[sEventName] ];
			/* !!no break!! deliberate case sliding. */
		case 'object':
			if (oEvent instanceof Array)
			{
				this[sEventName][this[sEventName].length] = fHandler;
				return;
			}
		
		default: //string, boolean, number, objects, and so on...
			sEventName += " is not an event, but: " + Object.serialize( oEvent ); 
			this.log.error(sEventName);
			throw new Error(sEventName);
	}
}

/**
 * @namespace TC.Controls
 *
 */
TC.Controls = {}
/**
 * @private
 * @returns a RegExp instance to execute a search of a simple containing tag in an HTML string
 *
 * @param {string} sTagName
 * The name of the simple containinig tag to find
 */
TC.Controls.tagRegExpFinder = function(sTagName)
{
	return new RegExp( "\<" + sTagName + "\>([\\w\\W]*)\<\/" + sTagName + "\>" , "gi" );
}
/**
 * @returns the HTML contained by the specified tag.
 * The tag has to be simple, means - with no attributes or spaces between its tringular braces.
 *
 * @param {string} sHTMLString
 * The HTML string to be searched in
 *
 * @param {string} sInnerTag
 * The tag containing the text to extract from the big HTML string
 */
TC.Controls.getInnerTag = function(sHTMLString, sInnerTag)
{
	try
	{
		return this.tagRegExpFinder(sInnerTag).exec( sHTMLString )[1];
	}
	catch(ex)
	{
		return null;
	}
}
/**
 * @class TC.Controls.Repeater
 * 
 *
 */
TC.Controls.Repeater = Class.create();
TC.Controls.Repeater = Class.enhance(TC.Controls.Repeater, IEventDispatcher);
/**
 * mapping of tag-names to template elements
 *
 */
TC.Controls.Repeater.defaultParseTags =	{ header		: "header"
										, item			: "item"
										, alternateItem : "alternate"	
										, seperator		: "seperator"
										, footer		: "footer"
										, noData		: "noData"
										};
/**
 * @constructor
 *
 * @param {string} sTemplateString
 *
 * @param {Log4Js.Logger(optional)} oLog
 *
 * @param {object(optional)} oParseTags
 *
 */
TC.Controls.Repeater.prototype.initialize = function( sTemplateString , oLog, oParseTags)
{
	this.log = (oLog && oLog instanceof Log4Js.Logger)? oLog : new Log4Js.Logger("Repeater");

	Claim.isString(sTemplateString, "sTemplateString is expected to be the template HTML string");
	this.templateString = sTemplateString;

	if(!oParseTags)
		oParseTags = Object.clone(this.constructor.defaultParseTags);
	else
		oParseTags = Object.extend( Object.clone(this.constructor.defaultParseTags), oParseTags);
	
	this.dispatch("onInit", oParseTags);
	
	this.templates = {};
	var each;
	for(each in oParseTags)
	{
		this.templates[each] = TC.Controls.getInnerTag( this.templateString, oParseTags[each] ) || "";
		this.log.debug( each + "-template:" + this.templates[each].replace(/</g, "&lt;"));
	}

	this.dispatch("onLoad");
}
/**
 *
 *
 */
TC.Controls.Repeater.prototype.dataBind = function(oMapping, oDataSource)
{
	if( oDataSource ) this.dataSource = oDataSource;
	if( oMapping ) this.bindMapping = oMapping;

	Claim.isLiveObject(this.bindMapping, "Mapping must be an object. Ither provide it as a first argument, or set the property: rpt.mapping");
	Claim.isArray( this.dataSource, "DataSource must be an array. Ither provide it as a second argument, or set the property: rpt.dataSource");
	var i, iIndex, arrBoundItems = [];
	
	this.dispatch("onDataBind", this.dataSource );
	
	for(i = 0; i < oDataSource.length; i++ )
	{
		iIndex = arrBoundItems.length;
		var item =  { dataItemIndex	: i
					, itemIndex		: iIndex
					, dataItem		: oDataSource[i]
					, template		: (this.templates.alternateItem && iIndex % 2) ? this.templates.alternateItem : this.templates.item
					, mapping		: Object.clone( this.bindMapping )
					, skipItem		: false
					}
		
		this.dispatch("onItemDataBound", item);
		if (true == item.skipItem)
			continue;
		
		arrBoundItems[arrBoundItems.length] = item.template.bindTemplate(item.mapping, item.dataItem);
	}
	
	this.content =  {header   : this.templates.header
					,seperator: this.templates.seperator
					,footer   : this.templates.footer
					,items    : arrBoundItems
					,noData   : this.templates.noData
					,toString :	function()
								{
									return this.header 
										 + ( (this.items.length)?
											 this.items.join(this.seperator) : this.noData 
										   )
										 + this.footer;
		  						}
					};

	if(0 == this.content.items.length)
	{
		this.dispatch("onNoDataFound");
	}
	
	this.dispatch("onDataBound", this.content);
	
	return this.content;
}
/**
 *
 *
 */
TC.Controls.Repeater.prototype.render = function(oTargetElement, oMapping, oDataSource){
	this.log.debug("Repeater - rendering");
	if(oTargetElement !== null) Claim.isObject(oTargetElement, "oTargetElement can be an HTML element or the document object, or null");
	
	if (  !this.content 
	   || oMapping && oDataSource ) 
		 this.content = this.dataBind(oMapping, oDataSource);
	
	this.targetElement = oTargetElement;

	this.dispatch("onRender", this.content);
	
	var strHTML = this.content.toString();
	if( oTargetElement)
	{
		if( oTargetElement.write === document.write )
		{
			oTargetElement.write( strHTML );
		}else{
			Element.setText( oTargetElement, strHTML );
		}
	}

	this.log.info("Repeater - render complete");
	return strHTML;	
}

/**
 * Adds the specified url to the favorites list of IE or to the bookmark of Mozilla/Firefox
 * @param {string} url
 * the url to add to the favorites list of the cross-browser
 * @param {string} displayName
 * the display text of the url
 */
TC.AddFavorite = function(url, displayName){
	
	if(window.external){/* IE */
		window.external.AddFavorite( url, displayName); 
	}else if(window.sidebar){ /* Mozilla */
		window.sidebar.addPanel(displayName,url,"");
	}
}


if(!window.UI) UI = {};
if(!UI.Avatar) UI.Avatar = {};
/**
 *
 * enum for avatar sizes
 */
UI.Avatar.Size = {};
UI.Avatar.Size.Studio		= {						  name:"Studio"};
UI.Avatar.Size.Size150x200	= {width:150, height:200, name:"Size150x200" };
UI.Avatar.Size.Size124x165	= {width:124, height:165, name:"Size124x165" }; 
UI.Avatar.Size.Size86x115	= {width:86 , height:115, name:"Size86x115"  };
UI.Avatar.Size.Size98x131	= {width:98 , height:131, name:"Size98x131"  };
UI.Avatar.Size.Size65x87	= {width:65 , height:87 , name:"Size65x87"   };
UI.Avatar.Size.Size24x24	= {width:24 , height:24 , name:"Size24x24"   };  
UI.Avatar.Size.Size48x48	= {width:48 , height:48 , name:"Size48x48"   };  

/****************** TC.Utils.js - End *********************/

TC.OnlinePlayers.settings.onlinePlayersUnavailable = '0';
 UI.Avatar.Size.Size24x24.showTypes = '~glasses~hair~face~skull~shirt~beard~body~jewelry~hats~';
/******************combobox.js - Start *********************/

var Combobox = {

	// Variables and Constants ----------------------------------------------------------------------------------------------------

	comboboxClosed					: true,
	closingTimeout					: null,
	lastDropdownOptionObjMouseOver	: null,

	// ----------------------------------------------------------------------------------------------------------------------------
	

	ComboboxMouseOver				: function ()
										{
											this.ClearTimeoutForComboboxClosing();
										},
										
	ComboboxMouseOut				: function ()
										{
											this.SetTimeoutForComboboxClosing();
										},

	ComboboxMouseDown				: function ()
										{
											if (this.comboboxClosed) this.OpenCombobox();
											else this.CloseCombobox();
										},

	DropdownMouseOver				: function ()
										{
											this.ClearTimeoutForComboboxClosing();
										},
										
	DropdownMouseOut				: function ()
										{
											this.SetTimeoutForComboboxClosing();
										},

	DropdownOptionMouseOver			: function (tdObj)
										{
											tdObj.className = "comboboxDropdownOptionMouseOver";
											this.lastDropdownOptionObjMouseOver = tdObj;
										},
	
	DropdownOptionMouseOut			: function (tdObj)
										{
											tdObj.className = "comboboxDropdownOption";
										},
	
	DropdownOptionClick				: function (tdObj)
										{	
											var optionValue = tdObj.getAttribute('optionValue');
											var optionText = tdObj.innerHTML;
											var comboboxObj;
											if (comboboxObj = document.getElementById("combobox"))
											{
												comboboxObj.setAttribute('optionValue',optionValue);
												comboboxObj.getElementsByTagName('TD')[0].innerHTML = optionText;
											}
											try{
												this.onValueSelected(optionValue);
											}catch(ex){												
											}
												
											this.CloseCombobox();
										},
										
	onValueSelected					: function () 
										{	
											//Expected to be overriden by project
										},
	GetChosenValue					: function ()
										{
											var objCombobox;
											if ( objCombobox = document.getElementById("combobox") )
											{
												return objCombobox.getAttribute('optionValue');
											}
											else return null;
										},
										
	SetTimeoutForComboboxClosing	: function ()
										{
											this.closingTimeout = setTimeout("Combobox.CloseCombobox()",200);
										},
										
	ClearTimeoutForComboboxClosing	: function ()
										{
											if (this.closingTimeout) clearTimeout(this.closingTimeout);
										},
										
	OpenCombobox					: function ()
										{
											var objCombobox, objDropdown;
											if ( (objCombobox = document.getElementById("combobox")) && (objDropdown = document.getElementById("comboboxDropdown")) )
											{
												objDropdown.style.display = "block";
												var comboboxWidth = this.getObjWidth(objCombobox);
												var comboboxHeight = this.getObjHeight(objCombobox);
												var comboboxPosX = 0//this.findObjPosX(objCombobox);
												var comboboxPosY = 0//this.findObjPosY(objCombobox);
												objDropdown.style.width = comboboxWidth;
												var dropdownWidth = this.getObjWidth(objDropdown);
												
												var positionX = comboboxPosX;
												var positionY = comboboxPosY + comboboxHeight - 1;

												objDropdown.style.left = positionX;
												objDropdown.style.top = positionY;

												setTimeout("document.getElementById('comboboxDropdown').style.visibility = 'visible'", 10);
												this.comboboxClosed = false;
											}
										},

	CloseCombobox					: function ()
										{
											var objDropdown;
											if ( objDropdown = document.getElementById("comboboxDropdown") )
											{
												this.comboboxClosed = true;
												objDropdown.style.display = "none";
												objDropdown.style.visibility = "hidden";
												objDropdown.style.top = 0;
												objDropdown.style.left = 0;
												if (this.lastDropdownOptionObjMouseOver) this.lastDropdownOptionObjMouseOver.className = "comboboxDropdownOption";
											}
										},
										
	findObjPosX						: function (obj)
										{
											var curleft = 0;
											do{
												if (obj.tagName.toLowerCase() == 'div')
												{
													curleft -= obj.scrollLeft;
													if (obj.id && obj.id == "mainWorkplaceContainerDiv") break;
												}
												curleft += obj.offsetLeft;
											}while (obj = obj.offsetParent)
											return curleft;
										},

	findObjPosY						: function (obj)
										{
											var curtop = 0;
											do{
												if (obj.tagName.toLowerCase() == 'div')
												{
													 curtop -= obj.scrollTop;
													if (obj.id && obj.id == "mainWorkplaceContainerDiv") break;
												}
												curtop += obj.offsetTop;
											}while (obj = obj.offsetParent)
											return curtop;
										},

	getObjWidth						: function (obj) { return obj.offsetWidth; },
	
	getObjHeight					: function (obj) { return obj.offsetHeight; },
	writeOptionsList				: function (arrOptionsList,sOptionCssClass,sSeperatorCssClass) 
										{
											var oOptData;
											var sOptTemplate = this.UI.optionsListOptionTemplate.replace("OPTION_CSS",sOptionCssClass)
											var HTML = [];
											HTML[HTML.length] = '<table width="100%" border="0" cellspacing="0" cellpadding="0">';
											for(var i = 0; i < arrOptionsList.length ; i++){
												oOptData = arrOptionsList[i];
												HTML[HTML.length] = sOptTemplate.replace("OPTION_VALUE",oOptData.value).replace("OPTION_TEXT",oOptData.text);
											}
											HTML[HTML.length] = '</table>';
											document.write(HTML.join(this.UI.optionsListSeperator.replace("SEPERATOR_CSS",sSeperatorCssClass)));
										},
	UI								:	{
											 optionsListSeperator		: '<tr><td class="SEPERATOR_CSS"><div class="divSpacer">&nbsp;</div></td></tr>',
											 optionsListOptionTemplate	: '<tr><td class="OPTION_CSS" optionValue="OPTION_VALUE" onmouseover="Combobox.DropdownOptionMouseOver(this)" onmouseout="Combobox.DropdownOptionMouseOut(this)" onclick="Combobox.DropdownOptionClick(this)">OPTION_TEXT</td></tr>'
										}
}	

	

/******************combobox.js - End *********************/
/******************UserMedals.js - Start *********************/
//-------------------------------------------------------
/** 
 *  TC = Type C namespace
 */
if(window["TC"] == null){
	TC = {};
}
//-------------------------------------------------------
TC.UserMedals = Class.create();
/**
 * Normal  Ranking: 0 = best 1 = last
 * Reverse Ranking: 1 = best 0 = last
 **/
TC.UserMedals.reverseRanking = true;
/**
 * Array of all medal-levels
 **/
TC.UserMedals.All = [];
/**
 * adds a new ranking level
 *
 * @param {double} sImg
 * a number between 0 to 1 that ranks level of users in comparison to 
 * thier community
 *
 * @param {string} sImg
 * Relative path to the user-medal image
 **/
TC.UserMedals.addRankingLevel = function(dblRanking, sImg){
	var oLevel = new TC.UserMedals(dblRanking, sImg)
	this.All[this.All.length] = oLevel;
	this.All.sort();
}
/**
 * Returns the Ranking Level by the user ranking
 *
 * @param {double} dblRanking
 * The ranking of the user
 **/
TC.UserMedals.getMedalByRanking = function(dblRanking){
	var i;

	if (this.reverseRanking)
	    dblRanking = 1 - dblRanking;

	for(i = 0; i < this.All.length; i++)
		if (dblRanking <= this.All[i].ranking)
			return this.All[i];
}
/**
 *@private
 * Constructor of Ranking-Level object
 *
 * @param {double} dblRanking
 * @param {string} sImg
 * The ranking of the user
 **/
TC.UserMedals.prototype.initialize = function(dblRanking, sImg){
	this.img = sImg;
	this.ranking = dblRanking;
}
/**
 * @private
 * override of  Object.toString(), for the Array.sort()
 **/
TC.UserMedals.prototype.toString = function(){
	return this.ranking;
}
/**
 * MpRanking class stores the images of the ranking levels for the mp
 **/
TC.MpRanking = Class.create();
/**
 * Array of all ranking-levels
 **/
TC.MpRanking.All = [];
/**
 * Holds the maximum upper bound for the ranking (2000+)
 */
TC.MpRanking.MaximumRanking = {};
/**
 *@private
 * Constructor of Ranking-Level object
 *
 * @param {integer} score
 * @param {string} image
 * The ranking of the user
 **/
TC.MpRanking.prototype.initialize = function(score, image){
	this.score = score;
	this.image = image;
}
/**
 * adds a new ranking level for multiplayer game
 *
 * @param {integer} score
 * @param {string} image
 **/
TC.MpRanking.addRankingLevel = function(score, image){
	var oLevel = new TC.MpRanking(score,image);
	this.All[this.All.length] = oLevel;
}
/**
 * adds a the upper bound ranking level for multiplayer game
 *
 * @param {integer} score
 * @param {string} image
 **/
TC.MpRanking.addMaximumRankingLevel = function(score, image){
	this.MaximumRanking = new TC.MpRanking(score,image);
}
/**
 * Returns the Ranking Level by the user score
 *
 * @param {integer} score
 * The ranking of the user
 **/
TC.MpRanking.getMpRankingByScore = function(score){
	for(var i=0;i<this.All.length;i++){
		if(score<=this.All[i].score)
			return this.All[i];
	}
	if(this.MaximumRanking && score>=this.MaximumRanking.score)
		return this.MaximumRanking;
	return null;	
}

/******************UserMedals.js - End *********************/
/******************ClientMgr.js - Start *********************/
/**
 * General Constants
 */
if(!window.Const) Const = {};
Object.extend(	Const,	
				{	UNSET_STRING: "-UNSET-STRING-"
				}
			 );

/**
 * ElementsGroup - a group of HTML elements distincted in the program by a provided 
 * name that may be different from thier Html-Element ID.
 * The elements are gathered on the this.elements collection, while the element IDs 
 * are in this.elementIDs.
 * 
 * It features:
 *  - managment of elements by logical names
 *  - show and hide elements 
 *  - onload events stack executed on window.onload
 */
ElementsGroup = Class.create();
/**
 * The constructor expects a dictionary, pointing every element's programatic name 
 * to its ID on the screen.
 * The constructor scheduels a task for the window's load event, and once the HTML 
 * document is loaded, it parses the provided dictionary, and obtains references to 
 * all specified elements.
 * Missing elements are reported in the log in WARN level.
 * 
 * @param {string}	p_screenElementsDictionary
 *  dictionary of program-names as keys, and HTML element-ids as values.
 *
 * @param {string(optional)}  sInstanceName
 *  The name of the ClientMgr instance (usually a singletone utilities class)
 *  used for the Log4Js.Logger and for on-the-fly creation of an onload function
 *  - Optional: when not provided, a random unique identifier is generated for internal use.
 */
ElementsGroup.prototype.initialize = function(p_elementsDictionary, sInstanceName)
{
	//default sInstanceName - for "anonymous"
	if(!sInstanceName) sInstanceName = "ElementsGroup" + ((new Date()).getTime() + "_" + Math.random()).replace(".","_");
	
	ElementsGroup.all[ElementsGroup.all.length] = this;
	if(parseInt(sInstanceName) != Number(sInstanceName))
	{
		 ElementsGroup.all[sInstanceName] = this;
	}

	this.log = new Log4Js.Logger(sInstanceName);
	this.instanceName = sInstanceName;
	this.elements = {};
	this.elementIDs = {};
	
	//prepare to and attach its onload
	this.prv_constructorTmpDictionary = p_elementsDictionary;
	this.onLoadHandlers = [ function() 
							{
								var oConstrDictionary = this.prv_constructorTmpDictionary;
								delete this.prv_constructorTmpDictionary;

								var anythingInDictionary;
								for(anythingInDictionary in oConstrDictionary) break;		
								if(anythingInDictionary)
								{	
									this.setElementIDs(oConstrDictionary);	
								}
							}
						  ];
}
/**
 * @private
 * A dictionary of all element-groups, named by thier provided instance name
 */
ElementsGroup.all = [];
/**
 * adds new or overrides an existing element to the 
 * this.elements and this.elementIDs dictionaries
 *
 * @param {string} sElementName
 *  Name of the element in the program
 *
 * @param {string} sElementID
 *  projectal HTML element ID of the element
 */	
ElementsGroup.prototype.setElementID = function(sElementName, sElementID)
{
	this.elementIDs[sElementName] = sElementID;
	this.elements[sElementName] = $(sElementID);
} 
/**
 * adds or overrides managed elements names and thier HTML ids in the elementIDs dictionary
 *
 * @param {object} p_screenElementsDictionary
 *  a dictionary of the managed element names as keys, and thier HTML element-ids as values.
 */
ElementsGroup.prototype.setElementIDs = function(p_elementsDictionary)
{
	//if the preload has not occuded yet - add it to the constructor dictionary
	if(this.prv_constructorTmpDictionary)
	{
		Object.extend(this.prv_constructorTmpDictionary, p_elementsDictionary);
		return;
	}
	var element;
	for(element in p_elementsDictionary)
	{
		this.setElementID(element, p_elementsDictionary[element]);
	}
}
/**
 * @private
 *
 * @param {string} sElementName
 *	the name of the element in the program
 *
 * @param {string} sCallerInstance
 * the caller function (for logging}
 * - optional : Default value: "[ClientMgr].getMyElement(...)"
 */
ElementsGroup.prototype.getMyElement = function(sElementName, sCallerInstance)
{	//default sCallerInstance
	if(!sCallerInstance) sCallerInstance = "[ElementsGroup].getMyElement(...)";
	
	//first - check the this.elements collection
	if(this.elements[sElementName]){
		return this.elements[sElementName];
	}
	this.log.info(sCallerInstance + " doesn't have " + sCallerInstance + ".elements." + sElementName);
	
	//get managed element ID
	var sElementID = this.elementIDs[sElementName];
	if(sElementID == null){ 		
		this.log.warn(sCallerInstance + " was asked to show an unknown element: " + sElementName);
		return;
	}
	//get element
	var oElement = $(sElementID);
	if(oElement == null){
		this.log.warn(sCallerInstance + " was asked to show an element that does not exist: " + sElementID);
		return;
	}
	
	return oElement;
}
/**
 * shows a managed element by its logical name in the program.
 *
 * @param {string} sElementName
 *  the name of the element in the program
 */
ElementsGroup.prototype.showElement = function(sElementName,displayVal)
{
	
	var e = this.getMyElement(sElementName, "showElement");
	if(!e) return;
	if(displayVal==null)
		displayVal="block";
	e.style.display = displayVal;
	
}
/**
 * hides a managed element by its logical name in the program.
 *
 * @param {string} sElementName
 *  the name of the element in the program
 */
ElementsGroup.prototype.hideElement = function(sElementName)
{
	var e = this.getMyElement(sElementName, "hideElement");
	if(!e) return;
	e.style.display = "none";
}
/**
 * API to add handlers to the onload events
 *
 * @param {function} fHandler
 * A handler to dispatch from window.onload
 */
ElementsGroup.prototype.addOnLoadHandler = function(fHandler)
{
	Claim.isFunction(fHandler,"[ElementsGroup].addOnloadHandler(fHandler) - fHandler must be a function");
	this.onLoadHandlers[this.onLoadHandlers.length] = fHandler;
}
/**
 * @private
 * Used in on-the-fly generated functions, attached to the window.onload event.
 * The goal of this function is to allow sub-classes to have window.onload event 
 * listenerss of thier own, and assure the execution sequence of the event handlers
 * between events of the parent and events of the subclass.
 * The first listener that is registered in the constructor is 
 * ElementsGroup.prv_onLoad_handler_ref
 */
ElementsGroup.prototype.prv_onPageLoad = function()
{
	var i;
	for(i = 0; i < this.onLoadHandlers.length; i++){
		this.onLoadHandlers[i].call(this);
	}
}
/**
 * @private
 * static behavior, called from a function attached to Window.onload
 * dispatches onPageLoad to all instances
 */
ElementsGroup.prv_observeWindowLoad_callback = function()
{
	for(var i = 0; i <  this.all.length; i++)
	{
		this.all[i].prv_onPageLoad();
	}
}

// Call onPageLoad on all instances created untill page-load event
Event.observe(	window
			 ,  "load" 	
			 , function(){
				  ElementsGroup.prv_observeWindowLoad_callback();
			   }
			 );


//============================================================
/**
 * LayersGroup is an ElementGroup that all its layers share the same screen space, 
 * hence, a single layer is visible at a time, or non at all.
 */
LayersGroup = Class.create( "ElementsGroup" );
/**
 *
 */
LayersGroup.prototype.initialize = function(p_screenElementsDictionary, sInstanceName)
{
	this.layersIDs = this.elementsIDs;
	this.layers = this.elements;
}
/**
 *
 */
LayersGroup.prototype.hideAll = function()
{
	var each;
	for(each in this.elementIDs){
		this.hideElement(each);
	}
}
/**
 *
 */
LayersGroup.prototype.showLayer = function(sLayerName)
{
	this.hideAll();
	this.showElement(sLayerName);
}
//==============================================
/**
 * ClientMgr - class for managing client-side UI.
 * Features utilities for:
 *  - post/get/redirections
 *  - show/hide HTML elements
 *
 * @param {string}  sInstanceName
 *  The name of the ClientMgr instance (usually a singletone utilities class)
 *  used for the Log4Js.Logger and for on-the-fly creation of an onload function
 * 
 * @param {string}	p_screenElementsDictionary
 *  dictionary of program-names as keys, and HTML element-ids as values.
 */
ClientMgr = Class.create("ElementsGroup");
ClientMgr.prototype.initialize = function(p_globalElementsDictionary, sInstanceName)
{
	//init the current URL
	var sUrl = location.href;
	//PATCH: - remove #anchor - overcome a bug of the infrastructure
	i =	sUrl.lastIndexOf("#");
	if(   i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=") )
	{
		sUrl = sUrl.substr(0,i);
	}		
	
	this.Url = Url.parse(sUrl);
	
	//windows collection
	this.windows = {};
	this.templates = {};
	//infra for close all windows in unload
	this.onPageUnloadHandlers = [ ClientMgr.onPageUnload_handler_ref ];
	Event.observe(	window
				 ,	"unload"
				 ,	new Function( "try{\n\t" 
								+	 this.instanceName + ".onPageUnload();\n"
								+ "}catch(ex){\n\t" 
								+	"(new Log4Js.Logger('" + this.instanceName + "')).error('Error or Exception in " + this.instanceName + ".onPageUnload(): ' + (ex.description)?ex.description:ex );\n" 
								+ "}"
								)
				 );
}
 //===============================================
//---- PAGE NAVIGATION AND WINDOWS MANAGMENT ----
/**
 * @private
 * This is a dictionary for name in the program as key, and page-settings dictionary as values
 * for windows the managed page uses.
 * each window settings can contain URL and winSettings in case its used in a window.
 * This collection is managed by the API: 
 *	- ClientMgr.prototype.addManagedPage(...) 
 */
ClientMgr.prototype.pages = {};
/**
 * Adds deffinition for a page in the managed window-deffinitions collection.
 *
 * @param {string} sName
 *  the name of the page in the program
 *
 * @param {string} sUrl
 *  the Url of the page
 *
 * @param {string(optional)} sWinSettings
 * - optional: when not provided - the page does not open in a window, 
 * but replaces the current page
  */
ClientMgr.prototype.addManagedPage = function(sName, sUrl, sWinSettings)
{
	this.pages[sName] = { URL: sUrl
						, winSettings: sWinSettings
						};
}
/**
 * Usefull for:
 * - send the page to _top without conflicting IFrames security.
 * - Submit a form to a provided URL with the provided parameters and form settings.
 *
 * @param {object|string} oFormAttributes
 *  a key-value dictionary of form HTML attributes to be used to add or override to the default settings.
 *  When the parameter is provided as string - it is assumed to be the 
 *  'action' attribute, and the rest of the settings are taken from the default settings.
 *  Default settings: 
 *			- target = "_top"
 *			- method = if oAdditionalParams is provided - "POST", otherwise - "GET"
 *			- action = when oFormAttributes is provided as string
 * 
 * @param {object} oAdditionalParams
 *	a key-value dictionary of required query-string parametes.
 *  when an argument exists both in oParameters and in the sUrl 
 *  as query-string parameter - the parameter in sUrl overrides.
 *  - optional : functionality ignored when not provided.
 *  when this parameter is provided, the default form-method is "POST"
 *  otherwise - "GET".
 *
 */
ClientMgr.prototype.submitToPage = 	function go(oFormAttributes, oAdditionalParams)
{
	if(typeof(oFormAttributes) == 'string'){
		this.log.debug("ClientMgr.submitToPage got 'oFormAttributes' as string, assumed to be the oFormAttributes.action");
		oFormAttributes = {action: oFormAttributes };
	}
	else
	{
		if(oFormAttributes.URL && !oFormAttributes.action)
			oFormAttributes.action = oFormAttributes.URL;
		Claim.isString(	oFormAttributes.action, "..submitToPage(oFormAttributes.action)");
	}
	
	//PATCH: - remove #anchor - overcome a bug of the infrastructure
	var sUrl = oFormAttributes.action;
	i =	sUrl.lastIndexOf("#");
	if(   i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=") )
	{
		sUrl = sUrl.substr(0,i);
	}
	
	var oUrl = Url.parse(sUrl);
	oFormAttributes.action = oUrl.base;
	// use default settings for all settings not in oFormAttributes
	if(null == oFormAttributes.target) oFormAttributes.target = "_top";
	if(null == oFormAttributes.method) oFormAttributes.method = (oAdditionalParams != null)? "POST" : "GET";

	//copy all settings to a newly created <FORM>
	var f = Object.extend(	document.createElement("FORM")
						 ,	oFormAttributes
						 );
	//copy all parameters found in action URL to oAdditionalParams
	if(oAdditionalParams == null) oAdditionalParams = {};
	var oParams = Object.extend(oAdditionalParams, oUrl.params)

	//populate <FORM> with all fields found
	var e, paramName;
	for(paramName in oParams){
		if(paramName == "") continue;
		
		e =	Object.extend(	document.createElement("INPUT")
						 ,  {  type : "hidden"
							,  name : paramName
							,  value: oParams[paramName]
							} 
						 );
		f.appendChild(e);
	}

	//append and submit
	document.body.appendChild(f)
	f.submit();
}

/**
 * @private
 *  parses window settings string (as passed to window.open)
 *
 * @param {string} sSettings
 */
ClientMgr.prototype.prv_parseWindowSettingsString = function(sSettings){
    if(!sSettings) return;
    Claim.isString(sSettings, "prv_parseWindowSettingsString(sSettings)");
    
    sSettings = sSettings.split(",");
    var oProps = {};
    for(var i = 0 ; i < sSettings.length; i++){
        try{
            sSettings[i] = sSettings[i].split("=");
            oProps[sSettings[i][0].toLowerCase()] = sSettings[i][1];
        }catch(ex){}
    }
    return oProps;
}
/**
 * Opens a managed window
 * - centalizes all windows to the center of the screen
 * - focuses every opened window
 * - allow supply window name from managed windows or directly a URL
 * - allows page names and windows reuse, and allows anonymous windows
 * - hold a reference to all used windows, so that when the page unloads, all windows can be closed
 *
 * @param {string} sWindowPage
 *  The URL to populate the window with. The Url can contain Query-String parameters
 * 
 * @oParams {object} oQSParams
 *  Parameters for to add to the URL Query-String.
 *  When a parameter appears in the QS of the URL and in the oParams, 
 *  the value in oParams overrides the one in the QS.
 * 
 * 
 */
ClientMgr.prototype.openWindow = function(sWindowPage, oQSParams, sWinID, sDefaultWinSettings)
{
    Claim.isString(sWindowPage, this.instanceName + ".openWindow(sWindowPage) - sWindowPage is expected to be a URL in a string");
    
    if(!oQSParams) oQSParams = {};
    
    if(!sWinID) sWinID = sWindowPage;
    
    //TODO:
    var sUrl;
    if(this.pages[sWindowPage]){
		sUrl = this.pages[sWindowPage].URL;
    }else{
		sUrl = sWindowPage;
		sWindowPage = sWindowPage.replace(/[^A-Z^a-z^0-9]*/g,"_");
    }
    
	//PATCH: - remove #anchor - overcome a bug of the infrastructure
	i =	sUrl.lastIndexOf("#");
	if(   i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=") )
	{
		sUrl = sUrl.substr(0,i);
	}
    
    sUrl = Url.parse(sUrl);
    oQSParams = Object.extend(sUrl.params, oQSParams);    
    delete oQSParams[""];// work around 
    sUrl = Url.appendParams(sUrl.base, oQSParams);

    var sWinSettings;
    if(sDefaultWinSettings){
		sWinSettings = sDefaultWinSettings;
    }else if(this.pages[sWindowPage]) {
		sWinSettings = this.pages[sWindowPage].winSettings;
    }//	else - do nothing...

	if(sWinSettings){
		var oProps = this.prv_parseWindowSettingsString(sWinSettings);
		if(oProps.width && oProps.height){
			var h = parseInt((screen.height - oProps.height) / 2);
			var w = parseInt((screen.width - oProps.width) / 2);
			sWinSettings += ",top=" + h + ",left=" + w;
		}
	}
	    
    if(this.windows[sWinID] && !this.windows[sWinID].closed)
        this.windows[sWinID].close();
    this.windows[sWinID] = window.open(sUrl, sWindowPage, sWinSettings);
}
/**
 * 
 */
ClientMgr.prototype.onPageUnload = function()
{
	var i;
	for(i = 0; i < this.onPageUnloadHandlers.length; i++)
	{
		this.onPageUnloadHandlers[i].call(this);
	}
}
/**
 * @private
 * this is a STATIC member - a handler referece that is attached 
 * dynamicly later to each instance
 */
ClientMgr.onPageUnload_handler_ref = function()
{
	var sWinID;
	for(sWinID in this.windows)
	{
		try{
			this.windows[sWinID].close();
		}catch(e){}
	}
}
//=========================================
//---- DATA_SOURCE-TO-SCREEN UTILITIES ----
ClientMgr.prototype.populateElement = function(sElementID, varValue)
{
	var oElement = $(sElementID);
	if(!oElement){
		this.log.warn("populateElement(..) sElementID specifies and element which does not exist:" + sElementID);
		return;
	}	
	Element.setText(oElement, varValue);
}
/**
 * populates the HTML elements whos IDs are the keys in the parameter oElementsDictionary
 * while thier correlating values are the property-names on the parameter oDataSource.
 *
 * @param {object} oElementsDictionary
 *  dictionary with HTML IDs as keys, and names of properties on oDataSource as values.
 *
 * @param {object} oDataSource
 *  dictionary with property names as keys, and thier fetched data as values.
 */
ClientMgr.prototype.populateElements = function(oElementsDictionary, oDataSource)
{
	Claim.isObject(oElementsDictionary, "[ClientMgr].populateElements(oElementsDictionary)");
	Claim.isObject(oDataSource , "[ClientMgr].populateElements(oDataSource)");
	var each, oElement, value;
	for(each in oElementsDictionary){
		oElement = $(each);
		if(!oElement){
			this.log.warn("populateElements(..) properties-dictionary specifies and element which does not exist:" + each);
			continue;
		}
		value = oDataSource[oElementsDictionary[each]];
		if(null == value){
			this.log.warn("populateElements properties-dictionary askes for a property which does not exist. Element: " + each + ", Property: " + oElementsDictionary[each]);
			continue;
		}
		Element.setText(oElement, value);
	}
}
/**
 * Populates the provided string-template by replacing the placeholders in the sTemplate 
 * with values from the oDataSource. 
 * The searched placeholders and the correlating values are matched according to the 
 * provided oPlaceHoldersAttributesDictionary.
 *
 * @param {string} sTemplate
 *  The template to populate. can be the template istelf as a string, or a template logical name
 *
 * @param {object} oPlaceHoldersAttributes
 *  Dictionary that correlates place-holders in sTemplate as keys, and properties of oDataSource as values.
 *
 * @param {object} oDataSource
 *  Data-Source object
 */
ClientMgr.prototype.populateStringTemplate = function(sTemplate, oPlaceHoldersAttributes, oDataSource)
{
	Claim.isString(sTemplate  , "[ClientMgr].populateStringTemplace(sTemplate,...)");
	Claim.isObject(oPlaceHoldersAttributes, "[ClientMgr].populateStringTemplace(..,oPlaceHoldersAttributes,..)");
	Claim.isObject(oDataSource , "[ClientMgr].populateStringTemplace(..,oDataSource)");


	//The template can be a string, or a template logical name
	if(this.templates[sTemplate])
		sTemplate = this.templates[sTemplate];

	var placehoder, attribute, replacment;
	
	for(placehoder in oPlaceHoldersAttributes)
	{
		attribute = oPlaceHoldersAttributes[placehoder];
		if(null == attribute){
			this.log.warn("in populateStringTemplace(...) oPlaceHoldersAttributes dictionary specifies a placeholder without providing its data-attribute name: " + placehoder);
			continue;
		}
		replacement = oDataSource[attribute];
		if(null == replacement){
			this.log.warn("in populateStringTemplace(...) oPlaceHoldersAttributes dictionary specifies a property that does not exist on the provided oDataSource. Placehoder: " + placehoder +", attribute: " + attribute);
			continue;
		}
		//replacment = replacment.replace(/\$/g,"");
		sTemplate = sTemplate.replace(new RegExp(placehoder,"g"), replacement);
	}
	return sTemplate;
}
ClientMgr.openLink = function (link){
    var wn = window.open(link,'GameCenterMainWindow');
    wn.focus();
}

/******************ClientMgr.js - End *********************/
/******************OnlineShellMgr.js - Start *********************/
OnlineShellMgr = new ClientMgr(	{	chatContainer		: "upChatContainer"
								,	expandChatButton	: "divExpandChat"
								,   userEndGameScore	: "yourScore"
								}
							  , "OnlineShellMgr"
							  );
					  
/**
 * The area of the portlet
 */

OnlineShellMgr.portletArea = new LayersGroup(	{	howToPlay			: "upHowToPlay"
												,	chatPreferences		: "upChatPreferences"
												,	endGameWarning		: "upWarning"
												,	rankingLegend		: "upRankingLegend"
												,	userPortlet			: "divUserPortlet"
												,	chatUserProfile		: "divPlayerProfile"
												}
											,	"portletArea"
											);

// must override this values to the actual values where using the sound/mute funcs
OnlineShellMgr.defaultSoundImageID = "";
OnlineShellMgr.defaultCheckboxID = "";
OnlineShellMgr.defaultSoundImagesNames = ["",""];



/**
* The text colors of the chat activex control
*/											
OnlineShellMgr.chatTextColors = {};
OnlineShellMgr.chatTextColors.colorItems			= 6;
OnlineShellMgr.chatTextColors.holderPrefix			= 'colorItem_';
OnlineShellMgr.chatTextColors.selectedBorderColor	= 'yellow';
OnlineShellMgr.chatTextColors.normalBorderColor		= 'black';
												
/**
 * Managed Pages
 */						
OnlineShellMgr.addManagedPage( "UserMedals", "/Orange2.0/App/MyMedals.aspx", "width=611,height=440,status=no,scrollbars=yes,toolbar=no,menubar=no,location=no,resizeable=no");  							  
OnlineShellMgr.addManagedPage( "HighScore", "/Orange2.0/App/GameHighScore.aspx", "width=611,height=440,status=no,scrollbars=yes,toolbar=no,menubar=no,location=no,resizeable=no");  							  

/* show & hide elements */
//TODO: check if the active-X can suffer a div over it.
//		if not - then when every div is shown the code
//				 must make sure the chat is not expanded.
OnlineShellMgr.classNames = {	chatContainer	: ["upChatMaximized", "upChatMinimized" ]
							,	expandChatButton: ["divChatDown", "divChatUp"]
							};
/**
 * Opens the high-score game
 */
OnlineShellMgr.openGameHighScore = function(iSku)
{
	ProfileMgr.openGameHighScore(iSku);
}
/**
 * Opens the user-games and medals page
 */
OnlineShellMgr.openMyMedals = function()
{ 
	this.openWindow("UserMedals");
}
/**
 * Makes the User-Poprtlet visible
 */
OnlineShellMgr.showUserPortlet		=	function()
{	
	this.collapseChatState();
	this.portletArea.showLayer("userPortlet");
}
/**
 * Shows the chat pereferences layer
 */
OnlineShellMgr.showChatPreferences	=	function()
{ 
    GameCatalog.GameShellMediator.trackChatPreferencesOpened(); 
	this.collapseChatState();
	this.portletArea.showLayer("chatPreferences"); 
}
/**
 * Shows the endGame layer
 */
OnlineShellMgr.showEndGameWarning	=	function()
{	
	this.collapseChatState();
	this.portletArea.showLayer("endGameWarning"	); 
}
/**
 * Shows the how to play layer
 */
OnlineShellMgr.showHowToPlay		=	function()
{
	//GameCatalog.GameShellMediator.trackHowToPlay(); 
		GameCatalog.GameShellMediator.trackErrorMessage();
	this.collapseChatState();
	this.portletArea.showLayer("howToPlay"); 
}
/**
 * Shows the ranking/rating legend layer
 */
OnlineShellMgr.showRankingLegend	=	function()
{	
	this.collapseChatState();
	this.portletArea.showLayer("rankingLegend"); 
	GameCatalog.GameShellMediator.trackRatingLegendOpened(); 
}
/**
 * Shows the user-profile for chat users
 * //init code:
 * OnlineShellMgr.profileByNickEvents = {onDataBound: function() { ... } };
 * //use by flash chat:
 * OnlineShellMgr.showProfileByNick( 'momo' );
 * 
 */
OnlineShellMgr.showProfileByNick = function( sNickname )
{
    GameCatalog.GameShellMediator.trackOtherPlayerProfile(); 

	Claim.isNumber(this.currentGameSku, "OnlineShellMgr.showProfileByNick needs OnlineShellMgr.currentGameSku to be set with the played product-sku-code for this function to work");

	this.collapseChatState();

	this.resetChatUserProfile();
	this.portletArea.showLayer("chatUserProfile");
	
	var cuf = new OnlineShellMgr.ChatUserProfile(/* nickname : */	sNickname
											  ,/* sku :      */ this.currentGameSku)

	Object.extend(cuf, this.profileByNickEvents);					  

	cuf.apply();
}
//--OnlineShellMgr.OtherUser------------------------------------------------------------
	OnlineShellMgr.ChatUserProfile = Class.create("UA.User");
	OnlineShellMgr.ChatUserProfile = Class.enhance(OnlineShellMgr.ChatUserProfile, IEventDispatcher);
	OnlineShellMgr.ChatUserProfile.prototype.initialize = function(sNickname, iSku, enAvatarSize)
	{
		//TODO: claims
		GameCatalog.GameShellMediator.trackOtherPlayerProfile(); 
		
		this.log = new Log4Js.Logger("OnlineShellMgr.ChatUserProfile");
		

		this.nickname = sNickname;
		this.currentGameSku = iSku;
	}
	/**
	 * Fires the GetPersonaDataByNickname request
	 * 
	 */
	OnlineShellMgr.ChatUserProfile.prototype.apply = function()
	{
		//TODO: remove the enAvatarSize parameter
		this.GetPersonaDataByNickname (/* nickname :	*/	this.nickname
									  ,/* enAvatarSize:	*/	""
									  ,/* iSku :		*/	this.currentGameSku
									  ,/* fSuccess :	*/	this.onSuccess
									  ,/* fFailure :	*/	this.onFailureOrTimeout
									  ,/* fTimeout :	*/	this.onFailureOrTimeout
									  );
	}
	/**
	 * Overrides the toString implementation
	 */
	OnlineShellMgr.ChatUserProfile.prototype.toString = function()
	{
		return "[UA.User] extension: ChatUserProfile";
	}
	/**
	 * @private
	 * converts the twiched structure from User-Accounts to the structure expectd 
	 * by populateChatUserProfile.
	 */
	OnlineShellMgr.ChatUserProfile.prototype.onSuccess = function(dataUA)
	{
		this.log.info("OnlineShellMgr.ChatUserProfile.onSuccess - got data: " + Serialize(dataUA));

		data  = { avatar	: dataUA.avatar
				, nickname	: dataUA.nickname
				};
		
		if(dataUA.highestMedal) 
		{
			var oGame = TC.SKUs[dataUA.highestMedal.sku];
			if(oGame) 
			{
				data.userBadge	 =	{	badgeGameSku	: dataUA.highestMedal.sku
									,	score			: dataUA.highestMedal.score
									,	position		: dataUA.highestMedal.position
									,	badgeImgUrl		: TC.UserMedals.getMedalByRanking(dataUA.highestMedal.ranking).img
									,	badgeGameName	: oGame.name
									,	badgeGameUrl	: oGame.gamePageURL
									};
			}
			else
			{	
				data.userBadge  = "ERROR";
				this.log.warn("Can't find game of user medal. Sku: " + dataUA.highestMedal.sku );
			}
		}					
		else
		{
			this.dispatch("onNoBadgeFound", data);
			this.log.info("No user badge found");
		}
		
		if(dataUA.requestedGame)
		{
			data.currentGame =	{	score	 : dataUA.requestedGame.score
								,	position : dataUA.requestedGame.position 
								,	userRanking : dataUA.requestedGame.ranking
								};
		}
		else
		{
			this.dispatch("onNoScoreForCurrentGame", data);
			this.log.info("No score found for the current game. Sku: " + this.currentGameSku);
		}
		
		this.dispatch("onDataBound", data, dataUA);
		
		this.log.info("populating user chat profile with :  " + Serialize(data));
		OnlineShellMgr.populateChatUserProfile(data);
	}



	/**
	 * @private
	 */
	OnlineShellMgr.ChatUserProfile.prototype.onFailureOrTimeout = function(request)
	{
		OnlineShellMgr.setChatUserProfileErrorMsg();
	}
//--/ProfileMgr.OtherUser------------------------------------------------------------
/**
 * Default handler for reseting the chat-user-profile pallete 
 */
OnlineShellMgr.resetChatUserProfile = function()
{
	this.log.error("OnlineShellMgr.resetChatUserProfile is expected to be overwridden in project");
}
/**
 * Default handler for reseting the chat-user-profile pallete with error messages
 */
OnlineShellMgr.setChatUserProfileErrorMsg = function()
{
	this.log.error("OnlineShellMgr.setChatUserProfileErrorMsg is expected to be overwridden in project");
}
/**
 * Default handler for asyncronious call for GetOtherUserProfile
 * 
 * The provided data is expected to contain:
 *	data.nickname
 *  data.avatar
 *  data.userBadge.skuCode
 *  data.userBadge.score
 *  data.userBadge.position
 *	data.currentGame.score
 *	data.currentGame.position
 */
OnlineShellMgr.populateChatUserProfile = function(data)
{
	alert("OnlineShellMgr.populateChatUserProfile was not overriden in project.\n\n Received data: " + Serialize(data) );
}

/**

 * Hides the chat pereferences layer
 */
OnlineShellMgr.hideChatPreferences	=	function()
{
	this.showUserPortlet();
}	
/**
 * Hides the end-game warning layer
 */
OnlineShellMgr.hideEndGameWarning	=	function()
{
	this.showUserPortlet();
}	
/**
 * Hides the ranking/rating legend layer
 */
OnlineShellMgr.hideRankingLegend	=	function()
{
	this.showUserPortlet();
}	
/**
 * Hides the how-to-play layer
 */
OnlineShellMgr.hideHowToPlay		=	function()
{
	this.showUserPortlet();
}	
/**
 * Hides the chat-user profile area
 */
OnlineShellMgr.hideProfileByNick = function( sNickname )
{
	this.showUserPortlet();
}
/**
 * changes the state of the chat (expanded/collapsed)
 * 
 * @param {Element} the element with the onclick on
 */
OnlineShellMgr.changeExpandChatState = function(divButton)
{
	if( divButton.className == this.classNames.expandChatButton[0] )
	{
	//	this.collapseChatState();
	}
	else
	{
		this.expandChatState();
	}
}
/**
 * expands the chat
 */
OnlineShellMgr.expandChatState = function()
{
	if(this.elements.expandChatButton)
		this.elements.expandChatButton.className = this.classNames.expandChatButton[0];
	if(this.elements.chatContainer)			
		this.elements.chatContainer.className	 = this.classNames.chatContainer[0];
	//TODO: interact with active X 
	//alert('TODO: implement activeX height');
}
/**
 * collapses the chat
 */
OnlineShellMgr.collapseChatState = function()
{
	if(this.elements.expandChatButton)
		this.elements.expandChatButton.className = this.classNames.expandChatButton[1];
	if(this.elements.chatContainer)	
		this.elements.chatContainer.className	 = this.classNames.chatContainer[1];
	//TODO: interact with active X 
	//alert('TODO: implement activeX height');
}

OnlineShellMgr.login = function()
{
	this.loginRequest=true;
	OnlineShellMgr.showEndGameWarning();
}
OnlineShellMgr.register = function()
{
	this.registerRequest=true;
	OnlineShellMgr.showEndGameWarning();
}
OnlineShellMgr.continueProc = function(b_closeAfter, obj)
{
	if(b_closeAfter==null)
		b_closeAfter=true;
	if(this.loginRequest){
		ProfileMgr.sendToAdapter("login");
		GameCatalog.GameShellMediator.trackLoginClicked(obj);
	}
	if(this.registerRequest){
		ProfileMgr.sendToAdapter("register");	
		GameCatalog.GameShellMediator.trackCreateAccountClicked(obj);
	}
	if(b_closeAfter){
		// for avoiding the prompt for closing the window
		window.opener=null;
		// now close the current window
		self.close();
	}
}
/*
* the flag indicates to mute or not
*/
OnlineShellMgr.changeSoundState = function(flag)
{
    if(this.sound==null)
        this.sound=true;
    if(flag!=null)
		this.sound=flag;    
    try{    
		ChatSetMuteStatus(this.sound);
		this.sound = !this.sound;
		if(this.updateControls())
			return true;
		return false;	
	}catch(ex){
		this.log.error("could not change the sound status of the game host! Exception: " + Serialize(ex));
		return false;
	}
    
}
OnlineShellMgr.updateControls = function(){
	
	if(!$(this.defaultSoundImageID)){
		this.log.error("the image id of the sound icon is not correct");
		return false;
	}
	if(!$(this.defaultCheckboxID)){
		this.log.error("the checkbox id is not correct");
		return false;
	}
	var strMute  = this.defaultSoundImagesNames[0];
	var strSound = this.defaultSoundImagesNames[1];
	if(!this.sound){
		$(this.defaultSoundImageID).src = $(this.defaultSoundImageID).src.replace(strSound,strMute); 
		
	}else{
		$(this.defaultSoundImageID).src = $(this.defaultSoundImageID).src.replace(strMute,strSound); 
	}
	$(this.defaultCheckboxID).checked = !this.sound;
	return true;
	
}

OnlineShellMgr.chooseChatTextColor = function(index,strColor)
{
	try{
		ChatSetTextColor(strColor);
		// set the border for the selected color item holder
		$(OnlineShellMgr.chatTextColors.holderPrefix+index).style.borderColor = OnlineShellMgr.chatTextColors.selectedBorderColor;
		for(var i=1;i<=OnlineShellMgr.chatTextColors.colorItems;i++){
			if(i!=index)
				$(OnlineShellMgr.chatTextColors.holderPrefix+i).style.borderColor=OnlineShellMgr.chatTextColors.normalBorderColor;
		}
	}catch(ex){
		this.log.error("could not change the text color of the chat control! Exception: " + Serialize(ex));
    }
}

/******************OnlineShellMgr.js - End *********************/
/******************Profile.js - Start *********************/
//Claim.isFunction(ClientMgr,"Missing script reference: /Javascript/ClientMgr.js\n required for Profile.js");
if(!ClientMgr) throw new Error('Missing script reference: src="/Javascript/ClientMgr.js\"n required for Profile.js');

if(!window.Const) Const = {};
Object.extend(	Const,	
				{	UNSET_STRING: "-UNSET-STRING-"
				,	UNSET_NUMBER: NaN	
				}
			 );
/**
 * ProfileMgr
 * 
 * ProfileMgr.sendToAdapter(sCommand)
 * ProfileMgr.sendToProfile()
 * ProfileMgr.openGameHighScore(iSku)
 * ProfileMgr.getUserDetails(p_propsDictionary)
 * ProfileMgr.getAvatar(sHtmlElementID,eAvatarSize,sNoDataFoundHTML,sNotAvailableHTML)
 * ProfileMgr.getGameBestScore(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML)
 * ProfileMgr.getUserBestScore(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
 * ProfileMgr.getUserOnlineGames(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, iMaxShownGames)
 * ProfileMgr.getUserDownloadGames( sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, iMaxShownGames))
 * ProfileMgr.getUserWornBadge(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
 *
 * TODO - ProfileMgr.getInstalledGames(...) - TODO
 */
ProfileMgr = new ClientMgr(	 {}
						  ,	 "ProfileMgr");
/**
 * contains default settings untill the ProfileMgr is initiated.
 * Initiation must contain channel, and authenticationAdapter
 * @type Object
 */
ProfileMgr.settings = 	{}
/**
 * The channel. Its expected to be overide by ProfileMgr.init(settings)
 * @type Number
 */
ProfileMgr.settings.channel = Const.UNSET_NUMBER;
/**
 * The URL for the authentication adapter
 * Its expected to be overide by ProfileMgr.init(settings)
 * @type String
 */
ProfileMgr.settings.authenticationAdapter =	Const.UNSET_STRING;
/**
 * The URL of the page that the redirection to the profile sends to
 * @type string
 */
ProfileMgr.settings.userProfile = "/Profile/ProfileSummary.aspx";
/**
 * The size of the avatar in the page the ProfileMgr runs in
 * @type UA.User.Avatar
 */
ProfileMgr.settings.avatarSize = "Size150x200";
/**
 *
 */
ProfileMgr.settings.loginTarget = "_top";
/**
 * A general handler for Failure on asynchronous calls from ProfileMgr
 * @type Function
 */
ProfileMgr.settings.onProfileCallFailure = null;
/**
 * A general handler for Timeout on asynchronous calls from ProfileMgr
 * @type Function
 */
ProfileMgr.settings.onProfileCallTimeout = null;
/**
 * The Url of the channel Homepage.
 * Used when the Mgr sends to the adapter from a popup, while the parent window is closed.
 */
ProfileMgr.settings.channelHomePage = Const.UNSET_STRING;
/**
 * A general error message, used when a connection error or server error occures.
 */
ProfileMgr.settings.noDataMessage = "<b>No data available</b>";
/**
 * The current User - access to UserAccounts API
 */
ProfileMgr.user = new UA.User();
/**
 * Returns true if the current user is logged as member, otherwise - false
 * 
 * @type boolean
 */
ProfileMgr.isMember = function()
{
	return Clearance.isMember();
}

/**
 * @param {object} oSettingsDictionary
 * A settings dictionary specifying at least "channel" and "authenticationAdapter"
 * can include any of the documented properties on the Profile.settings inner object
 */
ProfileMgr.init = function(oSettingsDictionary)
{
	if(!this.isInitiated)
	{
		Claim.isObject(oSettingsDictionary, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary must be an object");
		Claim.isNumber(oSettingsDictionary.channel, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.channel must be a number - describing the channel-id");
		Claim.isString(oSettingsDictionary.authenticationAdapter, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.authenticationAdapter must be a string - describing the authentication-adapter URL");
		Claim.isString(oSettingsDictionary.channelHomePage, "ProfileMgr.init(oSettingsDictionary) - oSettingsDictionary.channelHomePage must be a string - expected to be : the  URL for the homepage of the channel");

		this.log = new Log4Js.Logger("ProfileMgr")
		this.isInitiated = true;
	}

	this.set(oSettingsDictionary);
	
}
/**
 * Logs-Off the current User, and redirects
 * to the current page to dispose all cookies
 */
ProfileMgr.logOffCurrentUser = function()
{
	this.log.info("logging off current user...");
	
	// clear any cookie-related QS parts
	var oUrl = Url.parse(location.href);
	var oRemovedQS = String("ui,cx,rx,ux,ax,cn,rn,un,an").split(",");
	for(var i = 0 ; i < oRemovedQS.length; i++)
		delete oUrl.params[oRemovedQS[i]];

	//patch over bug of Url.parse on no QS URLs
	delete oUrl.params[""]

	var sUrl = Url.appendParams(oUrl.base, oUrl.params);
	this.log.info("sending to URL: " + sUrl );
	
	Clearance.forget(sUrl);
}
/**
 * @param {object} oSettingsDictionary
 * can include any of the documented properties on the ProfileMgr.settings inner object
 */
ProfileMgr.set = function(oSettingsDictionary)
{
	Object.extend(this.settings, oSettingsDictionary);	
}
/**
 * Sends the current page to the Authentication Adapter
 *
 * @param {string} sCommand
 * Command passed to the adapter
 */
ProfileMgr.sendToAdapter = function(sCommand)
{
	//assure userProfile 
	Claim.check(this.settings.authenticationAdapter != Const.UNSET_STRING, "ProfileMgr.sendToAdapter used without defining ProfileMgr.settings.authenticationAdapter");
	if(this.settings.authenticationAdapter == Const.UNSET_STRING)
		return alert("sendToAdapter used without defining settings.authenticationAdapter");

	if (sCommand == null || typeof(sCommand) != 'string'){
		sCommand = "login";
	}
	
	var submitSettings = {	action : this.settings.authenticationAdapter
						 ,	method : "GET"	
						 ,  target : this.settings.loginTarget
						 } 

	var sUrl =  Url.parse( this.getReturnUrl() );
	delete sUrl.params.channel;
	delete sUrl.params.lc;
	sUrl = Url.appendParams( sUrl.base, sUrl.params );

	var params =	{	command: sCommand.toLowerCase()
					,	retUrl : sUrl 
					,	channel: this.settings.channel
					};

	//applicative submit to TOP or Opener-window without conflicting IFrames/Windows security
	this.submitToPage(	submitSettings,	params );
	
	//in case the method is called from A.onclick
	return false;
}
/**
 * Sends the current page to the User-Profile page
 */
ProfileMgr.sendToProfile = function()
{
	//assure userProfile 
	Claim.check(this.settings.userProfile != Const.UNSET_STRING, "ProfileMgr.settings.userProfile","ProfileMgr.settings.userProfile is not set");

	//applicative submit to TOP or Opener-window  
	//without conflicting IFrames/Windows security
	this.submitToPage(	{	action : this.settings.userProfile
						,	target : this.settings.loginTarget }
					 );
}		
/**
 * @private
 * When the Mgr runs in the GC - returns the location of the current page.
 * When the Mgr runs in popup - tries to retrieve the Url of the parent, 
 * or returns ProfileMgr.settings.channelHomePage on failure.
 * Used when the sendToAdapter is called on the popup, to retrieve the return URL.
 *
 * Also - @private.
 * wrap function - in cirtain browser versions and settings security issues 
 * hide inner attributes of variables on parent and opener windows.
 * This wrap allows calling a function on the window itself.
 */
ProfileMgr_getReturnUrl = function(){	return ProfileMgr.getReturnUrl(); }
ProfileMgr.getReturnUrl = function()
{
	Claim.isTrue( this.isInitiated , "ProfileMgr.getReturnUrl() was called before initiating ProfileMgr. \n\nSee ProfileMgr.init(oSettingsDictionary)");
	// when running in popup - use opener
	if( window.opener )
	{
		try
		{
			return window.opener.ProfileMgr_getReturnUrl()
		}
		catch(ex)
		{
			this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the opener window. channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + Object.serialize(ex));
			return this.settings.channelHomePage;
		}	
	}
	// Use highest IFRAME with a ProfileMgr instance
	if( window.parent != window)
	{
		this.log.info("ProfileMgr.getReturnUrl() - Parent window detected");
		try
		{
			return window.parent.ProfileMgr_getReturnUrl()
		}
		catch(ex)
		{
			switch(typeof(ex))
			{
				case 'object': /*explorer*/
					this.log.debug("ProfileMgr.getReturnUrl() - Parent window detected, assumed Explorer-based browser ");
					if	(	ex.number == -2146827850 /*doesn't support this property*/
						||	ex.number == -2146823281 /*is null or not an object*/
						)
					{
						this.log.warn("widow.parent.ProfileMgr_getReturnUrl() is not found on parent window. Code runs in IFrame on a page of the partner. Exception: " + Object.serialize(ex) );
					}
					else
					{			
						this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the parent window for unexpected reason. Channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + Object.serialize(ex));
						return this.settings.channelHomePage;
					}
				break;
				case 'string': /* FireFox/Mozilla */ 
					this.log.debug("ProfileMgr.getReturnUrl() - Parent window detected, assumed Mozilla-based browser ");
	
					/** 
					 * the identifier of the exception is the message FF/Mozila use for permission denied:
					 * "Permission denied to get property Window.ProfileMgr_getReturnUrl"
					 * However, the words "Permission denied to get property" can be localized, 
					 * that leaves us only the property name...
					 */
					if	(  ex.indexOf("Window.ProfileMgr_getReturnUrl") != -1 ) 
					{
						this.log.warn("widow.parent.ProfileMgr_getReturnUrl() is not found on parent window. Code runs in IFrame on a page of the partner. Exception: " + ex);
					}
					else
					{			
						this.log.warn("ProfileMgr.getReturnUrl() failed to retrieve location from the parent window for unexpected reason. Channel-home used instead: " + this.settings.channelHomePage + ". Exception: " + ex);
						return this.settings.channelHomePage;
					}
				break;
			}
		}		
	}

	var sUrl = this.Url.full;
	//PATCH: - remove #anchor - overcome a bug of the infrastructure
	i =	sUrl.lastIndexOf("#");
	if(   i > -1 && i > sUrl.lastIndexOf("?") && i > sUrl.lastIndexOf("=") )
	{
		sUrl = sUrl.substr(0,i);
	}		
	return sUrl;
	

}
/**
 * High-Score - to open popup of user high-score of his worn badge
 */
ProfileMgr.addManagedPage( "HighScore", "/Orange2.0/App/GameHighScore.aspx", "width=611,height=440,status=no,scrollbars=yes,toolbar=no,menubar=no,location=no,resizeable=no");  							  
/**
 * Opens the high-score Page
 */
ProfileMgr.openGameHighScore = function(iSku)
{
	var oParams = Object.extend({}, this.Url.params);
	if(iSku)
	{
		oParams.sku = iSku;
	}
	this.openWindow("HighScore",oParams, {method: "GET"});
}
/**
 * Fetches and Populates the User-Details to the HTML elements, 
 * as specified by the provided dictionary.
 * The dictionary is expected to contain HTML element-IDs as keys, 
 * and User-Details properties as values.
 *
 * @param {object} p_propsDictionary
 * Supported properties as values 
 * according to the product UA.User.getDetails.
 * Known by the time of this update:
 *  - age            - gender
 *  - nickname       - birthDayOfMonth
 *  - birthMonth     - birthYear
 *  - country        - zipCode
 *
 * Uses a subclass of UA.USer as worker class.
 * It is described right bellow.
 */
ProfileMgr.getUserDetails = function(p_propsDictionary,oEvents)
{
	var ud = new ProfileMgr.UserDetails( p_propsDictionary );
	ud = Object.extend(ud,oEvents);
	ud.apply();
}
//--ProfileMgr.UserDetails-----------------------------------------------------------------
  /**
   * A worker class that fetches user details.
   */
	ProfileMgr.UserDetails = Class.create("UA.User");
	ProfileMgr.UserDetails = Class.enhance(ProfileMgr.UserDetails, IEventDispatcher);
	ProfileMgr.UserDetails.prototype.initialize = function(pPropsDictionary, fFailure, fTimeout)
	{
		Claim.isObject(pPropsDictionary, "UserDetails.get(pPropsDictionary) - pPropsDictionary is expected to be an object");
		
		this.log = new Log4Js.Logger("ProfileMgr.UserDetails");

		this.detailsPropDictionary = pPropsDictionary;
	}
	ProfileMgr.UserDetails.prototype.apply = function(){
		this.GetUserDetails(  this.onSuccess
							, this.onFailure 
							, this.onTimeout);
	}
	ProfileMgr.UserDetails.prototype.onSuccess = function(data)
	{
		this.log.debug("onSuccess(" + Object.serialize(data) + ")");

		this.dispatch("onDataBind", data);

		ProfileMgr.populateElements (/*oElementsDictionary*/ this.detailsPropDictionary
									,/*oDataSource		  */ data
									);
		this.log.debug("onSuccess is complete");
	}
	ProfileMgr.UserDetails.prototype.onFailure = function(r){ this.log.error('FAILURE on ProfileMgr.UserDetails.get()'); }
	ProfileMgr.UserDetails.prototype.onTimeout = function(r){ this.log.error('TIMEOUT on ProfileMgr.UserDetails.get()'); }
	ProfileMgr.UserDetails.get = function(pPropsDictionary, fFailure, fTimeout, oUser)
	{
		new ProfileMgr.UserDetails(pPropsDictionary, fFailure, fTimeout, oUser);
	}
//--/ProfileMgr.UserDetails------------------------------------------------------------
/**
 * ProfileMgr.getAvatar
 * gets the avatar of the user, and sets it's HTML to the provided sHtmlElementID.
 * The size of the avatar can be specified by the optional eAvatarSize
 *
 * @param {string} sHtmlElementID
 *
 * @param {Object(optional)} oSettings
 * Any settings, configurations, HTML-attributes or Flash-Params we want to pass on.
 *
 */
ProfileMgr.getAvatar = function(sHtmlElementID, oSettings, oEvents)
{
	Claim.isString(sHtmlElementID, "sHtmlElementID is expected to be the ID of the target element");
	oSettings = oSettings || {};

   ua = new GameCatalog.AvatarViewer( oSettings );
   ua = Object.extend(ua,oEvents);
   ua.render(sHtmlElementID);
}

/**
 * ProfileMgr.getAvatarStudio
 * gets the avatar of the user, and sets it's HTML to the provided sHtmlElementID.
 * The size of the avatar can be specified by the optional eAvatarSize
 *
 * @param {string} sHtmlElementID
 *
 * @param {Object(optional)} oSettings
 * Any settings, configurations, HTML-attributes or Flash-Params we want to pass on.
 *
 */
ProfileMgr.getAvatarStudio = function(sHtmlElementID, oSettings,oEvents)
{
	Claim.isString(sHtmlElementID, "sHtmlElementID is expected to be the ID of the target element");
	oSettings = oSettings || {};

   ua = new GameCatalog.AvatarStudio( sHtmlElementID, oSettings );
   ua = Object.extend(ua,oEvents);
   ua.apply();

}

/**
 * ProfileMgr.getGameBestScore
 * Populates the cummunity best score of the provided SKU in to the element specified by ID.
 *
 * @param {number} iSku
 * The Sku of the queried game
 *
 * @param {string} sElementID
 * The HTML element ID to feed the top-score into 
 *
 *  @param {string(optional)} sNoDataFoundHTML
 *  HTML to populate target-element when server returms with no data
 *  - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 *
 *  @param {string(optional)} sNotAvailableHTML
 *  HTML to populate target-element when there is a problem with the server's response
 *  - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 */
ProfileMgr.getGameBestScore = function(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML, oEvents)
{	
	var gbs = new ProfileMgr.GameBestScore( iSku
										  , sScoreElementID
										  , sNoDataFoundHTML  || this.settings.noDataMessage
										  , sNotAvailableHTML || this.settings.noDataMessage
										  );
	gbs = Object.extend(gbs,oEvents);
	gbs.apply();
}
//--ProfileMgr.GameBestScore------------------------------------------------------------
	/**
	 * A worker class that feches game community high-score
	 */
	ProfileMgr.GameBestScore = Class.create("UA.Game");
	ProfileMgr.GameBestScore = Class.enhance(ProfileMgr.GameBestScore, IEventDispatcher);
	ProfileMgr.GameBestScore.prototype.toString = function()
	{
		return "[UA.Game] extension: GameBestScore";
	}
	ProfileMgr.GameBestScore.prototype.initialize = function(iSku, sScoreElementID, sNoDataFoundHTML, sNotAvailableHTML)
	{
		Claim.isString(sScoreElementID,"ProfileMgr.GameBestScore(sScoreElementID,...) - sScoreElementID must be a string")	
		Claim.isObject($(sScoreElementID),"ProfileMgr.GameBestScore(sScoreElementID,...) - sScoreElementID must be a string representing an HTML element ID")	
		Claim.isString(sNoDataFoundHTML	, "ProfileMgr.GameBestScore(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
		Claim.isString(sNotAvailableHTML, "ProfileMgr.GameBestScore(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")

		this.log = new Log4Js.Logger("ProfileMgr.GameBestScore");

		this.oTargetElement = $(sScoreElementID);		
		this.noDataFound	= sNoDataFoundHTML;
		this.notAvailable	= sNotAvailableHTML;
		
	}
	ProfileMgr.GameBestScore.prototype.apply = function()
	{
		this.GetGameHighScores  ( /*mode	*/	""	
								, /*iAmount	*/	1			
								, /*period	*/	UA.Game.Scores.Periods.EVER
								, /*fSuccess*/	this.onSuccess
								, /*fFailure*/	this.onFailureOrTimeout
								, /*fTimeout*/	this.onFailureOrTimeout);
	}
	ProfileMgr.GameBestScore.prototype.onSuccess = function(data)
	{
		this.log.info("onSuccess with this data: " + Object.serialize(data));
		if(!data || !data.TopScores || !data.TopScores[0] || !data.TopScores[0].Score)
		{
			this.log.error("GameBestScore did not get game best-score data. Object.serialize(data): " + Object.serialize(data));
			Element.setText(this.oTargetElement, this.noDataFound);
			return;
		}

		this.dispatch("onDataBind", data);
		
		Element.setText(this.oTargetElement, Number(data.TopScores[0].Score).format());
	}
	ProfileMgr.GameBestScore.prototype.onFailureOrTimeout = function(r)
	{ 
		this.log.error('FAILURE or TIMEOUT on ProfileMgr.GameBestScore.get()');
		Element.setText(this.oTargetElement, this.sNotAvailableHTML);
	}
//--/ProfileMgr.GameBestScore------------------------------------------------------------

/**
 * ProfileMgr.getUserBestScore
 * Gets the user's best score to the provided game, and populates the target element
 * using the provided template
 *	
 * @param {number} iSku
 * The Sku of the queried game
 *
 * @param {string} sStringTemplate
 * The template of the populated element
 * 
 * @param {object} oPlaceHoldersDictionary
 * A dictionary with place-holders in the template as keys, 
 * and the expected value-propreties for these places from the server's response as values
 * 
 * @param {string} sTargetElementID
 * The HTML element ID to feed the top-score into 
 *
 * @param {string(optional)} sNoDataFoundHTML
 * HTML to populate target-element when server returms with no data
 * - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 *
 * @param {string(optional)} sNotAvailableHTML
 * HTML to populate target-element when there is a problem with the server's response
 * - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 */
ProfileMgr.getUserBestScore  = function(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML, oEvents)
{
	var ubs = new ProfileMgr.UserBestScore( iSku
											, sStringTemplate
											, oPlaceHoldersDictionary
											, sTargetElementID
											, sNoDataFoundHTML  || this.settings.noDataMessage
											, sNotAvailableHTML || this.settings.noDataMessage
											);
	ubs = Object.extend(ubs, oEvents);
	ubs.apply();
}
//--ProfileMgr.getUserBestScore------------------------------------------------------------
	/**
	 * A worker class that feches game user high-score
	 */
	ProfileMgr.UserBestScore = Class.create("UA.Game");
    ProfileMgr.UserBestScore = Class.enhance(ProfileMgr.UserBestScore, IEventDispatcher);
	ProfileMgr.UserBestScore.prototype.toString = function()
	{
		return "[UA.Game] extension: UserBestScore";
	}
	ProfileMgr.UserBestScore.prototype.initialize = function(iSku, sStringTemplate, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
	{
		Claim.isString(sStringTemplate, "UserBestScore.initialize - sStringTemplate must be a string");
		Claim.isObject(oPlaceHoldersDictionary, "UserBestScore.initialize - oPlaceHoldersDictionary  must be an object");
		Claim.isString(sTargetElementID, "UserBestScore.prototype.initialize - sTargetElementID must be a string");
		Claim.isObject($(sTargetElementID), "UserBestScore.prototype.initialize - sTargetElementID must be a string describing an HTML element ID");
		Claim.isString(sNoDataFoundHTML	, "ProfileMgr.UserBestScore(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
		Claim.isString(sNotAvailableHTML, "ProfileMgr.UserBestScore(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")
		
		this.log = new Log4Js.Logger("ProfileMgr.UserBestScore");
		
		
		this.userBestScoreTemplate = sStringTemplate;
		this.userBestScorePlaceHoldersDictionary = oPlaceHoldersDictionary;
		this.oTargetElement = $(sTargetElementID);		
		this.noDataFound	= sNoDataFoundHTML;
		this.notAvailable	= sNotAvailableHTML;
	

	}
	/**
	 * sends the request
	 */
	ProfileMgr.UserBestScore.prototype.apply = function()
	{
		this.GetUserHighScore( /* mode:		*/ null
							 , /* fSuccess: */ this.onSuccess
							 , /* fFailure: */ this.onFailureOrTimeout
							 , /* fTimeout: */ this.onFailureOrTimeout
							 );
	}
	/**
	* @param {object} data
	* expeced properties on data (provided by infra): 
	*   - userHighScore    - userRanking
	*   - userPosition
	*/
	ProfileMgr.UserBestScore.prototype.onSuccess = function(dataUA)
	{
		
		this.log.info("onSuccess with this Data: " + Object.serialize(dataUA) );

		if(!dataUA.userPosition && !dataUA.userHighScore && !dataUA.userRanking)
		{
			Element.setText(this.oTargetElement, this.noDataFound);
			return;
		}
		
		var data = Object.extend({}, dataUA);
		
		data.userPosition		= (!data.userPosition	   ) ? "&nbsp" : "(" + data.userPosition + ")";
		data.userRankingImgUrl  = (data.userRanking == null) ? ""	   : TC.UserMedals.getMedalByRanking( data.userRanking ).img;
		data.userHighScoreFormatted = Number(data.userHighScore).format();
		
		this.log.debug("pre populating template with : " + Object.serialize(data) );
	
		this.dispatch("onDataBind", data);
		
		var strHTML = ProfileMgr.populateStringTemplate (	this.userBestScoreTemplate
														,	this.userBestScorePlaceHoldersDictionary
														,   data
														);
		Element.setText(this.oTargetElement, strHTML );
	}
	ProfileMgr.UserBestScore.prototype.onFailureTimeout = function()
	{
		this.log.error('FAILURE or TIMEOUT on UserBestScore.get()');
		Element.setText(this.oTargetElement, this.notAvailable );
	}
//--/ProfileMgr.GameBestScore------------------------------------------------------------
/**
 * ProfileMgr.getUserOnlineGames
 * Gets the user's recent online games, and populates them into the target element, 
 * in the format of the provided game-template. 
 *
 * @param {string} sTemplatesString
 * The template for each found game 
 * 
 * @param {object} oPlaceHoldersDictionary
 * A dictionary with place-holders in the template as keys, 
 * and the expected value-propreties for these places from the server's response as values
 *
 * @param {string} sTargetElementID
 * The HTML element ID to feed the top-score into 
 *
 * @param {number(optional)} oParams
 * The max displayed games.
 * - optiona: When not provided - all fetched games are shown.
 *
 */
ProfileMgr.getUserOnlineGames = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oParams, oEvents)
{
	var uog = new ProfileMgr.UserOnlineGames( sTemplatesString
											, oPlaceHoldersDictionary
											, sTargetElementID
											, oParams
											);
	uog = Object.extend(uog, oEvents);
	uog.apply();
}
//--ProfileMgr.UserOnlineGames------------------------------------------------------------
	ProfileMgr.UserOnlineGames = Class.create("UA.User");
    ProfileMgr.UserOnlineGames = Class.enhance(ProfileMgr.UserOnlineGames, IEventDispatcher);
	ProfileMgr.UserOnlineGames.prototype.initialize = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oParams )
	{
		Claim.isString(sTemplatesString, "ProfileMgr.UserOnlineGames(GameTemplateString,...) must be a string");
		Claim.isObject(oPlaceHoldersDictionary, "ProfileMgr.UserOnlineGames(...,oPlaceHoldersDictionary,...) must be an object");
		Claim.isString(sTargetElementID, "ProfileMgr.UserOnlineGames(...,sTargetElementID,...) must be a string");
		Claim.isObject($(sTargetElementID), "ProfileMgr.UserOnlineGames(...,sTargetElementID,...) must be a string describing an HTML element");

		if(!oParams) oParams = {};
		
		//backward compatibility - iMaxShownGames as a "default" parameter
		if(parseInt(oParams)) oParams = {maxGames: parseInt(oParams)};

		this.params = Object.extend( this.params, oParams );
		
		if(oParams.maxGames) this.maxDisplayedGames = oParams.maxGames;
		
		this.log = new Log4Js.Logger("ProfileMgr.UserOnlineGames");
		
		this.repeater = new TC.Controls.Repeater( sTemplatesString 
												, this.log
												, {error: "error"} 
												);
		this.repeater.boss = this;
		this.repeater._dispatch = this.repeater.dispatch;
		this.repeater.dispatch = function()
		{
			this.log.info("ProfileMgr.UserOnlineGames.repeater - dispatching " + arguments[0] );
			if(this[arguments[0]])
				return this._dispatch.apply(this, arguments);

			return this.boss.dispatch.apply(this.boss, arguments);
		}

		this.templates = this.repeater.templates;

		if(0 == this.templates.noData.length) this.templates.noData = ProfileMgr.settings.noDataMessage;
		if(0 == this.templates.error.length	) this.templates.error		  = ProfileMgr.settings.noDataMessage;

		this.templatePlaceHoldersDictionary = oPlaceHoldersDictionary;
		this.oTargetElement = $(sTargetElementID);
	}
	ProfileMgr.UserOnlineGames.prototype.apply = function()
	{	
		this.GetUserGames( this.onSuccess
						 , this.onFailureOrTimeout
						 , this.onFailureOrTimeout);
	}
	ProfileMgr.UserOnlineGames.prototype.toString = function()
	{
		return "[UA.User] extension: UserOnlineGames";
	}
	ProfileMgr.UserOnlineGames.prototype.prv_repeater_onItemDataBound = function(item)
	{
		if( !TC.SKUs.extendDataFromSKU(item.dataItem, item.dataItem.gameSku) )
		{
			item.skipItem = true;
			this.log.info(item.dataItem.sku + " was reported as recent user online game, but is not found in games catalog");
		}
		
		this.boss.dispatch("onItemDataBound", item);
	}
	ProfileMgr.UserOnlineGames.prototype.onSuccess = function(data)
	{
		this.log.info("onSuccess with this Data: " + Object.serialize(data) );
		
		var arrGames = data.Games;
		if ( this.maxDisplayedGames && arrGames.length > this.maxDisplayedGames )
			arrGames = arrGames.slice(0, this.maxDisplayedGames);

		this.repeater.onItemDataBound = this.prv_repeater_onItemDataBound;
		this.repeater.dataBind( this.templatePlaceHoldersDictionary, arrGames );

		this.repeater.render( this.oTargetElement );
		return;
	}
	ProfileMgr.UserOnlineGames.prototype.onFailureOrTimeout = function()
	{ 
		this.log.error("FAILURE or TIMEOUT on ProfileMgr.UserOnlineGames");
		Element.setText(this.oTargetElement, this.templates.error);
	}
//--/ProfileMgr.UserOnlineGames------------------------------------------------------------

/**
 *
 */
ProfileMgr.getUserDownloadGames = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings, oEvents)
{
	if(!oSettings.channel) oSettings.channel = this.settings.channel;

	var udg = new ProfileMgr.UserDownloadGames(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings);
	udg = Object.extend(udg, oEvents);
	udg.apply();
}
 
//--ProfileMgr.UserDownloadGames------------------------------------------------------------
    ProfileMgr.UserDownloadGames = Class.create();
    ProfileMgr.UserDownloadGames = Class.enhance(ProfileMgr.UserDownloadGames, IEventDispatcher);
	ProfileMgr.UserDownloadGames.prototype.toString = function()
	{
		return "[ProfileMgr.UserDownloadGames]";
	}
    ProfileMgr.UserDownloadGames.prototype.initialize = function(sTemplatesString, oPlaceHoldersDictionary, sTargetElementID, oSettings)
    {
		Claim.isString(sTemplatesString, "ProfileMgr.UserDownloadGames(...,GameTemplateString,...) must be a string");
		Claim.isObject(oPlaceHoldersDictionary, "ProfileMgr.UserDownloadGames(...,oPlaceHoldersDictionary,...) must be an object");
		Claim.isString(sTargetElementID, "ProfileMgr.UserDownloadGames(...,sTargetElementID,...) must be a string");
		Claim.isObject($(sTargetElementID), "ProfileMgr.UserDownloadGames(...,sTargetElementID,...) must be a string describing an HTML element");

		if(!oSettings) oSettings = {};
		Claim.isScalar(oSettings.channel, "ProfileMgr.UserDownloadGames(.../oSettings.channel) must be the channel-code or codes");
		this.channel = oSettings.channel;

		this.log = new Log4Js.Logger("ProfileMgr.UserDownloadGames");

		this.maxDisplayedGames = oSettings.showMaxGames || 10;

		this.repeater = new TC.Controls.Repeater( sTemplatesString , this.log );
		this.repeater.boss = this;
		this.repeater._dispatch = this.repeater.dispatch;
		this.repeater.dispatch = function()
		{
			this.log.info("ProfileMgr.UserOnlineGames.repeater - dispatching " + arguments[0] );
			if(this[arguments[0]])
				return this._dispatch.apply(this, arguments);

			return this.boss.dispatch.apply(this.boss, arguments);
		}
		
		this.templatePlaceHoldersDictionary = oPlaceHoldersDictionary;
		this.oTargetElement = $(sTargetElementID);
    }
    ProfileMgr.UserDownloadGames.prototype.apply = function()
    {
		var data = ProfileMgr.getInstalledGames(this.channel)
		if (!data.games.length)
		{
			this.log.info("No downloadable games are found.");
		}
		this.onPopulate(data);
    }
    ProfileMgr.UserDownloadGames.prototype.prv_repeater_onItemDataBound = function(item)
	{
		if( !TC.SKUs.extendDataFromSKU(item.dataItem) ){
			this.log.info(item.dataItem.sku + " is installed for channel " + ProfileMgr.settings.channel + " but is not found in games catalog");
			item.skipItem = true;
		}

		this.boss.dispatch("onItemDataBound", item);
	}
    ProfileMgr.UserDownloadGames.prototype.onPopulate = function(data)
    {
    
		this.log.info("populating downloadable games with this Data: " + Object.serialize(data) );
		
		var arrGames = data.games;
		if ( this.maxDisplayedGames && arrGames.length > this.maxDisplayedGames )
			arrGames = arrGames.slice(0, this.maxDisplayedGames);

		this.repeater.onItemDataBound = this.prv_repeater_onItemDataBound;
		this.repeater.dataBind( this.templatePlaceHoldersDictionary, arrGames );

		this.repeater.render( this.oTargetElement );
		return;
    }
//--/ProfileMgr.UserDownloadGames------------------------------------------------------------

/**
 * ProfileMgr.getUserWornBadge
 * Gets the user worn badge, and populates the target element using the worn 
 * badge's properties and the badge HTML template.
 *
 * @param {string} sBadgeTemplateString
 * The template for the user's worn badge 
 *
 * @param {object} oPlaceHoldersDictionary
 * A dictionary with place-holders in the template as keys, 
 * and the expected value-propreties for these places from the server's response as values

 * @param {string} sTargetElementID
 * The HTML element ID to feed the top-score into 
 *
 * @param {string(optional)} sNoDataFoundHTML
 * HTML to populate target-element when server returms with no data
 * - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 *
 * @param {string(optional)} sNotAvailableHTML
 * HTML to populate target-element when there is a problem with the server's response
 * - optional: When not provided, ProfileMgr.settings.noDataMessage is used
 */
ProfileMgr.getUserWornBadge = function(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML,oEvents)
{
	var ub = new ProfileMgr.UserBadge(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID
									, sNoDataFoundHTML  || this.settings.noDataMessage
									, sNotAvailableHTML || this.settings.noDataMessage
									);
	ub = Object.extend(ub, oEvents);									
	ub.apply();
}
//--ProfileMgr.UserBadge------------------------------------------------------------
	ProfileMgr.UserBadge = Class.create("UA.User");
    ProfileMgr.UserBadge = Class.enhance(ProfileMgr.UserBadge, IEventDispatcher);
	ProfileMgr.UserBadge.prototype.toString = function()
	{
		return "[UA.User] extension: UserBadge";
	}
	ProfileMgr.UserBadge.prototype.initialize = function(sBadgeTemplateString, oPlaceHoldersDictionary, sTargetElementID, sNoDataFoundHTML, sNotAvailableHTML)
	{
		Claim.isString(sBadgeTemplateString, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTemplateString must be a string");
		Claim.isObject(oPlaceHoldersDictionary, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - oPlaceHoldersDictionary must be an object");
		Claim.isString(sTargetElementID, "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTargetElementID must be a string");
		Claim.isObject($(sTargetElementID), "UserBadge.prototype.initialize(sTargetElementID, oPlaceHoldersDictionary, sBadgeTargetElementID) - sBadgeTargetElementID must be a string describing an HTML element ID");
		Claim.isString(sNoDataFoundHTML	, "ProfileMgr.UserBadge(...,sNoDataFoundHTML,...) - must be a string, expected HTML for no-data-found case")
		Claim.isString(sNotAvailableHTML, "ProfileMgr.UserBadge(...,sNotAvailableHTML) - must be a string, expected HTML for no-data-available case")
		
		this.log = new Log4Js.Logger("ProfileMgr.UserBadge");
		
		this.oTargetElement = $(sTargetElementID);		
		this.noDataFound	= sNoDataFoundHTML;
		this.notAvailable	= sNotAvailableHTML;
		this.medalsStringTemplate = sBadgeTemplateString;
		this.medalsPlaceHoldersDictionary = oPlaceHoldersDictionary;
		
	}
	ProfileMgr.UserBadge.prototype.apply = function()
	{
		this.GetHighestMedal( this.onSuccess
							, this.onFailure
							, this.onTimeout);
	}
	ProfileMgr.UserBadge.prototype.onSuccess = function(data)
	{
		this.log.info("ProfileMgr.serBadge.onSuccess - got data: " + Object.serialize(data));

		var game = TC.SKUs[data.gameSku];
		if(!game){
			this.log.error("Game sku " + data.gameSku + " is not found.");
			Element.setText (this.oTargetElement, this.notAvailable);
			return;
		}
		this.log.info("getUserWornBadge - user badge game: " + Object.serialize(game));
		this.log.info("data.userRanking:"+ data.userRanking + ", TC.UserMedals.getMedalByRanking(data.userRanking):" + Object.serialize(TC.UserMedals.getMedalByRanking(data.userRanking)));
		
		data.badgeGameSku	=	game.sku;
		data.badgeGameName	=	game.name;
		data.badgeGameUrl   =   game.gamePageURL;
		data.badgeImgUrl	=	TC.UserMedals.getMedalByRanking(data.userRanking).img;

		this.dispatch("onDataBind", data);
	
		var sHTML = ProfileMgr.populateStringTemplate( this.medalsStringTemplate
													 , this.medalsPlaceHoldersDictionary
													 , data
													 );
		Element.setText (this.oTargetElement,	sHTML);
	}
	ProfileMgr.UserBadge.prototype.onFailure = function(response)
	{ 
		this.log.error("FAILURE on ProfileMgr.UserBadge");

		if( response.Status == 'PERSONAL_DETAILS_NOT_FOUND')
		{
			this.log.warn("PERSONAL_DETAILS_NOT_FOUND on UserBadge");
			Element.setText (this.oTargetElement,	this.noDataFound);
		}
		else
		{
			this.log.warn("Error on UserBadge: " + response.Status);
			Element.setText (this.oTargetElement,	this.notAvailable);
		}
	}
	ProfileMgr.UserBadge.prototype.onTimeout = function(request)
	{ 
		this.log.error("TIMEOUT on ProfileMgr.UserBadge");
		Element.setText (this.oTargetElement,	this.notAvailable);
	}
//--/ProfileMgr.UserBadge------------------------------------------------------------
/**
 * ProfileMgr.getInstalledGames
 * 
 * @param {Number|String(optional)} The channel-code or comma-delimited-string of channel-codes
 * When not provided - the channel that is initiated into ProfileMgr is used.
 */
ProfileMgr.getInstalledGames = function(channel)
{
	channel = channel || this.settings.channel;
	return getGamesListByChannel(channel)
}
//----------------------------------------------------------------------------------

/**
 * Centralizes the applicativity of the user's Avatar
 */
ProfileMgr.Avatar = { }
/**
 * id of the HTML id
 */
ProfileMgr.Avatar.id = "mainFAV"
/**
 * supported emotions array
 */
ProfileMgr.Avatar.Emotions = [ "Happy"
							 , "Sad"
							 ];
ProfileMgr.Avatar.Emotions.Happy = 0
ProfileMgr.Avatar.Emotions.Sad = 1


ProfileMgr.Avatar = {};


/**
 * initiates the ProfileMgr.Avatar object
 * 
 * @param {string(optional)} sAvatarID
 * - optional: when not provided, the default in ProfileMgr.Avatar.id is used.
 */
ProfileMgr.Avatar.init = function(sAvatarID)
{
	if(!this.log) this.log = new Log4Js.Logger("ProfileMgr.Avatar");

	if(sAvatarID) this.id = sAvatarID;
	if(!this.id) 
	{
		this.log.warn("avatar object ID is not set");
		return;
	}
	if( navigator.appName.indexOf("Netscape") != -1 )
	{
		this.log.info("netscape detected.");
		this.objFAV = document.embeds[this.id];
		return;
	}
	else
	{
		this.objFAV = $(this.id);
	}
}
ProfileMgr.addOnLoadHandler( 
	function()
	{ 
		ProfileMgr.Avatar.init(); 
	}
);
/**
 * Sets emotion to the active avater
 *
 * @param {string} sEmotion
 * The emotion be to set
 */
ProfileMgr.Avatar.be = function(sEmotion)
{
	Claim.isString(sEmotion, "ProfileMgr.Avatar.be(sEmotion) - sEmotion must be a string, expectedly - describing a supported emotion");
	if(null == this.Emotions[sEmotion])
	{
		this.log.warn("ProfileMgr.Avatar.be(sEmotion) - invalid emotion is used: " + sEmotion);
		return;
	}
	this.objFAV.SetVariable("val", sEmotion);
	this.objFAV.SetVariable("command","changeEmotion");
}
/**
 * sets the zoom of the avatar
 * 
 * @param {string} sZoom
 * The zoom to be set
 */
ProfileMgr.Avatar.zoom = function(sZoom)
{
	Claim.isString(zoom, "ProfileMgr.Avatar.be(zoom) - zoom must be a string, expectedly - describing a supported zoom rate");

	this.objFAV.SetVariable("val", sZoom);
	this.objFAV.SetVariable("command","setZoom");
}
/**
 * Sets the avatar emotion to Happy
 */
ProfileMgr.Avatar.beHappy = function()
{
	this.be("Happy");
}
/**
 * Sets the avatar emotion to Sad
 */
ProfileMgr.Avatar.beSad = function()
{
	this.be("Sad");
}



//--------------------------------------------------------
// SEATLE PORTLET AVATAR ON CLICK API
avatarOnClick = function(){}
/******************Profile.js - End *********************/
/******************UI.Community.js - Start *********************/
if(!window.UI) UI = {};
if(!UI.Community) UI.Community = {};

//--UI.Community.GameScores------------------------------------------------------------
/**
 * @fileoverview
 * A worker class that feches game community high-score
 */
;(UI.Community).GameScores = Class.create("UA.Game");
Class.enhance(UI.Community.GameScores, IEventDispatcher);
/**
 * Overrides the default toString() implementation.
 * @returns "[UA.Game] extension: GameScores"
 * @type String
 */
UI.Community.GameScores.prototype.toString = function()
{
	return "[UA.Game] extension: GameScores";
}

/**
 * The execution settings for the current instance
 * Supported settings:<ol>
 *  <li>period - The queried period
 *  <li>maxScores - The maximum scores that are fetched. 
 *  <li>avatarSize - the size of the avatar, taken from the 'enum' <b>UA.User.Avatar.Size</b>. 
 *  </ol>
 * @type Object
 */
UI.Community.GameScores.prototype.settings = { period: "EVER"
											 , maxScores: 10
											 , avatarSize: "NONE"
											 } 

/** 
 *
 */
UI.Community.GameScores.prototype.initialize = function(iSku, sTemplate, oMapping, sScoreElementID, oSettings)
{
	Claim.isString(sTemplate		, "UI.Community.GameScores(..,sTemplate) - sTemplate is expected to be an HTML string template for use of TC.Controls.Repeater");
	Claim.isObject(oMapping			, "UI.Community.GameScores(..,oMapping,..) - oMapping must be a mapping object fit for use of TC.Controls.Repeater");
	Claim.isString(sScoreElementID,"UI.Community.GameScores(..,sScoreElementID,..) - sScoreElementID must be a string");
	if(oSettings.period) Claim.isString( UA.Game.Scores.Periods[oSettings.period], "UI.Community.GameScores(..,settings.period) - when provided, must be a legal period from the enum UA.Game.Scores.Periods. Provided: + [" + oSettings.period + "]")
	var avatarSize = oSettings.avatarSize;
	if(typeof(avatarSize) == 'string') avatarSize = UI.Avatar.Size[avatarSize];
	Claim.isNumber( oSettings.avatarSize.height + oSettings.avatarSize.width, "UI.Community.GameScores(..,enPeriod.avatarSize) - when provided, must be a legal period from the enum UI.Avatar.Size, or a string representing its name. Provided: + [" + Object.serialize(oSettings.avatarSize) + "]");
	/**
	 * The Log4Js.Logger instance
	 * @type Log4Js.Logger
	 */
	this.log = new Log4Js.Logger("UI.Community.GameScores");
	/**
	 * The element to populate with the bound template
	 * @type DOM-Element
	 */
	this.targetElement = sScoreElementID;		
	/**
	 * The {@link TC.Controls.Repeater} worker class
	 * @type TC.Controls.Repeater
	 */
	this.repeater = new TC.Controls.Repeater( sTemplate 
											, this.log
											, {error: "error"} 
											);
	this.repeater.boss = this;
	this.repeater._dispatch = this.repeater.dispatch;
	this.repeater.dispatch = function()
	{
		this.log.info("UI.Community.UserOnlineGames.repeater - dispatching " + arguments[0] );
		if(this[arguments[0]])
			return this._dispatch.apply(this, arguments);

		return this.boss.dispatch.apply(this.boss, arguments);
	}
	
	
	/**
	 * Mapping dictionary, with Place-Holders as keys and thier data-bind replacements as values.
	 * @type Object
	 */
	this.mapping = oMapping;
	
	// copies all provided settings to this instance's settings	
	this.settings = Object.extend( Object.extend( this.settings), oSettings);
}
/****/
UI.Community.GameScores.prototype.apply = function(isCached)
{
	if(isCached == true)
	{
		this.log.info("applying cached request");
		this.isCachedResponse = true;
	}
	
	this.GetGameHighScores  ( /*mode	*/	""	
							, /*iAmount	*/	this.settings.maxScores
							, /*period	*/	this.settings.period 
							, /*fSuccess*/	this.onSuccess
							, /*fFailure*/	this.onFailureOrTimeout
							, /*fTimeout*/	this.onFailureOrTimeout
							, /*avatar  */  this.settings.avatarSize.name);
}
UI.Community.GameScores.prototype.onSuccess = function(data)
{
	this.log.info("onSuccess with this data: " + Object.serialize(data));
	if(!data || !data.TopScores)
	{
		this.log.error("GameScores did not get game best-score data. Object.serialize(data): " + Object.serialize(data));
		Element.setText(this.oTargetElement, this.repeater.templates.noData);
		return;
	}

	this.shownScores = data.TopScores.cut(0, this.maxScores);
	this.dispatch("onData");

	if (this.settings.avatarSize)
	{
		var i;
		var a = new GameCatalog.AvatarViewer( this.settings.avatarSize );
		for(i = 0; i < this.shownScores.length; i++)
		{
			
			a.settings.nickname = this.shownScores[i].Nickname;
			a.settings.id = a.settings.name = "oAvatar_" + a.settings.nickname;
			this.shownScores[i].Avatar = a.render();
		}
	}

	this.dispatch("onDataBind", this.shownScores);

	Claim.isObject($(this.targetElement),"UI.Community.GameScores.onSuccess - Cannot find target element: [" + this.targetElement + "]");	
	this.repeater.dataBind(this.mapping, this.shownScores);
	this.repeater.render($(this.targetElement));
}
UI.Community.GameScores.prototype.onFailureOrTimeout = function(r)
{ 
	this.log.error('FAILURE or TIMEOUT on UI.Community.GameScores.get()');
	Claim.isObject($(this.targetElement),"UI.Community.GameScores.onFailureOrTimeout - Cannot find target element: [" + this.targetElement + "]");	
	Element.setText( $(this.targetElement), this.repeater.templates.error);
}
//--/UI.Community.GameScores------------------------------------------------------------

//--UI.Community.TopPlayedGames------------------------------------------------------------

	
/*
* @param {string} sTarget
* Target Element (where to show the result)
*
* @param {string} sTemplate
* the Template as string (usually its in a textarea object, therefore we should send <ObjectName>.value)
*
* @param {object} oPlaceHoldersDictionary
* template dictionary (place holder & dataItem Name)
*
* @param {object} oSettings
* Settings: maxGames
*/
UI.Community.getTopPlayedGames = function (sTarget,sTemplate, oPlaceHoldersDictionary, oSettings)
{
	
	oPlayedGames = new UI.Community.TopPlayedGames(sTemplate, oPlaceHoldersDictionary, oSettings);
	
	oPlayedGames.dataBind(oPlaceHoldersDictionary);
	oPlayedGames.render($(sTarget));
}

/**
 *
 */
UI.Community.TopPlayedGames = Class.create();
Class.enhance(UI.Community.TopPlayedGames, IEventDispatcher);

/**
 *
 * @param
 *
 * @constructor
 */							
UI.Community.TopPlayedGames.prototype.initialize = function (sTemplate, oPlaceHoldersDictionary, oSettings)
{
	//create logger
	this.log = new Log4Js.Logger("UI.Community.TopPlayedGames")
	this.log.debug("TopPlayedGames - Initiatiate start");
	//update settings
	this.settings = Object.extend(Object.clone(this.settings), oSettings);
	//create repeater worker object
	this.mapping = oPlaceHoldersDictionary;
	//TODO: the innerItem repeater parse-tag is meant for the sub-class HallOfFame.
	//      We will need in the future more extensibility like innerHeader, innerFooter etc - 
	//		therefore - it must be more infrastructural
	this.repeater = new TC.Controls.Repeater(	sTemplate 
											,	this.log
											,	this.enhancedParseTags
											);
	this.repeater.boss = this;
	this.repeater._dispatch = this.repeater.dispatch;
	
/*	this.repeater.dispatch = function()
	{
		this.log.info("ProfileMgr.UserOnlineGames.repeater - dispatching " + arguments[0] );
		if(this[arguments[0]])
			return this._dispatch.apply(this, arguments);

		return this.boss.dispatch.apply(this.boss, arguments);
	}
*/	
	this.log.debug("TopPlayedGames - Initiatiate End");
}


/**
 * This function allows UI.Community.TopPlayedGames to be a parent class, 
 * using the Class.create(fClass) mechanism.
 * @private
 */
UI.Community.TopPlayedGames.AsPrototype = function()
{
	return new UI.Community.TopPlayedGames("", {} );
}
/**
 *
 */
UI.Community.TopPlayedGames.prototype.enhancedParseTags = {error: "error"};

/**
 *
 */
UI.Community.TopPlayedGames.prototype.settings = {	maxGames:	5	}

/**
 *
 */
UI.Community.TopPlayedGames.prototype.dataBind = function(oPlaceHoldersDictionary)
{
	if(!oPlaceHoldersDictionary) oPlaceHoldersDictionary = this.mapping;
	Claim.isObject(oPlaceHoldersDictionary, "UI.Community.TopPlayedGames.dataBind(oPlaceHoldersDictionary) - oPlaceHoldersDictionary must be provided to the dataBind method, or be provided to the constructor");

	var dsPlayedGames = new Array();
	//get the data-source
	// - get the topPlayedGames from presence-catalog - returns array of SKUs
	this.boundGames = [];
	var arrGames = this.getTopPlayedSkus();
	
	var oGame;
	//pass on the array = collect in a new array for each sku its corresponding oGame from the catalog
	for (var i = 0;i < arrGames.length; i++)
	{
		oGame = TC.SKUs.extendDataFromSKU( arrGames[i] );
		if(!oGame)
		{
			this.log.warn("Presence reported a sku that is not in the catalog. sku: [" + this.boundGames[i] + "]");
			this.dispatch("onMissingSku", Object.serialize(arrGames[i]));
			continue;
		}
		oGame.itemNumber = i + 1;
		this.dispatch("onDataItemPrepare", oGame);
		this.boundGames[this.boundGames.length] = oGame;
	}
	this.dispatch("onDataBind");
	
	this.log.debug("gathered total " + this.boundGames.length + " games");
	this.repeater.dataBind( this.mapping, this.boundGames )
}

/**
 *
 */
UI.Community.TopPlayedGames.prototype.getTopPlayedSkus = function()
{
	return PresenceCatalog.getTopPlayedSkus(this.settings.maxGames);
}

/**
 *
 */
UI.Community.TopPlayedGames.prototype.render = function (sTarget)
{
	//input checks
	if(!sTarget) sTarget = this.settings.targetElement;
	Claim.isObject( $(sTarget) , "UI.Community.TopPlayedGames.render(sTarget) - sTarget must be an ID of the target DOM-container, or a default target DOM container must be provided in the initial oSettings object");
	//call dataBind (if wasn't called)
	if  (!this.boundGames) this.dataBind();
	//Render
	this.repeater.render( $(sTarget) );
	
	this.dispatch("onComplete");

}
//--/UI.Community.TopPlayedGames------------------------------------------------------------


//--UI.Community.HallOfFame------------------------------------------------------------
/**
 *
 */
 UI.Community.HallOfFame = Class.create("UI.Community.TopPlayedGames");

/**
 *
 
 
hof = new UI.Community.HallOfFame( /*template * /		$("hall_of_fame_template").value
								, /*mapping * /		{	GAME_SKU		:	"sku"
													,	GAME_NAME		:	"name"
													,	USER_AVATAR		:	"Avatar"
													,	USER_NICK		:	"Nickname"
													,	SCORE			:   "Score"
													,	GAME_PAGE_URL	:	"gamePageURL"
													,	ITEM_NUMBER		:	function(){return myItemNumber++;}
													}
								, /*settings * /		{	maxGames			: 5
													,	maxScoresPerGame	: 1
													,	targetElement		: "hall_of_fame_target"
													}
								);


hof.render();
 
 */
UI.Community.HallOfFame.prototype.initialize = function(sTemplate, oPlaceHoldersDictionary, oSettings)
{
	Claim.isString(oSettings.innerItemTemplate, "UI.Community.HallOfFame(..,oSettings) - oSettings must contain the template of the high-score elements as oSettings.innerItemTemplate");
	/**
	 *
	 */
	this.HighScoreRequests = [];
	
	this.innerMapping = this.mapping;
	this.mapping = { INNER_TARGET_ID : "highScoreAsyncTarget"	};
	
	this.itrSlotIndex = 0;
}
/**
 *
 */
UI.Community.HallOfFame.prototype.enhancedParseTags.innerItem = "innerItem";
/**
 *
 */
UI.Community.HallOfFame.prototype.settings.maxScoresPerGame = 1;
/**
 *
 */
UI.Community.HallOfFame.prototype.settings.scoresPeriod = UA.Game.Scores.Periods.EVER;
/**
 *
 */
UI.Community.HallOfFame.prototype.settings.avatarSize = UI.Avatar.Size.Size24x24;
/**
 *
 */
UI.Community.HallOfFame.prototype.onDataItemPrepare = function(oGame)
{
	
	//prepare the ID of the asyncronous score-fetch
	oGame.highScoreAsyncTarget = "oGameHighScore_" + this.itrSlotIndex++;

	//prepare the worker-object that fetches the score for the sku
	this.log.debug("instantiating worker UI.Community.GameScores object for sku : " + oGame.sku );
	r = 
	this.HighScoreRequests[this.HighScoreRequests.length] = 
		new UI.Community.GameScores ( /*iSku             */ oGame.sku
									, /*sTemplateString  */ this.settings.innerItemTemplate
									, /*oPlaceHolders    */ this.innerMapping
									, /*targetElement    */ oGame.highScoreAsyncTarget
									, /* oSettings		 */ {	maxScores	: this.settings.maxScoresPerGame
															,	avatarSize	: this.settings.avatarSize
															,	period		: this.settings.scoresPeriod
															}
									);

	r.boss = this;
	r.repeater.game = oGame;
	r.repeater.onItemDataBound = function(item)
	{
		Object.extend(item.dataItem, this.game);
	}
	r.onDataBound = function(content)
	{
		//todo - externalize this event for customizations
		if (content.items.length == 0)
		{
			this.targetElement = "junkYard";
		} 
		else
		{
			this.targetElement = "oGameHighScore_" + this.boss.itrSlotIndex++;
			$(this.targetElement).parentNode.style.display = "";
		}
		
		
	}

}
/**
 *
 */
 UI.Community.HallOfFame.prototype.onComplete = function()
{
	//prepare the slot-index for the onRender of the responses
	this.itrSlotIndex = 0;
	// fire the requests
	var isCached = true;
	var i; 
	this.log.debug("applying async requests, total: " + this.HighScoreRequests.length );
	for(i = 0; i < this.HighScoreRequests.length ; i++)
	{
		this.HighScoreRequests[i].apply(isCached);
	}
}
//--/UI.Community.HallOfFame------------------------------------------------------------
/******************UI.Community.js - End *********************/
/******************MaxPlayersConfig.js - Start *********************/
Project.defaultMaxPlayersForLobbies = 3000;
Project.defaultMaxPlayersForOpenRooms = 100;
Project.defaultMaxPlayersForRestrictedRooms  = 200;

/******************MaxPlayersConfig.js - End *********************/
/******************CommonUA.js - Start *********************/
// JSon Function to get User Details //
//-----------------------------------//

/* ----- Avatar -----------------------------------

   Avatar will return as image or flash in HTML format
   Parameters:1. HTML Element with ID, (example: <td id="test"> - send "test" as parameter)
   ---------- 2. avatar size (example: UA.User.Avatar.Size.Size150x200)
  
  call example: var userAcct = new uaAvatar("GetAvatar_Result",UA.User.Avatar.Size.Size150x200);
  
*/
uaAvatar = function uaAvatar(htmlElement,avatarSize)
{
	
	this.id = htmlElement;   // id of the html element
	this.oElement = $(this.id);  // reference to html Element
	this.size = avatarSize; // size of Avatar
	
	this.Init();
}

uaAvatar.prototype.errorMessage = "ERROR"; //Error message when we have problem with GetUserMedals (from product)
// Initialize object (get data and set call back functions)
uaAvatar.prototype.Init = function()
{
	this.user = new UA.User();
	this.user.oElement = this.oElement;
	this.user.errorMessage = this.errorMessage;
	this.user.GetAvatar(this.size, this.GetAvatar_onSuccess, this.GetAvatar_onFailure, this.onAvatarTimeout); 
	
	
}

// callback function  - avatar success
uaAvatar.prototype.GetAvatar_onSuccess = function(request)
{
	
	this.oElement.innerHTML = request.avatar;
}

// callback function  - avatar fail
uaAvatar.prototype.GetAvatar_onFailure = function(request)
{
	this.oElement.innerHTML = this.errorMessage;
}

// callback function  - avatar timeout
uaAvatar.prototype.onAvatarTimeout = function()
{
	this.oElement.innerHTML = this.errorMessage;
}

// -----------End Avatar---------------------------------------------

/* ----- Avatar studio (FAS)-----------------------------------

   Avatar Studion will return flash in HTML format
   Parameters:1. HTML Element with ID, (example: <td id="FAS"> - send "FAS" as parameter)
  
  call example: var FAS = new uaFAS("FAS");
  
*/

uaFAS = function uaFAS(htmlElement)
{
	
	this.oElement = $(htmlElement);  // reference to html Element
	this.user = new UA.User();
	this.user.oElement = this.oElement;
	uaFAS.prototype.oFasObj = this.oElement;
	this.user.errorMessage = this.errorMessage;
	this.user.oFAS = "";
	this.user.GetAvatarStudio(this.GetAvatarStudio_onSuccess, this.GetAvatarStudio_onFailure, this.GetAvatarStudio_onTimeout);
	
}

uaFAS.prototype.errorMessage = "ERROR"; //Error message when we have problem with GetUserMedals (from product)
uaFAS.prototype.oFasObj = "";
uaFAS.prototype.oFasSave = "";
// callback function  - avatar studio success
uaFAS.prototype.GetAvatarStudio_onSuccess = function(request)
{
	var preLoadFlash = request.avatarStudio;
	//Save FAS before replace with PreLoad Flash
	uaFAS.prototype.oFasSave = preLoadFlash;
	/* swf replace occurs 2 times*/
	preLoadFlash = preLoadFlash.replace('<object ','<object id="FAS_Obj" ');
	/* load HTML Tag with the PreLoader (PreLoader will call FAS_Prefetch_Complete upon complete ) */
	this.oElement.innerHTML = preLoadFlash;
	
}

// callback function from Flash PreLoader - will load the FAS into HTML Tag.
uaFAS.prototype.FAS_Obj_DoFSCommand = function(command, args)
{
	if(command=="FAS_Prefetch_Complete")
	{
		this.oFasObj.innerHTML = this.oFasSave;
	}
}


// callback function  - avatar studio fail
uaFAS.prototype.GetAvatarStudio_onFailure = function(request)
{
	this.oElement.innerHTML = this.errorMessage;
}

// callback function  - avatar studio timeout
uaFAS.prototype.GetAvatarStudio_onTimeout = function()
{
	this.oElement.innerHTML = this.errorMessage;
}


/*
   -------------------------------------------------------------------
   ------ Get User Details --------
   All parameters are HTML Elements
   
   BEFORE you initiate getDetails, please load the following parameters as you need (load only the parameters you need)
   each parameter will represent the HTML Tag ID - 
   (copy the following into the calling page ONLY the values you need and replace "" with HTML Tag you need)
   ----------------------------------------------
   the parameters(Globals):
   ----------------
    uaGetUserDetails.prototype.age = "";// -> return the user Age
	uaGetUserDetails.prototype.gender = "";// -> return the user gender as string ("Male"/"Female"/"Unspecified")
	uaGetUserDetails.prototype.birthdate = "";// -> return full birthdate in format "DD/MM/YYYY")
	uaGetUserDetails.prototype.country = "";// -> return country name (example: "France")
	uaGetUserDetails.prototype.zipCode = "";// -> return zip code
	uaGetUserDetails.prototype.nickname = "";// -> return nickname
	uaGetUserDetails.prototype.newsletterSend = "";// -> return true/false
	uaGetUserDetails.prototype.acceptedTermsAndConditions = "";// -> return true/false
	uaGetUserDetails.prototype.birthDD = "";// -> return birthdate Day
	uaGetUserDetails.prototype.birthMM = "";// -> return birthdate Month
	uaGetUserDetails.prototype.birthYYYY = "";// -> return birthdate Year
	uaGetUserDetails.prototype.countryCode = "";// -> return country code (for example "FR")
   
    call example: var userDetails = new uaGetUserDetails();
    
    
              
*/

uaGetUserDetails = function uaGetUserDetails(ageID,genderID,birthdateID,countryID,zipID,nickNameID,newsletterSendID,acceptedTermsAndConditionsID,termsAndConditionsVersionID,birthDD,birthMM,birthYYYY,countryCode)
{	
	this.user = new UA.User();
	
	// Parameters - assign to User
	this.user.age=$(this.age);
	this.user.gender = $(this.gender);
	this.user.birthdate= $(this.birthdate);
	this.user.country= $(this.country);
	this.user.zipCode= $(this.zipCode);
	this.user.nickname= $(this.nickname);
	this.user.newsletterSend = $(this.newsletterSend);
	this.user.acceptedTermsAndConditions = $(this.acceptedTermsAndConditions);
	this.user.termsAndConditionsVersion = $(this.termsAndConditionsVersion);
	this.user.birthDD = $(this.birthDD);
	this.user.birthMM = $(this.birthMM);
	this.user.birthYYYY = $(this.birthYYYY);
	this.user.countryCode = $(this.countryCode);

	this.user.GetUserDetails(this.GetUserDetails_onSuccess, this.GetUserDetails_onFailure, this.onDetailsTimeout);

}
// Globals should be loaded from outside as following (HTML Elements):
uaGetUserDetails.prototype.age = "";
uaGetUserDetails.prototype.gender = "";
uaGetUserDetails.prototype.birthdate = "";
uaGetUserDetails.prototype.country = "";
uaGetUserDetails.prototype.zipCode = "";
uaGetUserDetails.prototype.nickname = "";
uaGetUserDetails.prototype.newsletterSend = "";
uaGetUserDetails.prototype.acceptedTermsAndConditions = "";
uaGetUserDetails.prototype.birthDD = "";
uaGetUserDetails.prototype.birthMM = "";
uaGetUserDetails.prototype.birthYYYY = "";
uaGetUserDetails.prototype.countryCode = "";


uaGetUserDetails.prototype.GetUserDetails_onSuccess = function(request)
{
	if (this.age != null)
	{
		Element.setText(this.age,request.age);
	}
	if (this.gender != null)
	{
		Element.setText(this.gender,request.gender);
	}
	if (this.nickname != null)
	{
		Element.setText(this.nickname,request.nickname);
	}
	if (this.birthdate != null)
	{
		Element.setText(this.birthdate,request.birthDayOfMonth + '/' + request.birthMonth + '/' + request.birthYear);
	}
	if (this.country != null)
	{
		// country will return country name (for example: "France")
		Element.setText(this.country ,request.country); 
	}
	if (this.countryCode != null)
	{
		// countryA2 will return country ID (for example: "FR" for France)
		Element.setText(this.countryCode ,request.countryA2); 
	}
	if (this.zipCode != null)
	{
		Element.setText(this.zipCode ,request.zipCode);
	}
	if (this.newsletterSend != null)
	{	
		this.newsletterSend.checked = (request.emailOptIn.toLowerCase()=="true")
	}
	
	if (this.acceptedTermsAndConditions != null)
	{

		this.acceptedTermsAndConditions.checked = (request.acceptedTermsAndConditions.toLowerCase()=="true");

	}
	if (this.termsAndConditionsVersion != null)
	{
		this.termsAndConditionsVersion.checked = (request.termsAndConditionsVersion.toLowerCase()=="true");
	}
	if (this.birthDD != null)
	{
		Element.setText(this.birthDD,request.birthDayOfMonth);
	}
	if (this.birthMM != null)
	{
		Element.setText(this.birthMM,request.birthMonth);
	}
	if (this.birthYYYY != null)
	{
		Element.setText(this.birthYYYY,request.birthYear);
	}
	
}

uaGetUserDetails.prototype.GetUserDetails_onFailure = function(request)
{
 // DO nothing
}

uaGetUserDetails.prototype.GetUserDetails_onDetailsTimeout = function(request)
{
 // DO nothing
}

//-----END Get User Details------------------------------------------

/*
  -------------------------------------------------------------------
  --- Get Medal Details ----
  All parameters are HTML Elements
call example:  var userMedals = new uaGetUserMedals("medal_image","medal_game_name","medal_rank","<%=me.ImageGraphicsPath()%>");
  
*/

uaGetUserMedals = function uaGetUserMedals(medalImageID,skuID,medalID,imagePath)
{
	this.user = new UA.User();
	this.user.GetHighestMedal(this.GetUserMedals_onSuccess, this.GetUserMedals_onFailure, this.onDetailsTimeout);
	
	// Parameters - assign to HTML Element
	this.medalImage=$(medalImageID);
	this.skuID=$(skuID); 
	this.medalID=$(medalID);
	this.imagePath = imagePath;
		
	// Parameters - assign to User
	this.user.medalImage=this.medalImage;
	this.user.skuID = this.skuID;
	this.user.medalID= this.medalID;
	this.user.imagePath=this.imagePath;
	this.user.errorMessage = this.errorMessage;
	this.user.noDataMessage = this.noDataMessage;
}

uaGetUserMedals.prototype.errorMessage = "ERROR"; //Error message when we have problem with GetUserMedals (from product)
uaGetUserMedals.prototype.noDataMessage = "No_MEDAL"; // No Data message (no medals)

uaGetUserMedals.prototype.GetUserMedals_onSuccess = function(request)
{
	
	var gameDetailsArr=	GameCatalog.Game.All.BySku[request.gameSku];//oGameDetails.getGameDetails(request.gameSku);
	
	if (gameDetailsArr != null)
	{
		// 0,3 are temp values untill we get gamesDetailsArr from product
		this.skuID.innerHTML = gameDetailsArr.name;
		this.skuID.href = gameDetailsArr.gamePageURL;
		// User Ranking - select Image to display (image names are hard coded as requested)
		var userRanking = request.userRanking;
		this.medalImage.innerHTML = "<img src='" + TC.UserMedals.getMedalByRanking(userRanking).img + "' alt=''  border='0'>"; 
	}
	else // No Data
	{
		this.skuID.innerHTML =  this.errorMessage;//this.noDataMessage;
	}
	
		
}

uaGetUserMedals.prototype.GetUserMedals_onFailure = function(request)
{
	switch (request.Status)
	{
		case "PERSONAL_DETAILS_NOT_FOUND":
			this.medalImage.innerHTML = this.noDataMessage;
			break;
		default:
		this.medalImage.innerHTML = this.errorMessage;
	}
	
}

uaGetUserMedals.prototype.GetUserMedals_onDetailsTimeout = function(request)
{
	this.medalImage.innerHTML = this.errorMessage;
}
//-----End Get Medal details------------------------------------------

/*
	--------------------------------------------------------------------
	------ rightbar------
	rightBar - this object will update right bar by changing its class to highlighted 
	Parameters: 1.sPath =  window.location.pathname
	----------- 2.objDocument = document
*/
function rightBar()
{
	var sPage = window.location.pathname;
	sPage = sPage.substring(sPage.lastIndexOf('/') + 1).toLowerCase();

	var oPages = { line1:  "profilesummary.aspx"
				 , line2:  "profilepersonalinfo.aspx"
				 , line3:  "profiletokens.aspx"
				 , line4:  "profileavatar.aspx"
				 , line5:  "profilerecentgames.aspx"
			     };

	var i = 1, e, itrLine;
	while(true)
	{
		itrLine = "line" + i++;
		
		e = $(itrLine);
		if(! e ) break;

		e.className = (oPages[itrLine] == sPage)? "ifNavMenuSelItem" : "ifNavMenuRegItem";
	}
	
/*	// set current page highlighted
	switch(sPage)
	{
		case "profilesummary.aspx"		: sLineName = "line1"; break;
		case "profilepersonalinfo.aspx"	: sLineName = "line2"; break;
		case "profiletokens.aspx"		: sLineName = "line3"; break;
		case "profileavatar.aspx"		: sLineName = "line4"; break;
		case "profilerecentgames.aspx"  : sLineName = "line5"; break;
	}
	
	$(sLineName).className="ifNavMenuSelItem";*/
}
//-----End Right Bar---=------------------------------------------

/*
	--------------------------------------------------------------------
	------ GET USER GAMES------
	UaGetUserGames - this Object will get html templates (item & alternate item)
					 and will create a list of downloded games
	Parameters: 1.sTableName - table id (where the items will be added)
	----------- 2.sItemTemplate - (InnerHtml of item template)
				3.sAlterTemplate - (InnerHtml of alternate item template)
				4.maxRowsToShow - maximum rows to show in table.
	** don't forget to load globals
	HTML Place Holders: (put the following anyware on the Template, and they will be replaced with values)
	-------------------
						GAME_THUMB				game thumbnailSmall image
						GAME_DOWNLOAD_URL		game downloadURL
						GAME_NAME				game name
						GAME_PAGE_URL			gamePageURL
						GAME_CHECKOUT_URL		buyURL
						GAME_DOWNLOAD_EVENTS	downloadEvents
						GAME_EXECUTABLE_SIZE	game exe size
						CATEGORY_NAME			game category (ganre)
						CATEGORY_URL			game categoryURL
						
						GAME_EXPIRE_TIME		time left for the trial
						GAME_BUY_PLAY_TEXT      play/buy text
						GAME_BUY_PLAY_LINK		play/but HREF
						GAME_BUY_PLAY_IMAGE		play/buy image
						GAME_EXPIRED_TIME_CLASS_NAME   time expired class name
						
    Translations: (all translations are globals you need to update before calling this object)
    ------------- (copy the following into the calling page and replace upper case word with values)
				  (** translate only the values you need in your template)
				  
					UaUserDownloadedGames.playTranslate = "PLAY";
					UaUserDownloadedGames.buyTranslate = "BUY";
					UaUserDownloadedGames.minTranslate = "MIN";
					UaUserDownloadedGames.trialTranslate = "TRIAL_EXPIRED";
					UaUserDownloadedGames.unlimitedTranslate = "UNLIMITED";
					UaUserDownloadedGames.buyImage = "general/arrow2_right.gif";
					UaUserDownloadedGames.playImage = "general/arrow1_up.gif";
					UaUserDownloadedGames.trialUnlimitedClassName="dataTable1CellText2";
					UaUserDownloadedGames.trialExpiredClassName="dataTable1CellText4";
					UaUserDownloadedGames.trialNormalClassName="dataTable1CellText1";	
*/
UaUserDownloadedGames = function UaUserDownloadedGames(sTableName,sItemTemplate,sAlterTemplate,maxRowsToShow)
{

	// Parameters 
	this.theTable = $(sTableName);
	this.itemTemplate=sItemTemplate;
	this.itemAltTemplate=sAlterTemplate;
	this.maxRowsToShow = maxRowsToShow;
	
	//this.theTableBody = this.theTable.tBodies[0]; // reference to html table body
	
	//Place Holders - all values in HTML Template will be replace with values
	this.placeHolders = {
							GAME_THUMB:				"smallThumbnail"
						   ,GAME_NAME:				"name"
						   ,GAME_PAGE_URL:			"gamePageURL"
						   ,GAME_CHECKOUT_URL:		"buyURL"
						   ,CATEGORY_NAME:			"categoryLocalizedName"
						   ,GAME_SKU:				"sku"
						 }
	
					 
	//Load Table
	this.loadTable();
}

// Globals (translations) should be loaded from outside as following:
// 

UaUserDownloadedGames.prototype.playTranslate = "PLAY";
UaUserDownloadedGames.prototype.buyTranslate = "BUY";
UaUserDownloadedGames.prototype.minTranslate = "MIN";
UaUserDownloadedGames.prototype.trialTranslate = "TRIAL_EXPIRED";
UaUserDownloadedGames.prototype.unlimitedTranslate = "UNLIMITED";
UaUserDownloadedGames.prototype.buyImage = "general/arrow2_right.gif";
UaUserDownloadedGames.prototype.playImage = "general/arrow1_up.gif";
UaUserDownloadedGames.prototype.trialUnlimitedClassName="dataTable1CellText2";
UaUserDownloadedGames.prototype.trialExpiredClassName="dataTable1CellText4";
UaUserDownloadedGames.prototype.trialNormalClassName="dataTable1CellText1";
UaUserDownloadedGames.prototype.channelID="111"; //Default value
//Load table
UaUserDownloadedGames.prototype.loadTable = function()
{	
	
	var InstalledGames = getGamesListForChannel(this.channelID); //goes to Odessey ActiveX and get the list from client computer
										// JS reference is needed to :"/Javascript/Activex/OdysseyActivex.js"
	var listedGames = 0;
	var isAlternate = false;
	var sHTML="";
	
	for (var i = 0; i < InstalledGames.length; i++)
	{
			
		sHTML += this.BuildTableRowHTML(-1, i,InstalledGames[i],isAlternate)
		
		if (isAlternate==false)
		{
			isAlternate = true;
		}
		else
		{
			isAlternate = false;
		}
		
		listedGames ++;
		if (listedGames == this.maxRowsToShow)
		{
			break; // prevent show more then X rows in table
		}
		
		
	}

	this.theTable.innerHTML = sHTML;
	
}

UaUserDownloadedGames.prototype.BuildTableRowHTML = function(where, gameIndex,sku,isAlternate)
{
	var newCell;
	var gameSKU = 0; // use as CONST
    var gameDetails = this.getGameDetails(sku[gameSKU]);
    var bReturnValue = "";
    var currTemplate;  
    
    if (gameDetails!= null)
    {
		//Change class for alternate rows
		if (isAlternate)
		{
			currTemplate = this.itemAltTemplate;
		}
		else
		{
			currTemplate = this.itemTemplate;
		}
	    	    
		//replace all placehoders with gameDetails info
		var placehoder, replacment;
		for(placehoder in this.placeHolders)
		{
			replacment = gameDetails[this.placeHolders[placehoder]]
			if(replacment)
			{
				currTemplate = currTemplate.replace(new RegExp(placehoder,"g"), replacment);
			}
		}
				
		//Add Odessey ActiveX Data
		// Time left
		var strTimeLeft =sku[gameExpiredTime];
		var expTimeClassName;
		if (sku[gameIsRegistered]== false) 
		{
			if (sku[gameExpiredTime] == 0)// Expired and not registered
			{
				expTimeClassName = this.trialExpiredClassName;
				strTimeLeft += "&nbsp;(" + this.trialTranslate +")";
			}
			else if (sku[gameExpiredTime] >= 0)// Time left and not Registered
			{
				expTimeClassName = this.trialNormalClassName;
				strTimeLeft += "&nbsp;" + this.minTranslate ;
			}
		}
		else
		{
			// Registered Game
			expTimeClassName = this.trialUnlimitedClassName;
			strTimeLeft=this.unlimitedTranslate;
		}
		currTemplate = currTemplate.replace(/GAME_EXPIRE_TIME/g, sku[gameExpiredTime]);
		currTemplate = currTemplate.replace(/GAME_EXPIRED_TIME_CLASS_NAME/g, expTimeClassName);	
		     
		//Link to play/buy
	
		if (sku[gameExpiredTime]== 0 && sku[gameIsRegistered]== false)
		{
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_LINK/g, gameDetails.buyURL);
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_TEXT/g, this.buyTranslate);
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_IMAGE/g, this.buyImage);
		}
		else
		{
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_LINK/g, 'Javascript:launchGame(" + sku[gameSKU] + ");');
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_TEXT/g, this.playTranslate);
			currTemplate = currTemplate.replace(/GAME_BUY_PLAY_IMAGE/g, this.playImage);
		}
		
		
		bReturnValue=currTemplate;
   } 
   return bReturnValue;   
}

// Get Game(sku) Details
UaUserDownloadedGames.prototype.getGameDetails = function(sku)
{
	//page should have reference to game catalog
	return GameCatalog.Game.All.BySku[sku];
}



/******************CommonUA.js - End *********************/
