var app = new App();
var misc = new Misc();
var language = new Language();
var animation = new Animation();
var sprites = Array();
var funnyVideoPlayer = null;
var pageTracker = null;
var browserDetect = null;
var g_request = null;

document.onfocus = g_gotFocus;
document.onblur = g_lostFocus;

/*** Global functions for setInterval/ setTimeout, otherwise issues with using app object ***/

function g_showVote(i) {
    app.showVote(i);
}

function g_selectCaption() {
    app.selectCaption();
}

function g_blinkGlow() {
    app.blinkGlow();
}

function g_getMode() {
    app.getMode();
}

function g_showWinner() {
    app.showWinner();
}

function g_continueCountdown() {
    app.continueCountdown();
}

function g_doRefresh() {
    app.doRefresh();
}

function g_handleSprites() {
    animation.handleSprites();
}

function g_showEntertainment() {
    app.performCall('GetEntertainment', 'app.handleCallbackGetEntertainment', '');
}

function g_moveInEntertainment() {
    app.moveInEntertainment();
}

function g_closeEntertainmentAutomated() {
    app.closeEntertainmentAutomated();
}

function g_handleInRoomPending() {
    app.handleInRoomPending();
}

function g_showEntertainmentIfNotStarted() {
    app.showEntertainmentIfNotStarted();
}

function g_lostFocus() {
    app.hasFocus = false;
}

function g_gotFocus() {
    app.hasFocus = true;
}

function g_handleWindowFocus() {
    if (browserDetect && browserDetect.browser == 'Explorer') {
        app.hasFocus = true;
        window.focus();
        var elm = document.getElementById('caption');
        elm.focus();
    }
    else if (!app.hasFocus) {
        app.hasFocus = true;
        alert( language.get('welcomeStartPlaying') );
    }
}

function g_checkStatus() {
    app.checkStatus();
}

function g_displayStatus() {
    app.displayStatus();
}

function g_languageLoaded() {
    app.initContinue();
}

function g_hideQuickDialog() {
    misc.hideElm('quickDialog');
}


/*** App object ***/

App.prototype.init = function(version, useSandbox) {
    this.version = version;
    this.useSandbox = useSandbox;
    if (this.useSandbox) {
        this.baseUrl = 'http://captionxservice-sandbox.appspot.com/api';
        this.returnUrl = 'http://' + document.domain + '/?sandbox=true';
        this.toggleDoDebug();
    }
    language.callAfterLoaded = g_languageLoaded;
    language.loadByVersion(this.version);
}

App.prototype.initContinue = function(useSandbox) {
    this.defaultCaption = language.get('yourCaptionHere');
    g_checkStatus();
    setInterval('g_checkStatus()', 60 * 1000);
    doDetectBrowser();
    this.getMode();
    // this.showTest();
}

App.prototype.showTest = function() {
    // javascript:app.showVoteAnimation( 2, new Point(470, 270), '', true, 'explosive' );
    this.showVoteAnimation( 2, new Point(470, 270), '', true, 'explosive' );
}

App.prototype.checkStatus = function() {
    var url = '/section/game/status.txt?random=' + escape( Math.round( Math.random() * 100000000 ) );
    if (window.XMLHttpRequest) {
        g_request = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
        g_request = new ActiveXObject('Microsoft.XMLHTTP');
    }
    g_request.onreadystatechange = g_displayStatus;
    g_request.open('GET', url, true);
    g_request.send(null);
}

App.prototype.displayStatus = function() {
    if (g_request.readyState == 4 && g_request.status == 200) {
        var status = g_request.responseText;
        if (status == app.oldStatus) {
        }
        else if (status != '') {
            app.oldStatus = status;
            status += " <br /><a href=\"javascript:misc.hideElm('status')\">[x] close message</a>";
            misc.setHtml('status', status);
            misc.showElm('status');
        }
        else {
            misc.hideElm('status');
        }
    }
}

App.prototype.handleCallback = function(data) {
    this.debug( misc.getFormattedJson(data) );
    var logo = document.getElementById('logo');

    if (data.error) {
        logo.style.top = '60px';

        if (data.error.code == 'NO_LOGIN') {
            this.signInUrl = data.error.url;
            this.signInUrlFacebook = data.error.fburl;
            misc.showElm('dialog');
            misc.showElm('previewLink');
            misc.showElm('instructions');
        }
        else if (data.error.code == 'NO_ROOM') {
            this.data = data;
            this.getRoom();
            misc.hideElm('instructions');
        }
        else if (data.error.code == 'USER_BANNED') {
            this.data = data;
            var blockedMinutes = Math.floor(this.data.error.message / 60) + 1;
            blockedMinutes = (blockedMinutes == 1) ?
                    language.getReplace('minute', 'n', blockedMinutes) : language.getReplace('minutes', 'n', blockedMinutes);
            this.setHtmlShadowed( 'countdown', language.getReplace('blockedMessage', 'blockedMinutes', blockedMinutes) );
            misc.hideElm('instructions');
        }
        this.clearDisplay();
    }
    else {
        logo.style.top = '218px';
        misc.hideElm('instructions');    

        this.data = data;
        this.renameUsersNamed('you');

        this.showUserInfo(this.data.room.mode != 'WINNER');

        this.showTablePlayers();
        if (this.data.usercount && this.data.usercount > this.maxPlayers) {
            document.title = language.get('siteTitle') + ' (' + language.getReplace('aroundPlayersOnline', 'n', this.data.usercount) + ')';
        }
        else {
            document.title = language.get('siteTitle');
        }

        if (this.data.room.mode == 'PENDING') {
            this.pendingCounter++;
            if (this.pendingCounter == 6) { this.pendingCounter = 0; }
            this.startCountdown( Math.floor(data.room.expires) );
            this.clearDisplay();
            if (!this.triggeredPlayerSearchEntertainment) {
                this.triggeredPlayerSearchEntertainment = true;
                setTimeout('g_showEntertainmentIfNotStarted()', 10 * 1000);
            }
        }
        else {

            var startValue = Math.floor(this.data.room.expires) - 1;
            this.secondsLeft = startValue;
            if (startValue <= 1) { startValue = 1; }

            var minSecondsToEnterSomething = 10;
            if ( this.getPlayerActivity() >= 1 || this.sawTextMode ||
                    (this.data.room.mode == 'TEXT' && this.secondsLeft >= minSecondsToEnterSomething) ) {

                misc.hideElm('dialog');

                for (i = 1; i <= this.maxPlayers; i++) {
                    misc.showElm('imageWrapper' + i);
                    misc.showElm('progress' + i);
                }

                switch (this.data.room.mode) {
                    case 'TEXT':
                        this.justShownWinner = false;
                        this.initModeText();
                        this.startCountdown(startValue);
                        break;
                    case 'VOTE':
                        this.justShownWinner = false;
                        this.initModeVote();
                        this.startCountdown(startValue);
                        break;
                    case 'WINNER':
                        this.initModeWinner(startValue);
                        break;
                }
                this.pendingCounter = 0;
            }
            else if (this.inRoomPendingCount == 0) {
                this.inRoomPendingCount = startValue + 2;
                this.handleInRoomPending();
                if (this.data.room.mode == 'VOTE') {
                    setTimeout('g_showEntertainmentIfNotStarted()', 5 * 1000);
                }

                for (i = 1; i <= this.maxPlayers; i++) {
                    misc.hideElm('imageWrapper' + i);
                    misc.hideElm('progress' + i);
                }
            }
        }

        if (this.data.room.signouturl) {
            this.signOutUrl = this.data.room.signouturl;
        }

        if (this.data.room.profile_comment_entry && this.data.room.profile_comment_entry != this.latestProfileCommentKey) {
            this.latestProfileCommentKey = this.data.room.profile_comment_entry;
            var selfPlayer = this.getPlayerSelf();
            if (selfPlayer && selfPlayer.unique) {
                selfPlayer.unique;
                this.showQuickDialog('<p><img src="/image/mail.png" alt="" />&nbsp; ' +
                        '<a href="javascript:app.showProfileHideQuickDialog(' + "'" + selfPlayer.unique + "'" + ')">' +
                        language.get('newProfileComment') + ' :)</a></p>');
                setTimeout('g_hideQuickDialog()', 6000);
            }
        }

        if (this.version != this.data.version) {
            if (this.version) {
                this.showQuickDialog('<p>' + language.get('newVersionAvailable') + '</p>');
                setTimeout('g_doRefresh()', 5000);
            }
            this.version = this.data.version;
        }

    }
}

