function $(e){if(typeof e=='string')e=document.getElementById(e);return e};
function trim(str){return str.replace(/^\s+|\s+$/g, '');}
String.prototype.trim = function(str){trim(str)};
String.prototype.endsWith = function(str){return (this.match(str+"$")==str)}
function emp($val){
    return ($val==null || $val==undefined || $val==0 || $val=='');
}

/*login (qmsgl), error (qmsge) ve loading (qmsgo) messages at given object (o)*/
function qmsgl(o, _plc){qmsg.showAtObj(o,__userLoginMsg,3000,_plc);}
function qmsge(o, e, _plc){var m=__errMsg; if(e)__errMsg+=' ('+e+')'; qmsg.showAtObj(o,m,2000,_plc);}
function qmsgo(o, _plc){qmsg.showAtObj(o,__loadingMsg,0,_plc);}

/****************************************************************************/
/* forms                                                                     */
/****************************************************************************/

function gosInArray(v, a){for(k in a){if(a[k]==v) return true;} return false;}
var reUsername=/^([a-zA-Z0-9_-]+)$/;
var reAlphanum=/^([a-zA-Z0-9]+)$/;
var reEmail=/^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,6})+$/;

function gosVldMsg(o, r){ if($(o)) $(o).style.display=(r)? '':'none'; return r; }
function gosVldErrMsg(o, r){ if($(o)) $(o).style.display=(r)? 'none':''; return r; }
function gosGetRadioVal(o){r="";l=o.length;if(l==undefined) return (o.checked)? o.value:r; for(i=0;i<l;i++) if(o[i].checked) return o[i].value; return r;}
function gosVldMsgClose(oa){for(i in oa) gosVldMsg(oa[i], false);}

/****************************************************************************/
/* tabs                                                                     */
/****************************************************************************/

function gosTab(tabObj, callback){
    liObj = gosFindParentTag(tabObj, 'li');
    if(liObj){
        var sibNodes = liObj.parentNode.childNodes;
        for(var sib in sibNodes) sibNodes[sib].className = '';
        liObj.className='selected';
    }
    if(callback) window[callback]();
    return false;
}



/* favorites *************************************************************** */
// add to favorites, remove from favorites
// checks button's class name to decide to add ro remove
// if it is delfav removes the fame from favorites, else add to fav
function gosFav(btn, eu, cls, divId){
    if(!__userlogin){
        qmsgl(btn,'fav');
    }
    else{
        var url, f;
        btn.disabled = true;
        qmsgo(btn, 'fav');
        if(btn.className=='dfav'){
            url=BASE_PATH+'/ajax/favorites?cmd=del&u='+eu;
            f = function(r){
                var rcode = parseInt(r);
                if(rcode>0){ var div = $(divId); try{div.parentNode.removeChild(div);}catch(e){} qmsg.close();}
                else if(rcode==M_NOAUTH){qmsgl(btn,'fav'); btn.disabled=false;} 
                else{ qmsg.showAtObj(btn, __errMsg + '('+rcode+')', 2000, 'fav'); btn.disabled=false; }
            }
        }
        else{
            url=BASE_PATH+'/ajax/favorites?cmd=add&u='+eu;
            f = function(r){
                rcode = parseInt(r);
                if(rcode==M_NOAUTH){qmsgl(btn,'fav'); btn.disabled=false;}
                else if(rcode<0 && rcode!=M_DUPENT){qmsge(btn, r, 'fav'); btn.disabled=false;}
                else{
                    qmsg.showAtObj(btn, 'Thanks:)', 1000, 'fav');
                    if(cls) btn.className=cls;
                }
            } //end of function
        }
        ajax.get(url, f);
    }
}


/****************************************************************************/
/* game page functions                                                      */
/****************************************************************************/

//add to favorites for game page
function gosFavSingle(btnObj){
    gosFav(btnObj, __favKey, 'gto-favadded');
}