App.prototype.showProfileHideQuickDialog = function(playerId) {
    misc.hideElm('quickDialog');
    this.showProfile(playerId);
}

App.prototype.showEntertainmentIfNotStarted = function() {
    if (!this.sawTextMode) {
        g_showEntertainment();
    }
}

App.prototype.handleInRoomPending = function() {
    var message = language.get('waitForBeginning');
    numberOfDots = 3 - this.inRoomPendingCount % 3;
    message += misc.getChars('.', numberOfDots);
    this.setHtmlShadowed('countdown', message);

    if (this.inRoomPendingCount <= 0) {
        this.inRoomPendingCount = 0;
        g_getMode();
    }
    else {
        this.inRoomPendingCount--;
        setTimeout( 'g_handleInRoomPending()', 1 * 1000);
    }
}

App.prototype.otherDialogsOpen = function() {
    var dialogIds = new Array('profile', 'avatarSelection', 'entertainment', 'commentDialog', 'comment');
    var somethingOpen = false;
    for (var i = 0; i < dialogIds.length && !somethingOpen; i++) {
        var elm = document.getElementById(dialogIds[i]);
        if (elm && elm.style.display == 'block') {
            somethingOpen = true;
        }
    }
    return somethingOpen;
}

App.prototype.handleCallbackGetEntertainment = function(data) {
    if ( !this.otherDialogsOpen() ) {
        var type = data.entertainment.type;
        var content = data.entertainment.content;
        var html = '';
    
        html += '<a href="javascript:app.closeEntertainmentManually()" class="dialogClose">' +
                '<img src="image/close-small.png" alt="[' + language.get('closeButtonText') + ']" title="" /></a> ';
    
        switch (type) {
            case 'youtube':
                html += '<div id="entertainmentVideo" style="width: ' +
                        this.videoWidth + 'px; height: ' + this.videoHeight + 'px">&nbsp;</div>';
                if (!this.doAutoPlayVideo) {
                    html += '<p id="entertainmentPlay">' +
                            '<img src="/image/play.png" alt="" onclick="app.playVideo()" class="playButton" /></p>' +
                            '<p id="entertainmentLabel"><a href="javascript:app.playVideo()">' +
                            language.get('watchVideoWhileWaiting') + ' :)</a></p>';
                }
                html += '<div id="funny15_volumeControlMainImage" class="on" onclick="javascript:funnyVideoPlayer.toggleSound()">' +
                        '&nbsp;</div>';
                misc.setHtml('entertainment', html);
    
                funnyVideoPlayer = new funny15Player();
                funnyVideoPlayer.width = this.videoWidth;
                funnyVideoPlayer.height = this.videoHeight;
                funnyVideoPlayer.bgcolor = '#A7A7A7';
                funnyVideoPlayer.autostart = this.doAutoPlayVideo;
                funnyVideoPlayer.mode = 'random';
                funnyVideoPlayer.element = 'entertainmentVideo';
                funnyVideoPlayer.cats = 'funny,interesting,-violence';
                funnyVideoPlayer.captionx = true;
                funnyVideoPlayer.reload();
                EEvent.bind(funnyVideoPlayer, 'endVideo', g_closeEntertainmentAutomated);

                break;
        }

        this.entertainmentY = this.entertainmentStartY;
        this.moveInEntertainment();
        misc.showElm('entertainment');
        misc.showElm('entertainmentShade');
        if (pageTracker) { pageTracker._trackPageview('/analytics_api/entertainment/'); }
    }
}

App.prototype.playVideo = function() {
    this.doAutoPlayVideo = true;
    funnyVideoPlayer.playPauseVideo();
    misc.hideElm('entertainmentPlay');
    misc.hideElm('entertainmentLabel');
}

App.prototype.moveInEntertainment = function() {
    var shadeOffset = -25;
    this.entertainmentY += 15;
    if (this.entertainmentY > this.entertainmentEndY) {
        this.entertainmentY = this.entertainmentEndY;
    }

    var elm = document.getElementById('entertainment');
    var elmShade = document.getElementById('entertainmentShade');
    elm.style.top = this.entertainmentY + 'px';
    elmShade.style.top = ( this.entertainmentY + Math.floor(shadeOffset) ) + 'px';

    if (this.entertainmentY < this.entertainmentEndY) {
        setTimeout('g_moveInEntertainment()', 50);
    }
}

App.prototype.closeEntertainmentManually = function() {
    this.doAutoPlayVideo = false;
    this.closedEntertainmentInARow++;
    this.closeEntertainment();
}

App.prototype.closeEntertainmentAutomated = function() {
    var elm = document.getElementById('entertainment');
    if (elm.style.display == 'block') {
        this.closedEntertainmentInARow = 0;
    }
    this.closeEntertainment();
}

App.prototype.closeEntertainment = function() {
    misc.hideElm('entertainment');
    misc.hideElm('entertainmentShade');
    if (funnyVideoPlayer) {
        funnyVideoPlayer.destroy();
        funnyVideoPlayer = null;
    }
    misc.setHtml('entertainment', '&nbsp;'); // ...
}

App.prototype.getYouTubeVideoEmbedHtml = function(videoId, width, height) {
    return '<object width="' + width + '" height="' + height + '">' +
            '<param name="movie" value="http://www.youtube.com/v/' + videoId + '&hl=en&fs=1"></param>' +
            '<param name="allowFullScreen" value="false"></param>' +
            '<embed src="http://www.youtube.com/v/' + videoId + '&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="false" ' +
            'width="' + width + '" height="' + height + '">' +
            '</embed></object>';
}

App.prototype.clearDisplay = function() {
    misc.setHtml('credits', '');
    this.clearCaptions();
    this.showTablePlayers();
    misc.hideElm('userCaption');
}

App.prototype.handleCallbackGetUser = function(data) {
    this.signOutUrl = data.signouturl;
    misc.setHtml('userInfo', '<a href="javascript:app.signOut()" class="lessImportant">' + language.get('signOut') + '</a>');
}

App.prototype.doRefresh = function() {
    window.location.reload(false);
}

App.prototype.clickedCaption = function() {
    if ( this.getUserCaption() == '' ) {
        var elm = document.getElementById('caption');
        elm.select();
    }
}

App.prototype.checkCaptionKey = function(e) {
    var keycode;
    if (window.event) {
        keycode = window.event.keyCode;
    }
    else if (e) {
        keycode = e.which;
    }
    if (keycode == this.keycodeReturn) {
        this.saveCaption();
    }
}

App.prototype.checkCommentKey = function(e) {
    var keycode;
    if (window.event) {
        keycode = window.event.keyCode;
    }
    else if (e) {
        keycode = e.which;
    }
    if (keycode == this.keycodeReturn) {
        this.saveComment();
    }
}

App.prototype.saveCaption = function() {
    if (!this.captionEntered) {
        var text = this.getUserCaption();
        if (text != '') {
            misc.hideElm('userCaption');

            this.showCaption( 'caption' + this.playerPosition, this.getConvertedCaption(text) );

            this.setText(text);
            this.captionEntered = true;
            if (this.countdownSeconds > this.secondsNeededForEntertainment && this.closedEntertainmentInARow < 2) {
                setTimeout('g_showEntertainment()', 3 * 1000);
            }
        }
    }
}

App.prototype.getRoom = function() {
    this.performCall( 'GetRoom', 'app.handleCallback', '&Uri=' + encodeURIComponent(this.returnUrl) );
}

App.prototype.getMode = function() {
    this.performCall('GetMode', 'app.handleCallback', '&Uri=' + encodeURIComponent(this.returnUrl) );
}

App.prototype.forceMode = function(mode) {
    this.performCall( 'ForceMode', '', '&Mode=' + encodeURIComponent(mode) );
}

App.prototype.setText = function(text) {
    this.performCall( 'SetText', '', '&Text=' + encodeURIComponent(text) );
}

App.prototype.setVote = function(userId, playerPosition) {
    if (!app.didVote) {
        this.debug('trying to hide votes... voting for ' + userId);
        this.hideAllVotes();
        this.didVote = true;
        this.performCall( 'SetVote', '', '&User=' + encodeURIComponent(userId) );
        var elm = document.getElementById('caption' + playerPosition);

        var textComment = language.get('comment');
        var textThrowExtra = language.get('throwExtra');
        textComment.replace(' ', '&nbsp;');
        textThrowExtra.replace(' ', '&nbsp;');

        var player = this.getPlayerById(userId);
        if ( !g_getBooleanProperty(player.is_robot) ) {
            elm.innerHTML = elm.innerHTML + ' <span id="addComment">' +
                    '(<a href="javascript:app.addComment()">' + textComment + '</a> ' +
                    language.get('or') + ' ' +
                    '<a href="javascript:app.showActionDialog()">' + textThrowExtra + '</a>)</span>';
        }
    }
}

App.prototype.getPlayerKarma = function() {
    var karma = null;
    var player = this.getPlayerSelf();
    if (player) { karma = player.karma; }
    return karma;
}

App.prototype.getCloseButton = function(elementId) {
    return '<a href="javascript:misc.hideElm(' + "'" + elementId + "'" + ')" class="dialogClose">' +
            '<img src="image/close-small.png" alt="[' + language.get('closeButtonText') + ']" title="" /></a> ';
}

App.prototype.showActionDialog = function() {
    misc.hideElm('addComment');
    var elm = misc.getElementAndCreateIfNeeded('content', 'actionDialog');
    elm.style.display = 'block';
    var s = '';
    s += this.getCloseButton('actionDialog');
    var actions = this.data.room.actions;
    var karma = this.getPlayerKarma();
    var sClass = '';

    s += '<div class="actionInfo"><strong>' + language.get('yourKarma') + '</strong> ' + karma + '</div>';

    s += '<div class="actionDialogTableWrapper">';
    s += '<table>';
    s += '<tr><th colspan="2">' + language.get('extra') + '</th>' +
            '<th class="actionCheck">' + language.get('unlocked') + '</th>' +
            '<th class="actionKarma">' + language.get('karmaNeeded') + '</th></tr>';
    var isAlternateRow = false;
    for (var i = 0; i < actions.available.length; i++) {
        var action = actions.available[i];
        var link = "javascript:app.pickAction('" + action.action + "')";
        sClass = isAlternateRow ? ' class="alternate"' : '';

        s += '<tr' + sClass + '>';
        s += '<td class="actionIcon"><a href="' + link + '"><img src="/image/action/' + action.action + '.png" alt="" /></a></td>';
        s += '<td class="actionName"><a href="' + link + '">&#187; ' + language.get('throw') + ' ' +
                language.get('action_' + action.action) + '</a></td>';
        s += '<td class="actionCheck"><img src="/image/action/checked.png" alt="[' + language.get('yes') + ']" /></td>';
        s += '<td class="actionKarma">' + action.karma + '</td>';
        s += '</tr>';
        isAlternateRow = !isAlternateRow;
    }

    sClass = isAlternateRow ? ' class="alternate"' : '';
    s += '<tr' + sClass + '>';
    s += '<td class="actionIcon"><img src="/image/action/unknown.png" alt="" /></td>';
    s += '<td class="actionName"><em>' + language.get('notUnlocked') + '</em></td>';
    s += '<td class="actionCheck"><img src="/image/action/unchecked.png" alt="[' + language.get('no') + ']" /></td>';
    s += '<td class="actionKarma">' + actions.next.karma + '</td>';
    s += '</tr>';

    s += '</table>';
    s += '</div>';

    elm.innerHTML = s;
}

App.prototype.pickAction = function(name) {
    misc.hideElm('actionDialog');
    this.performCall( 'SetVoteAction', 'app.doNothing', '&Action=' + encodeURIComponent(name) );
}

App.prototype.addComment = function() {
    misc.hideElm('addComment');
    var elmInput = document.getElementById('commentInput');
    elmInput.value = '';
    misc.showElm('comment');
    var elm = document.getElementById('commentInput');
    elm.focus();
}

App.prototype.saveComment = function() {
    var elm = document.getElementById('commentInput');
    var s = elm.value;
    this.performCall( 'SetVoteComment', 'app.doNothing', '&Comment=' + encodeURIComponent(s) );
    misc.hideElm('comment');
}

App.prototype.renameUsersNamed = function(blacklisted) {
    // todo... to prevent a user being named "you" in this.data
}

App.prototype.showReturned = function(data) {
    this.debug( misc.getFormattedJson(data) );
}

App.prototype.debug = function(message) {
    if (message != '') {
        if (this.doDebug) {
            // not misc.showElm to avoid infinite recursion
            var elm = document.getElementById('debug');
            elm.style.display = 'block';
        }
        misc.setHtml( 'debug', misc.toXml(message) );
    }
}

App.prototype.toggleDoDebug = function() {
    this.doDebug = !app.doDebug;
    if (this.doDebug) {
        misc.showElm('debug');
    }
    else {
        var elm = document.getElementById('debug');
        elm.style.display = 'none';
    }
}

App.prototype.showChangeAvatar = function() {
    var avatarNumber = this.getAvatarNumber();
    var page = Math.floor(avatarNumber / this.avatarsLimit) + 1;
    misc.hideElm('profile');
    this.showChangeAvatarPage(page);
}

App.prototype.showChangeAvatarPage = function(page) {
    this.avatarsStart = (page - 1) * this.avatarsLimit;
    this.performCall( 'GetAvatars', 'app.doShowChangeAvatarPage',
            '&Start=' + encodeURIComponent(this.avatarsStart) + '&Limit=' + encodeURIComponent(this.avatarsLimit) );
}