/* star rating  ****************************************************************/
gsrate = new function GosStarRate(){
    var rateText = {'1':'Poor', '2':'Nothing Special', '3':'Worth Playing', '4':'Cool', '5':'Awesome'};
    var alreadyRated=false;
    var givenRate=0;
    var objId='star3';

    this.mover = function(_r){this.showRate(_r);}
    this.mout = function(){this.showOrgRate(__gameRate, ' ');}

    /**
     * rate game
     * @param no    given rate
     * @param cmd
     */
    this.rate = function(_r){
        if(!alreadyRated){
            alreadyRated=true;
            /*if(readCookie('rate_'+__gameUname)!=null){ this.showResult(M_DUPENT); return 1;}*/
            givenRate = _r;
            ajax.get(BASE_PATH+'/ajax/rating?uname='+__gameUname+'&rate='+_r, gsrate.showResult);
            qmsgo($(objId));
        }
    }


    this.showResult = function(_result){
        if(this!=gsrate) gsrate.showResult(_result);
        else{
            _result = parseInt(_result);
            var msg="";
            switch(_result){
                case M_SUC: msg='Thanks!'; alreadyRated=true; break;
                case M_DUPENT: msg='Rated already!'; alreadyRated=true; break;
                case M_NOAUTH: msg='Login or <a href="'+BASE_PATH+'/signup.htm">register</a> to rate'; alreadyRated=true; break;
                default: msg='Oops! Error.';
            }
            this.showRate(givenRate);
            qmsg.showAtObj($(objId), msg, 2000);
        }
    }

    this.showRate = function(_r){
        if(_r>=0) this.showStars(_r);
    }

    this.showOrgRate = function(_r){
        this.showStars(_r, true);
    }

    this.showStars = function(_r, _s){
        if(!alreadyRated){
            if(_r==0) _r=3;
            for(i=0; i<5; i++){
                var c = "ra0";
                if((_r-i)>0) c =((_r-i)==0.5)? "ra1":"ra2";
                if(!_s) c+='m';
                $("star"+(i+1)).className = c;
            }
        }
    }

    /*this.showText = function(_r){ if(!alreadyRated){this.showInfo(rateText[_r+'']);}}
    this.showInfo = function(text){$('ginf-ratetxt').innerHTML=text;}*/
}


/* page components *********************************************************/
/**
 * show or hide game walkthough
 */
function gosShowWalkthrough(){ toggleDisplay('wtdiv'); }


/* tabs & reviews **********************************************************/

/**
 * related games tab
 */
function gosTabRelGames(){
    $('tab-content-rel').style.display = '';
    $('tab-content-rev').style.display = 'none';
    if($('tab-content-excl')) $('tab-content-excl').style.display = 'none';
}

/**
 * reviews tab
 */
var __revTabShown=false ;__revTabShown = false;
function gosTabReviews(){
    $('tab-content-rev').style.display = '';
    $('tab-content-rel').style.display = 'none';
    if($('tab-content-excl')) $('tab-content-excl').style.display = 'none';
    if(!__revTabShown){ __revTabShown=true; ajax.update(__reviewsUrl, 'tab-content-rev');}
}

function gosTabReviewsPage(pageNo){
    ajax.update(__reviewsUrl+'&p='+pageNo, 'tab-content-rev');
}


function gosTabExclusive(){
    $('tab-content-rev').style.display = 'none';
    $('tab-content-rel').style.display = 'none';
	$('tab-content-best').style.display = 'none';
    $('tab-content-excl').style.display = '';
}

function gosTabBest(){
    $('tab-content-rev').style.display = 'none';
    $('tab-content-rel').style.display = 'none';
	$('tab-content-excl').style.display = 'none';
    $('tab-content-best').style.display = '';
}

/**
 * post a review
 */