App.prototype.getAvatarNumber = function() {
    var avatarNumber = null;
    var player = this.getPlayerSelf();
    if (player && player.avatar_id) {
        avatarNumber = Math.floor(player.avatar_id);
    }
    return avatarNumber;
}

App.prototype.getPlayerSelf = function() {
    var player = null;
    for (var i = 1; i <= this.maxPlayers; i++) {
        if (i == this.playerPosition) {
            player = this.getPlayerByPosition(i);
        }
    }
    return player;
}


App.prototype.doShowChangeAvatarPage = function(data) {
    var s = '';
    var maxAvatars = 448;
    var maxPages = maxAvatars / this.avatarsLimit + 1;
    var thisPage = Math.floor(this.avatarsStart / this.avatarsLimit + 1);
    var selfNumber = this.getAvatarNumber();
    this.debug( misc.getFormattedJson(data) );

    s += this.getCloseButton('avatarSelection');
    s += '<p class="pickAvatarLabel">' + language.get('pickAvatar') + '</p>';
    for (var i = 0; i < this.avatarsLimit; i++) {
        var avatar = data.avatar[i];
        if (avatar) {
            var key = avatar.key;
            var isSelf = Math.floor(avatar.name) == selfNumber;
            var sClass = isSelf ? ' avatarLinkSelf' : '';
            var src = this.getRelativePath(avatar.src);
            s += '<a href="javascript:app.pickAvatar(' + "'" + misc.toAttribute(key) + "','" +
                    misc.toAttribute(src) + "'" + ')" class="avatarLink' + sClass + '">' +
                    '<img src="' + misc.toAttribute(src) + '" alt="" class="avatarImage" /></a> ';
        }
    }

    s += '<p class="pager"><strong>' + language.get('page') + '</strong>&nbsp; ';
    for (var page = 1; page <= maxPages; page++) {
        if (page > 1) { s += ' | '; }
        if (page == thisPage) {
            s += '<strong>&nbsp;' + page + '&nbsp;</strong>';
        }
        else {
            s += '<a href="javascript:app.showChangeAvatarPage(' + page + ')">&nbsp;' + page + '&nbsp;</a>';
        }
    }

    if (thisPage < maxPages - 1) {
        s += ' &nbsp; <strong><a href="javascript:app.showChangeAvatarPage(' + (thisPage + 1) + ')">&gt;&gt;</a></strong>';
    }
    else {
        s += ' &nbsp; <strong>&gt;&gt;</strong>';
    }

    s += '</p>';

    var elm = document.getElementById('avatarSelection');
    elm.innerHTML = s;
    elm.style.display = 'block';
}

App.prototype.pickAvatar = function(key, src) {
    misc.hideElm('avatarSelection');
    var elm = document.getElementById('avatarSourceTable' + this.playerPosition);
    if (elm) { elm.src = src; }
    this.performCall( 'SetAvatar', 'app.doAvatarSet', '&Avatar=' + encodeURIComponent(key) );
}

App.prototype.doAvatarSet = function(data) {
    if (data.avatar) {
        var player = this.getPlayerSelf();
        player.avatar = this.getRelativePath(data.avatar.src);
        player.avatar_id = data.avatar.id;
        document.getElementById('avatarSourceTable' + this.playerPosition).src = player.avatar;

        // set the variable in userarray
        for (var key in this.data.room.user)
            if (this.data.room.user[key].unique == player.unique) {
                this.data.room.user[key].avatar = player.avatar;
                this.data.room.user[key].avatar_id = player.avatar_id;
            }
    }
}

App.prototype.doNothing = function(data) {
    this.debug( misc.getFormattedJson(data) );
}

App.prototype.getPlayerPositionById = function(id) {
    var position = null;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var player = this.getPlayerByPosition(i);
        if (player) {
            if (player.unique == id) {
                position = i;
                break;
            }
        }
    }
    return position;
}

App.prototype.showTablePlayers = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        var isSelf = i == this.playerPosition;
        var player = this.getPlayerByPosition(i);
        var s = '';
        if (player) {
            var barWidth = player.personrank * 10;
            var tooltip = language.get('karma') + ' ' + misc.toAttribute(player.karma);
            barWidth = misc.forceMinMax(barWidth, 5, 100);
            var profileLink = "javascript:app.showProfile('" + player.unique + "')";

            s += '<a href="' + profileLink + '">' +
                    '<img src="' + misc.toAttribute( this.getRelativePath(player.avatar) ) + '" ' +
                    'alt="' + tooltip + '" title="' + tooltip + '" ' +
                    'class="avatarImage" id="avatarSourceTable' + i + '" />' +
                    '</a>';
            s += '<div class="avatarRank" title="' + tooltip + '">';
            if ( g_getBooleanProperty(player.is_robot) ) {
                s += '<img src="/image/kitt.gif" alt="" class="rankbar" style="width: 100%" />';
            }
            else {
                s += '<img src="/image/rankbar.png" alt="" class="rankbar" style="width: ' + barWidth + '%" />';
            }
            s += '</div>';
            s += '<div class="avatarName"><a href="' + profileLink + '">' +
                    misc.toXml(player.alias) + '</a></div>';
        }
        misc.setHtml('avatar' + i, s);
    }
}

App.prototype.showProfile = function(playerId) {
    this.performCall( 'GetProfileActive', 'app.handleShowProfileCallback', '&Unique=' + encodeURIComponent(playerId) );
}

App.prototype.handleShowProfileCallback = function(data) {
    this.debug( misc.getFormattedJson(data) );
    var user = data.user;
    if (user) {
        var playerSelf = this.getPlayerSelf();
        var isSelf = playerSelf.unique == user.unique;
        var elm = misc.getElementAndCreateIfNeeded('content', 'profile');
        var barWidth = user.personrank * 10;
        barWidth = misc.forceMinMax(barWidth, 5, 100);

        // below
        elm.style.display = 'block';
        var s = '';
    
        s += this.getCloseButton('profile');

        s += '<div class="avatarName"><strong>' + misc.toXml(user.alias) + '</strong>' ;
        if (isSelf) { s += ' <span class="avatarNameYou">(' + language.get('you') + ')</span>'; }
        s += '</div>';

        s += '<div class="profileAvatarWrapper">';
        s += '<div class="avatarImageWrapper">' +
                '<a href="javascript:app.showChangeAvatar()">' +
                '<img src="' + this.getRelativePath(user.avatar) + '" alt="" class="avatarImage" /></a></div>';
        s += '<div class="avatarRank">' +
                '<img src="/image/rankbar.png" alt="" class="rankbar" style="width: ' + barWidth + '%" /></div>';
        s += '</div>';

        if ( !( g_getBooleanProperty(user.is_robot) ) ) {
            s += '<div class="profileInfo"><strong>' + language.get('personRankColon') + '</strong> ' + user.personrank + '</div>';
            s += '<div class="profileInfo"><strong>' + language.get('karmaColon') + '</strong> ' + user.karma + '</div>';
        }

        if (isSelf) {
            s += '<div class="changeAvatar"><a href="javascript:app.showChangeAvatar()">&#187; ' +
                    language.get('changeAvatar') + '</a></div>';
            if (data.user.merged && data.user.merged == 'True' && data.network && data.network == 'facebook') {
                s += '<div class="mergeAccountsLink"><a href="/merge" target="_blank">&#187; ' +
                        language.get('mergeAccountsLink') + '</a></div>';
            }
        }

        s += '<div class="moreInfo">';
        if ( g_getBooleanProperty(user.is_robot) ) {
            s += language.get('botInfo');
        }
        else {
            s += language.get('thrownAt') + ' ' + misc.toXml(user.alias) + ':<br />';
    
            var actionCount = 0;
            var testIterations = 1;
            for (var n = 1; n <= testIterations; n++) {
                for (var action in user.actions) {
                    var count = user.actions[action];
                    for (var i = 1; i <= count; i++) {
                        s += '<img src="/image/action/' + action + '.png" alt="" />';
                        actionCount++;
                    }
                }
            }
            if (actionCount == 0) {
                s += '<em>nothing yet</em>';
            }
    
            s += this.getProfileCommentSection(data.profile_comments, user.unique, isSelf);
        }
        s += '</div>';

        elm.innerHTML = s;
    }
}

App.prototype.getProfileCommentSection = function(commentsWrapper, profileUserId, isSelf) {
    var s = '';

    s += '<div class="profileCommentArea">';

    if (commentsWrapper.entries.length >= 1) {
        var isAlternate = false;
        s += '<div class="profileCommentAreaHeader"><strong>' + language.get('commentsColon') + '</strong></div>';
        for (var i = 0; i < commentsWrapper.entries.length; i++) {
            var comment = commentsWrapper.entries[i];
            var sClass = isAlternate ? ' alternate' : '';
            s += '<div class="profileCommentWrapper' + sClass + '">';
            s += '<div class="profileComment">' + this.getProfileCommentConverted(comment.text) + '</div>';
            s += '<div class="profileCommentUser">' +
                    '<img src="' + this.getRelativePath(comment.user_from.avatar) + '" alt="" class="profileCommentAvatar" />&nbsp; ' +
                    '<strong>' + misc.toXml(comment.user_from.alias) + '</strong> ' +
                    '(' + language.get('karma').toLowerCase() + ' ' + misc.toXml(comment.user_from.karma) + ')</div>';
            // if (isSelf) {
            //    s += '<div class="profileCommentDelete">' +
            //           '[<a href="javascript:app.deleteProfileComment(' + "'" + comment.key + "'" + ')">' +
            //           language.get('deleteQuestion') + '</a>]</div>';
            //
            s += '</div>';
            isAlternate = !isAlternate;
        }
    }

    s += '<div id="profileAddCommentArea">';
    s += language.get('addComment');
    s += '<textarea name="profileComment" id="profileComment"></textarea><br />';
    s += '<input type="button" value="' + language.get('submit') + '" class="profileCommentSubmit" ' +
            'onclick="javascript:app.submitProfileComment(' + "'" + profileUserId + "'" + ')" />';
    s += '<br /><em id="profileCommentFeedback">&nbsp;</em></div>';

    s += '</div>';

    return s;
}

App.prototype.deleteProfileComment = function(key) {
}

App.prototype.submitProfileComment = function(userId) {
    var commentElm = document.getElementById('profileComment');
    var comment = commentElm.value;
    if (comment != '') {
        this.performCall( 'AddProfileComment', 'app.doNothing', '&Unique=' + encodeURIComponent(userId) +
                '&Text=' + encodeURIComponent(comment) );
        misc.setHtml( 'profileAddCommentArea', '<p>' + this.getProfileCommentConverted(comment) + '</p>' +
                '<p><em style="font-weight: bold">' + language.get('commentSubmitted') + '</em></p>' );
    }
    else {
        misc.setHtml( 'profileCommentFeedback', language.get('enterCommentWarning') );
    }
}

App.prototype.getProfileCommentConverted = function(s) {
    s = misc.toXml(s);
    return s;
}

App.prototype.getPlayerActivity = function() {
    var user = this.getSelfPlayer();
    return user.activity;
}

App.prototype.showUserInfo = function(showNewKarma) {
    var user = this.getSelfPlayer();
    var s = '';
    if (user) {
        var karmaToShow = null;
        if (showNewKarma) {
            karmaToShow = user.karma;
            this.oldKarma = user.karma;
        }
        else {
            if (this.oldKarma) {
                karmaToShow = this.oldKarma;
            }
            else {
                karmaToShow = user.karma;
                this.oldKarma = user.karma;
            }
        }

        var uploadUrl = this.useSandbox ? '/upload?sandbox=true' : '/upload';
        var dashboardUrl = this.useSandbox ? '/dashboard?sandbox=true' : '/dashboard';

        s += language.getReplace('hi', 'user', user.alias) + ' <span class="karma">(' + language.get('karma').toLowerCase() + ' ' + karmaToShow + ')</span>';
        s += ' | <a href="javascript:app.showChangeAvatar()">' + language.get('changeAvatar').toLowerCase() + '</a> | ' +
                '<a href="' + dashboardUrl + '" target="_blank">&#187; ' + language.get('dashboardTitle').toLowerCase() + '</a> | ';
        s += '<a href="' + uploadUrl + '" target="_blank"><img src="/image/upload.png" alt="" /> ' + language.get('uploadPics') + '</a> | ';
        if ( this.getNumberOfPlayersInRoom() > 1 ) {
            s += '<a href="javascript:app.showReportAbuse()" class="lessImportant">' + language.get('reportAbuse') + '</a> | ';
        }
        s += '<a href="javascript:app.signOut()" class="lessImportant">' + language.get('signOut') + '</a>';
    }
    else {
        s += '<a href="javascript:app.signIn()">' + language.get('signIn') + '</a>';
    }
    misc.setHtml('userInfo', s);
}

App.prototype.getRelativePath = function(url) {
    return url.replace(/http:\/\/captionx.com\//g, '');
}

App.prototype.getNumberOfPlayersInRoom = function() {
    var players = 0;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var player = this.getPlayerByPosition(i);
        if (player) { players++; }
    }
    return players;
}

App.prototype.showReportAbuse = function() {
    var s = '';
    s += '<p>' + language.get('abuseIntroduction') + '</p>';
    s += '<p>| ';
    for (var i = 1; i <= this.maxPlayers; i++) {
        var isSelf = i == this.playerPosition;
        if (!isSelf) {
            var player = this.getPlayerByPosition(i);
            if (player) {
                s += '<a href="javascript:app.doReportAbuse(' + "'" + player.unique + "'" + ')">' +
                        '<img src="' + misc.toAttribute( this.getRelativePath(player.avatar) ) + '" alt="" class="abuseAvatar" /> ' +
                        language.get('report') + ' ' + player.alias + '</a> | ';
            }
        }
    }
    s += '</p>';
    this.showQuickDialog(s);
}

App.prototype.showQuickDialog = function(messageHtml) {
    var elm = document.getElementById('quickDialog');
    elm.innerHTML = this.getCloseButton('quickDialog') +
            '<div id="quickDialogContent">' + messageHtml + '</div>';
    elm.style.display = 'block';
}

App.prototype.doReportAbuse = function(playerId) {
    this.performCall( 'SetAbuse', 'app.doNothing', '&User=' + encodeURIComponent(playerId) );
    misc.setHtml('abuseContent', '<p><em>' + language.get('reportConfirm') + '</em></p>');
    setTimeout( "misc.hideElm('quickDialog')", 3000 );
}