function gosPostReview(formObj){
    if(!__userlogin){
        gosReviewMsg(__userLoginMsg, true);
    }
    else if(formObj.reviewText.value==''){ 
        gosReviewMsg('Your review text is empty!');
    }
    else{
        $('reviewBtn').disabled = true;
        formObj.gameId=__gameUname;
        var url = formObj.getAttribute('action');
        var rfunc = function(r){
            var d=false;
            if(r==M_SUC){ ajax.update(__reviewsUrl, 'tab-content-rev');d=true;}
            else if(r==M_NOAUTH){gosReviewMsg(__userLoginMsg, true);}
            else if(r==M_TOOMUCHREV){gosReviewMsg('So many posts in last few minutes', true);}
            else{ gosReviewMsg('Error in your inputs.', true); }

            $('reviewBtn').disabled = d;
        }
        ajax.post(url, rfunc, ajax.serialize(formObj));
    }
    return false;
}

/**
* show postReview result
*/
function gosReviewMsg(_msg, _e){
    var q=new GosQMsg(); q.showInside($('rev-result'), _msg, 10000);
    if(_e) q.changeClassName('qmsger');
}

/**
 * vote review
 */
function gosVoteRev(rev, vote){
    vote = (vote>0)? 1:-1;
    var sd = $('rvs'+rev); //vote result
    
    var rvtu = $('rvtu'+rev);
    var rvtd = $('rvtd'+rev);
    var rvt = (vote<0)? rvtu:rvtd;

    if(!__userlogin){ qmsgl(rvt); return; }

    //lo.style.display = '';
    rvtu.disabled = true;
    rvtd.disabled = true;
    
    qmsgo(rvt);

    //ajax callback function
    var vfunc = function(r){
            //lo.style.display = 'none';
            rvtu.disabled = false;
            rvtd.disabled = false;
            if(r==M_SUC){
                sd.innerHTML = parseInt(sd.innerHTML)+vote;
                qmsg.showAtObj(rvt, "Thanks:)", 1000);
            }
            else if(r==M_NOAUTH){ qmsgl(rvt); }
            else if(r==M_DUPENT){ qmsg.showAtObj(rvt, 'You have already voted this review.', 2000); }
            else{ qmsg.showAtObj(rvt, __errMsg + "("+parseInt(r)+")", 2000); }
        }
    var url=BASE_PATH+'/do/review?cmd=vote&r='+rev+'&v='+vote+'&k='+__reviewVoteKey;
    ajax.get(url, vfunc);
 }


 
/****************************************************************************/
/* common functions                                                         */
/****************************************************************************/

/**
 * bookmark page
 **/
function bookmarkPage(url, title) {
    //firefox
    if (window.sidebar) {
        window.sidebar.addPanel(title, url, "");
    //ie
    } else if( window.external ) {
        window.external.AddFavorite( url, title); }
    //opera
    else if(window.opera && window.print) {
        	var elem = document.createElement('a');
            elem.setAttribute('href',url);
            elem.setAttribute('title',title);
            elem.setAttribute('rel','sidebar');
            elem.click();
    }

}

function gosFindParentTag(obj, tag){
    tag = tag.toLowerCase();
    do{
        obj=obj.parentNode;
        if(obj && obj.tagName.toLowerCase()==tag) return obj;
    }while(obj)
    return null;
}

//http://blog.firetree.net/2005/07/04/javascript-find-position/
//by Peter-Paul Koch & Alex Tingle
function gosFindObjLoc(_obj){
    var loc=new Object();
    loc.x = 0; loc.y = 0;
    if(_obj.offsetParent){
        do{
          loc.x += _obj.offsetLeft;
          loc.y += _obj.offsetTop;
          _obj = _obj.offsetParent;
        }while(_obj.offsetParent);
    }
    else{
        if(_obj.x) loc.x += _obj.x;
        if(_obj.y) loc.y += _obj.y;
    }
    return loc;
}

/*
 * find referrer. return null if no referrer exists
 * */