App.prototype.getSelfPlayer = function() {
    var selfPlayer = null;
    if (this.data) {
        var userId = this.data.room.ident;
        for (var i = 1; i <= this.maxPlayers; i++) {
            var thisUser = this.data.room.user[i - 1];
            if (thisUser) {
                var thisUserId = thisUser.unique;
                if (thisUserId == userId) {
                    selfPlayer = thisUser;
                    break;
                }
            }
        }
    }
    return selfPlayer;
}

App.prototype.hideAllVotes = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        if (i != this.playerPosition) {
            misc.hideElm('captionVote' + i);
        }
    }
}

App.prototype.signOut = function() {
    document.location.href = this.signOutUrl;
}

App.prototype.initModeText = function() {
    if (!this.sawTextMode) { setTimeout('g_handleWindowFocus()', 2 * 1000); }
    this.sawTextMode = true;
    this.closeEntertainmentAutomated();
    misc.hideElm('comment');
    this.showImage();
    this.clearUserCaption();
    misc.showElm('userCaption');
    this.unfadeImage(this.playerPosition);
    this.fadeOtherImages();
    this.showOthersThinking();
    if (pageTracker) { pageTracker._trackPageview('/analytics_api/caption_input_box/'); }
}

App.prototype.showOthersThinking = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        if (i != this.playerPosition) {
            var player = this.getPlayerByPosition(i);
            if (player) {
                var text = '';
                text += '<em class="lessImportant">';
                if ( g_getBooleanProperty(player.is_robot) ) {
                    text += '<img src="/image/cog.png" alt="" /> ';
                    text += language.getReplace( 'isComputing', 'user', misc.toXml(player.alias) )
                }
                else {
                    text += language.getReplace( 'isThinking', 'user', misc.toXml(player.alias) )
                }
                text += '</em>';
                this.showCaption('caption' + i, text);
            }
            else {
                this.hideCaption('caption' + i);
            }
        }
    }
}

App.prototype.getPlayerById = function(id) {
    var player = null;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var thisPlayer = this.data.room.user[i - 1];
        if (thisPlayer && thisPlayer.unique == id) {
            player = thisPlayer;
            break;
        }
    }
    return player;
}

App.prototype.getPositionById = function(id) {
    var position = null;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var player = this.getPlayerByPosition(i);
        if (player && player.unique == id) {
            position = i;
            break;
        }
    }
    return position;
}

App.prototype.getPlayerByPosition = function(targetPosition) {
    var player = null;
    if (this.data.room) {
        var userId = this.data.room.ident;
        var chairs = Array();
        var position = 0;
        for (var i = 1; i <= this.maxPlayers; i++) {
            var thisUser = this.data.room.user[i - 1];
            if (thisUser) {
                var thisUserId = thisUser.unique;
                if (thisUserId == userId) {
                    chairs[app.playerPosition] = thisUser;
                }
                else {
                    position++;
                    if (position == this.playerPosition) { position++; }
                    chairs[position] = thisUser;
                }
            }
        }
        player = chairs[targetPosition];
    }
    return player;
}

App.prototype.initModeVote = function() {
    this.didVote = false;
    this.closeEntertainmentAutomated();
    this.showImage();
    misc.hideElm('userCaption');
    this.fadeImage(this.playerPosition);
    this.unfadeOtherImages();
    this.showCaptions(true);
}

App.prototype.initModeWinner = function(startValue) {
    misc.hideElm('actionDialog');
    this.closeEntertainmentAutomated();
    this.showCaptions(false);

    if (this.data.room.winnermode == 'failure') {
        this.setHtmlShadowed('countdown', language.get('noOneWins'));
        setTimeout( 'g_getMode()', (startValue + 1) * 1000 );
    }
    else {
        if (!this.justShownWinner) {
            var winnerId = this.data.room.winner;
            if (winnerId) {
                misc.hideElm('comment');
                this.showImage();
                var playerCount = 0;
                for (var i = 1; i <= this.maxPlayers; i++) {
                    var player = this.getPlayerByPosition(i);
                    if (player) {
                        setTimeout('g_showVote(' + i + ')', i * 3000);
                        this.unfadeImage(i);
                        playerCount++;
                    }
                }
                var delayBeforeAnnouncement = 1.5 * 1000;
                setTimeout( 'g_showWinner()', (playerCount + 1) * 3000 + delayBeforeAnnouncement );
            }
            setTimeout( 'g_getMode()', (startValue + 1) * 1000 );
            this.justShownWinner = true;
        }
        else {
            setTimeout( 'g_getMode()', 1500 );
        }
    }
}

App.prototype.showWinner = function() {
    if (this.data && this.data.room && this.data.room.mode == 'WINNER') {
        var winnerId = this.data.room.winner;
        if (winnerId && winnerId != '') {
            var winner = this.getPlayerById(winnerId);
            if (winner) {
                var address = ( this.getIsPlayer(winnerId) ) ?
                        language.get('youWin') : language.getReplace('someoneWins', 'user', winner.alias);
        
                if (this.data.room.winnermode == 'random') {
                    var message = language.get('itsADraw') + ' ' + address + ' ' + this.getDrawReason() + '!';
                    message = this.adjustMessageIfKarmaFreeRound(message);
                    this.setHtmlShadowed('countdown', message);
                }
                else {
                    var message = address + ' ' + language.get('theRound');
                    message = this.adjustMessageIfKarmaFreeRound(message);
                    if ( this.getIsPlayer(winnerId) ) { message += ' ' + language.get('congrats'); }
                    this.setHtmlShadowed('countdown', message);
                }
        
                this.showPlayerGlow( this.getPlayerPositionById(winnerId) );
            }
        }
        else {
            // unused?!
            this.setHtmlShadowed( 'countdown', language.get('nobodyWins') );
        }
        this.showUserInfo(true);
    }
}

App.prototype.adjustMessageIfKarmaFreeRound = function(s) {
    if ( this.isKarmaFreeRound() ) {
        var text = language.getReplace('karmaFreeInfo', 'n', this.tooLittlePlayers);
        s += ' ' + text;
    }
    return s;
}

App.prototype.isKarmaFreeRound = function() {
    return this.getPlayerCount() <= this.tooLittlePlayers;
}

App.prototype.getPlayerCount = function() {
    var playerCount = 0;
    if (this.data.room && this.data.room.user) {
        playerCount = this.data.room.user.length;
    }
    return playerCount;
}

App.prototype.getDrawReason = function() {
    var reasons = new Array();
    for (var i = 1; i <= 10; i++) {
        reasons[reasons.length] = language.get('drawReason' + i);
    }
    var randomI = misc.getRandomInt(0, reasons.length - 1);
    return reasons[randomI];
}

App.prototype.showPlayerGlow = function(position) {
    var playerPoint = this.getPointOfPlayer(position);
    playerPoint.x -= 44;
    playerPoint.y -= 49;
    var elm = document.getElementById('glow');
    playerPoint.assignToElement(elm);

    // workaround, as it was already CSS-assigned:
    elm.style.filter = 'alpha(opacity=75)';

    this.glowCount = 15;
    this.blinkGlow();
}

App.prototype.blinkGlow = function() {
    if (--this.glowCount % 2 == 0) {
        misc.showElm('glow');
    }
    else {
        misc.hideElm('glow');
    }

    if (this.glowCount > 0) {
        setTimeout('g_blinkGlow()', 300);
    }
    else {
        misc.hideElm('glow');
    }
}

App.prototype.getPointOfPlayer = function(position) {
    var points = new Array();
    points[1] = new Point(395, 232);
    points[2] = new Point(516, 232);
    points[3] = new Point(425, 345);
    points[4] = new Point(482, 345);
    points[5] = new Point(374, 296);
    points[6] = new Point(536, 296);
    return points[position];
}

App.prototype.getIsPlayer = function(id) {
    return this.data.room.ident == id;
}

App.prototype.showVote = function(i) {
    if ( this.data && this.data.room && this.data.room.mode == 'WINNER' && this.getPlayerCount() > 1 ) {
        var player = this.getPlayerByPosition(i);
        if (player) {
            var message = '';
            if (player.vote) {
                otherPlayer = this.getPlayerById(player.vote);
                if (otherPlayer) {
                    var pointStart = this.getPointOfPlayer(i);

                    var isPlayer = this.getIsPlayer(player.unique);
                    var address = (isPlayer) ? 'You' : player.alias;
                    var address1 = (isPlayer) ? 'you' : player.alias;
                    var address2 = ( this.getIsPlayer(otherPlayer.unique) ) ? language.get('you') : otherPlayer.alias;
                    var comment = player.comment ? player.comment : '';
                    var action = player.action ? player.action : '';

                    message = language.get('votedFor');
                    message = message.replace(/\[name1\]/, address);
                    message = message.replace(/\[name2\]/, address2);
                    if ( !this.isKarmaFreeRound() ) {
                        message += ' (' + language.getReplace('activityPoints', 'user', address1) + ')';
                    }

                    this.highlightPlayer(i);
                    this.showVoteAnimation( this.getPositionById(otherPlayer.unique), pointStart, comment, true, action );
                    this.justShownWinner = true;

                    if ( this.getIsPlayer(otherPlayer.unique) ) {
                        message += '!';
                    }
                }
            }
            else {
                var address = ( this.getIsPlayer(player.unique) ) ? language.get('you').ucFirst() : player.alias;
                if ( g_getBooleanProperty(player.is_robot) ) {
                    message = language.getReplace('someoneDidntVoteBot', 'user', address);
                }
                else {
                    message = language.getReplace('someoneDidntVote', 'user', address);
                }
            }
            this.setHtmlShadowed('countdown', message);
        }
    }
}

App.prototype.highlightPlayer = function(i) {
    var elm = document.getElementById('avatarSourceTable' + i);
    elm.style.borderColor = 'rgb(255,255,0)';
}

App.prototype.showVoteAnimation = function(targetPosition, pointStart, text, isHumanVote, action) {
    var points = new Array();
    var pointTarget = new Point();

    points[1] = new Point(220, 80);
    points[2] = new Point(630, 80);
    points[3] = new Point(220, 470);
    points[4] = new Point(630, 470);
    points[5] = new Point(160, 300);
    points[6] = new Point(760, 300);

    pointTarget.x = points[targetPosition].x + misc.getRandomInt(-30, 30) * 1;
    pointTarget.y = points[targetPosition].y + misc.getRandomInt(-30, 30) * 1;

    animation.startVoteSprite(pointStart.x, pointStart.y, pointTarget.x, pointTarget.y, text, isHumanVote, action);
}

App.prototype.clearCaptions = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        this.hideCaption('caption' + i);
        misc.hideElm('image' + i);
    }
}

App.prototype.showCaptions = function(showVoteLinks) {
    var somethingVotable = false;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var player = this.getPlayerByPosition(i);
        if (player) {
            var s = '';

            if (player.caption) {
                s += this.getConvertedCaption(player.caption);

                if (showVoteLinks && i != this.playerPosition) {
                    s += ' &nbsp; <span id="captionVote' + i + '" class="captionVote">' +
                            '(<a href="javascript:app.setVote(' + "'" + misc.toAttribute(player.unique) + "'" + ',' + i + ')">' +
                            '<img src="image/star-small.png" alt="" />&nbsp;' +
                            language.get('voteForIt').replace(' ', '&nbsp;') + '</a>)</span>';
                    somethingVotable = true;
                }
            }
            else {
                if (i != this.playerPosition) {
                    s += '<em class="lessImportant">' +
                            language.getReplace( 'didntEnterAnything', 'user', misc.toXml(player.alias) ) + '</em>';
                }
                else {
                    s += '<em class="lessImportant">' + language.get('youDidntEnterAnything') + '</em>';
                }
            }

            this.showCaption('caption' + i, s);
        }
        else {
            this.hideCaption('caption' + i);
        }
    }
    return somethingVotable;
}

App.prototype.showCaption = function(id, s) {
    misc.setHtml(id, s);
    misc.showElm(id);
}

App.prototype.hideCaption = function(id) {
    misc.hideElm(id);
}

App.prototype.getConvertedCaption = function(s) {
    s = misc.toXml(s);
    s = s.replaceAsteriskWithItalics();
    return s;
}

App.prototype.getIsVotable = function() {
    var isIt = false;
    for (var i = 1; i <= this.maxPlayers; i++) {
        var player = this.getPlayerByPosition(i);
        if (player && player.caption && i != this.playerPosition) {
            isIt = true;
            break;
        }
    }
    return isIt;
}

App.prototype.fadeOtherImages = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        if (i != this.playerPosition) {
            this.fadeImage(i);
        }
    }
}

App.prototype.unfadeOtherImages = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        if (i != this.playerPosition) {
            this.unfadeImage(i);
        }
    }
}

App.prototype.fadeImage = function(i) {
    var elm = document.getElementById('image' + i);
    elm.style.opacity = .3;
    elm.style.filter = 'alpha(opacity=30)';
}

App.prototype.unfadeImage = function(i) {
    var elm = document.getElementById('image' + i);
    elm.style.opacity = 1;
    elm.style.filter = 'alpha(opacity=100)';
}

App.prototype.showImage = function() {
    if (this.data.room.picture.src) {
        var imageUrl = this.getRelativePath(this.data.room.picture.src);

        for (var i = 1; i <= this.maxPlayers; i++) {
            var elm = document.getElementById('image' + i);
            elm.style.display = 'inline';
    
            if ( !( elm.src.indexOf(imageUrl) >= 1 ) ) {
                elm.src = 'image/blank.png';
                misc.showElm('progress' + i);
                setTimeout("misc.hideElm('progress" + i + "')", 1500);
            }
        }

        for (var i = 1; i <= this.maxPlayers; i++) {
            var elm = document.getElementById('image' + i);
            elm.style.display = 'inline';
            if ( !( elm.src.indexOf(imageUrl) >= 1 ) ) {
                elm.src = imageUrl;
            }
        }

        this.showLicense();
    }
    else {
        setTimeout( 'g_getMode()', 1000 * 2 );
    }
}

App.prototype.hideImages = function() {
    for (var i = 1; i <= this.maxPlayers; i++) {
        var elm = document.getElementById('image' + i);
        elm.style.display = 'none';
    }
}