function gosFindRefr(){
    refr=document.referrer;
    if (refr != ''){var e=new RegExp("(https|http|ftp):\/\/"); host = refr.replace(e, "");host = host.replace(/\/.*/, "");return host;}
    return null;
}

function toggleDisplay(o){o=$(o); o.style.display=(o.style.display=='none')? '':'none'; }


/************************************************************************** */
/* smooth scrolling                                                         */
/************************************************************************** */
var ss=new function(){
    var intvo;
    var o;
    var desty;
    this.scroll=function(_o){
        o=$(_o)
        var loc=gosFindObjLoc(o);
        desty = loc.y;
        intvo = setInterval('ss.intv()',10);
    }
    this.intv=function(){
        var y1=this.getTopOff();
        var am=(desty-y1)*.15;
        if(am>30) am=30; if(am<3) am=3;
        window.scrollTo(0, y1 + am);
        var y2=this.getTopOff();
        if(y1==y2 || y2>desty){
            clearInterval(intvo);
            window.scrollTo(0, desty);
        }
    }

    this.getTopOff= function() {
        if (document.body && document.body.scrollTop)
          return document.body.scrollTop;
        if (document.documentElement && document.documentElement.scrollTop)
          return document.documentElement.scrollTop;
        if (window.pageYOffset)
          return window.pageYOffset;
        return 0;
    }
}


/************************************************************************** */
/* cookie functions: http://www.quirksmode.org/js/cookies.html              */
/************************************************************************** */
function createCookie(name,value,days) {if (days) {var date = new Date();date.setTime(date.getTime()+(days*24*60*60*1000));var expires = "; expires="+date.toGMTString();}else var expires = "";document.cookie = name+"="+value+expires+"; path=/";}
function readCookie(name) {var nameEQ = name + "=";var ca = document.cookie.split(';');for(var i=0;i < ca.length;i++) {var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length);if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);}return null;}
function eraseCookie(name) {createCookie(name,"",-1);}



/****************************************************************************
 * miniajax

ajax.x - The XMLHttpRequest object (or MS equivalent) used for communication

ajax.serialize(f)
f = the form element you wish to be serialized
This function serializes all the fields in a form so that
they can be passed as a query string in the form 'arg1=val1&arg2=val2'.

ajax.get(url, func)
url = the url to query (can contain arguments after a '?')
func = the function to call once the response is returned
This function uses a GET request to query the specified url and
return a response to the specified function.

ajax.gets(url)
url = the url to query (can contain arguments after a '?')
This function uses a GET request to query the specified url and
return a response synchronously. Use this sparingly,
as synchronous calls can lock up the browser.

ajax.post(url, func, args)
url = the url to query
func = the function to call once the response is returned
args = a string containing arguments to be passed to the url
This function uses a POST request to query the specified url and
return a response to the specified function.

ajax.update(url, elm)
url = the url to query
elm = the (name of the) element to update
This function uses a GET request to query the specified url and
insert the result into the specified element.

ajax.submit(url, elm, frm)
url = the url to query
elm = the (name of the) element to update
frm = the form element to submit
This function is typically used in the onsubmit handler of a function.
The form is not submitted the usual way; the form is instead serialized using
'ajax.serialize' and submitted using 'ajax.post'.
The result is then inserted into the specified element.
*/
function collect(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};

ajax={};
ajax.x=function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}};
ajax.serialize=function(f){var g=function(n){return f.getElementsByTagName(n)};var nv=function(e){if(e.name)return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);else return ''};var i=collect(g('input'),function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)});var s=collect(g('select'),nv);var t=collect(g('textarea'),nv);return i.concat(s).concat(t).join('&');};
ajax.send=function(u,f,m,a){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText)};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a)};
ajax.get=function(url,func){ajax.send(url,func,'GET')};
ajax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};
ajax.post=function(url,func,args){ajax.send(url,func,'POST',args)};
ajax.update=function(url,elm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.get(url,f)};
ajax.submit=function(url,elm,frm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.post(url,f,ajax.serialize(frm))};