App.prototype.showLicense = function() {
    if (this.data.room && this.data.room.picture && this.data.room.picture.origin && this.data.room.picture.license) {
        var html = '';
        var origin = this.data.room.picture.origin;
        var license = this.data.room.picture.license;
        if (license && origin) {
            var name = misc.toXml( this.data.room.picture.creator.ucWords() );
            if (name == '') { name = 'Unnamed'; }
            html = '<a href="' + misc.toAttribute(origin) + '" target="_blank">' +
                    language.getReplace('photoBy', 'name', name) + '</a> (' +
                    '<a href="' + misc.toAttribute(license) + '" target="_blank" rel="license">' + language.get('license') + '</a>)';
        }
        else if (origin) {
            html = '<a href="' + misc.toAttribute(origin) + '" target="_blank">' + language.get('photoSource') + '</a>';
        }
        misc.setHtml('credits', html);
    }
}

App.prototype.startCountdown = function(seconds) {
    if (this.intervalId == 0) {
        var microSeconds = 1000;
        this.countdownSeconds = seconds;
        this.intervalId = setInterval(g_continueCountdown, microSeconds);
    }
}

App.prototype.continueCountdown = function() {
    if (--this.countdownSeconds <= 0) {
        clearInterval(this.intervalId);
        this.intervalId = 0;

        switch (this.data.room.mode) {
            case 'PENDING':
                this.getRoom();
                break;
            case 'TEXT':
                var caption = this.getUserCaption();
                if (!app.captionEntered && caption != '') {
                    caption += ' *[' + language.get('timeRanOut') + ']*';
                    var elmCaption = document.getElementById('caption');
                    elmCaption.value = caption;
                }
                this.saveCaption();
                this.showCountdown();
                setTimeout(g_getMode, 3000);
                break;
            case 'VOTE':
                this.showCountdown();
                setTimeout(g_getMode, 3000);
                break;
            default:
                this.showCountdown();
                this.getMode();
        }
    }
    else {
        if (this.data.room.mode == 'PENDING') {
            this.showPending();
        }
        else {
            if (this.countdownSeconds == 1 && this.data.room.mode == 'TEXT') {
                this.closeEntertainmentAutomated();
            }
            this.showCountdown();
        }
    }
}

App.prototype.getUserCaption = function() {
    var elm = document.getElementById('caption');
    var s = elm.value;
    s = s.replace(/\r/g, '');
    s = s.replace(/\n/g, '');
    s = s.replace(/\r\n/g, '');
    if (s == this.defaultCaption) {
        s = '';
    }
    return s;
}

App.prototype.clearUserCaption = function() {
    var elm = document.getElementById('caption');
    elm.value = this.defaultCaption;
    setTimeout('g_selectCaption()', 100);
    this.captionEntered = false;
    this.hideCaption('caption' + this.playerPosition);
}

App.prototype.selectCaption = function() {
    var elm = document.getElementById('caption');
    elm.select();
    elm.focus();
}

App.prototype.showPending = function() {
    var numberOfDots = 6 - this.countdownSeconds;
    if (numberOfDots <= 2) { numberOfDots = 2; }

    var message = language.get('lookingForPlayers');
    var messageImages = '';

    if (this.pendingCounter == 3) {
        message = language.get('mayTakeSomeSeconds');
    }
    else if (this.pendingCounter == 4) {
        message = language.get('sorryForDelay');
    }
    message += misc.getChars('.', numberOfDots);

    if (this.data.rooms) {
        var otherRoomsCount = this.data.rooms.length;
        if (otherRoomsCount >= 1) {
            message += '<div class="currentlyPlayingLabel">' + language.get('currentlyPlaying') + '</div>';
            for (var roomCounter = 0; roomCounter < otherRoomsCount; roomCounter++) {
                var room = this.data.rooms[roomCounter];
                for (var playerCounter = 0; playerCounter < room.user.length; playerCounter++) {
                    var player = room.user[playerCounter];
                    messageImages += '<img src="' + player.avatar + '" alt="" class="avatarOtherRoom" /> ';
                }
            }
        }
    }

    if (messageImages != '') {
        messageImages = '<div class="currentlyPlayingImages">' + messageImages + '</div>';
    }
    misc.setHtml('countdown', message + messageImages)
    misc.setHtml('countdownShadow', message)
    misc.setHtml('countdownShadow2', message)

    this.clearDisplay();
}

App.prototype.showCountdown = function() {
    var message = '';
    switch (this.data.room.mode) {
        case 'TEXT':
            if (this.captionEntered) {
                message = language.get('pleaseWait');
            }
            else {
                message = language.get('enterCaption');
            }
            break;
        case 'VOTE':
            if ( this.getIsVotable() ) {
                if (this.didVote) {
                    message = language.get('pleaseWait');
                }
                else {
                    message = language.get('voteBest');
                }
            }
            else {
                message = language.get('nothingToVote');
            }
            break;
        case 'WINNER':
            message = ' winsXXXX'; // how is this used?!
            break;
    }
    message += ' (' + this.countdownSeconds + ')';
    this.setHtmlShadowed('countdown', message);
}

App.prototype.setHtmlShadowed = function(id, html) {
    misc.setHtml(id, html);
    misc.setHtml(id + 'Shadow', html)
    misc.setHtml(id + 'Shadow2', html)
}

App.prototype.signIn = function(siteName) {
    var url = '';
    switch (siteName) {
        case 'facebook':
            url = this.signInUrlFacebook;
            break;
        default:
            url = this.signInUrl;
    }
    if (url != '') {
        // alert(url);
        document.location.href = url;
    }
}

App.prototype.performCall = function(mode, callbackFunction, parameter) {
    if (callbackFunction == '') { callbackFunction = 'app.showReturned'; }

    var containerId = 'scriptContainer' + misc.toName(mode);
    if ( document.getElementById(containerId) ) {
        document.body.removeChild( document.getElementById(containerId) );
    }
    var script = document.createElement('script');
    script.id = containerId;
    script.type = 'text/javascript';
    script.src = this.baseUrl + misc.toXml( '?Operation=' + mode + '&Output=json&Callback=' + callbackFunction + parameter +
                 '&r=' + misc.getRandomString() );
    /// this.debug( script.src.replace(/&amp;/g, '&') );
    document.body.appendChild(script);
}

App.prototype.showInfo = function() {
    alert('Version = ' + this.version);
}

function App() {
    this.baseUrl = 'http://captionxservice.appspot.com/api';
    this.returnUrl = 'http://' + document.domain + '/';
    this.signInUrl = '';
    this.signInUrlFacebook = '';
    this.signOutUrl = '';
    this.countdownSeconds = 0;
    this.intervalId = 0;
    this.data = '';
    this.pendingCounter = 0;
    this.maxPlayers = 6;
    this.playerPosition = 1;
    this.defaultCaption = '';
    this.captionEntered = false;
    this.didVote = false;
    this.avatarsStart = 0;
    this.avatarsLimit = 50;
    this.keycodeReturn = 13;
    this.glowCount = 0;
    this.doDebug = false;
    this.oldKarma = null;
    this.version = null;
    this.secondsNeededForEntertainment = 20;
    this.entertainmentStartY = -400;
    this.entertainmentEndY = 310;
    this.entertainmentY = this.entertainmentStartY;
    this.videoWidth = 285;
    this.videoHeight = 230;
    this.doAutoPlayVideo = false;
    this.closedEntertainmentInARow = 0;
    this.inRoomPendingCount = 0;
    this.sawTextMode = false;
    this.hasFocus = true;
    this.triggeredPlayerSearchEntertainment = false;
    this.status = '';
    this.useSandbox = false;
    this.latestProfileCommentKey = '';
    this.tooLittlePlayers = 2;
    this.justShownWinner = false;
}
