MetaGame = Class.create({
    initialize: function(technoId, technology) {
        this.technoId = technoId;
        this.technology = technology;
        this.update();
    },
    update: function() {
        
        var technoId = this.technoId;
        var technology = this.technology;
        
        log.debug('GetGameInfoAllTechno call. Techno id: ' + technoId + ' Technology: ' + technology);
        this.gameInfo = GetGameInfoAllTechno(technoId, technology);
        this.priority = parseInt(this.gameInfo.strDownloadPriority);
        for(i in this.gameInfo) {
            log.debug('->' + i + '=' + this.gameInfo[i]);
        }
        this.title = this.gameInfo.strProductName;
        this.titleWoSpace = this.title.replace(/\s+/gi, '-');
        this.download = {
            downloadedKBytes: 0,
            totalKBytesToPlay: 0,
            totalKBytes: 0,
            timeToPlay: 0,
            timeToFull: 0,
            speedKBSec: 0
        };
        this.setDownloadProgressInKBytes(
            this.gameInfo.strDownloadedKB,
            this.gameInfo.strInitialDownloadSizeKB,
            this.gameInfo.strFullDownloadSizeKB,
            this.gameInfo.strInitialDownloadTimeLeftSec,
            this.gameInfo.strFullDownloadTimeLeftSec
            );
        this.progress = {
            startSize: 0,
            startTime: 0,
            clearTime: 60 * 1000
        }
    },

    gametapUpdate: function() {
        var progress = getProgressInfoGame(this.technoId);
        var speed = parseInt(progress.SpeedKBSec);
        log.debug('gametap progress. DownloadedBytesStr: ' + progress.DownloadedBytesStr + ' TotalBytesToPlayStr: ' + progress.TotalBytesToPlayStr +
            ' TotalBytesStr: ' + progress.TotalBytesStr + ' EstTimeRemainingToPlaySec:' + progress.EstTimeRemainingToPlaySec +
            ' EstTimeRemainingFullDLSec: ' + progress.EstTimeRemainingFullDLSec + ' speed: ' + speed);
        speed = (speed < 0) ? 0 : speed;
        this.setDownloadProgressInBytes(
            progress.DownloadedBytesStr,
            progress.TotalBytesToPlayStr,
            progress.TotalBytesStr,
            progress.EstTimeRemainingToPlaySec,
            progress.EstTimeRemainingFullDLSec,
            speed
            );
    },
    isFullyCached: function() {
        return parseInt(this.gameInfo.strFullyCached);
    },
    isActive: function() {
        return parseInt(this.gameInfo.strActive);
    },
    isReady: function() {
        return parseInt(this.gameInfo.strReadyToUse);
    },
    isRunning: function() {
        return parseInt(this.gameInfo.strGameRunning);
    },
    isDownloadNow: function() {
        return (this.isActive() && !this.isRunning());
    },
    getStatus: function() {
        if (this.isFullyCached()) {
            return i18n('addGameInfo1');
        } else if (this.isReady()) {
            return i18n('addGameInfo2');
        } else if (this.isDownloadNow()) {
            return i18n('addGameInfo3');
        }
        return i18n('addGameInfo4');
    },
    downloadedPercent: function() {
        return percentAvancement(this.download.downloadedKBytes, this.download.totalKBytes);
    },
    getFullSize: function() {
        return this.getDynamicSize(this.download.totalKBytes);
    },    
    getDownloadedSize: function() {
        return this.getDynamicSize(this.download.downloadedKBytes);
    }, 
    minDownloadedPercent: function() {
        return percentAvancement(this.download.totalKBytesToPlay, this.download.totalKBytes);
    },
    setDownloadProgressInKBytes: function(downloadedKBytes, totalKBytesToPlay, totalKBytes, timeToPlay, timeToFull, speedKBSec) {
        downloadedKBytes = parseInt(downloadedKBytes);
        totalKBytesToPlay = parseInt(totalKBytesToPlay);
        totalKBytes = parseInt(totalKBytes);
        timeToPlay = parseInt(timeToPlay);
        timeToFull = parseInt(timeToFull);
        speedKBSec = parseFloat(speedKBSec);
        if (!isNaN(downloadedKBytes))  	this.download.downloadedKBytes = downloadedKBytes;
        if (!isNaN(totalKBytesToPlay))  this.download.totalKBytesToPlay = totalKBytesToPlay;
        if (!isNaN(totalKBytes)) this.download.totalKBytes = totalKBytes;
        if (!isNaN(timeToPlay))  this.download.timeToPlay = timeToPlay;
        if (!isNaN(timeToFull))  this.download.timeToFull = timeToFull;
        if (!isNaN(speedKBSec))  this.download.speedKBSec = speedKBSec;
    },
    setDownloadProgressInBytes: function(downloadedBytes, totalBytesToPlay, totalBytes, timeToPlay, timeToFull, speedKBSec) {
        downloadedKBytes = parseInt(downloadedBytes) / 1024;
        totalKBytesToPlay = parseInt(totalBytesToPlay) / 1024;
        totalKBytes = parseInt(totalBytes) / 1024;
        this.setDownloadProgressInKBytes(downloadedKBytes, totalKBytesToPlay, totalKBytes, timeToPlay, timeToFull, speedKBSec);
    },
    setBandwidthExent: function() {
        if (this.progress.startSize == 0 || (new Date() - this.progress.startTime) > this.clearTime) {
            this.progress.startSize = this.download.downloadedKBytes;
            this.progress.startTime = new Date();
        }
        var progressBandwidth = Math.round(
            (this.download.downloadedKBytes - this.progress.startSize) / (new Date() - this.progress.startTime) * 1000
            );
        //        progressBandwidth = parseFloat(progressBandwidth);
        if (isNaN(progressBandwidth)) progressBandwidth = 0;
        this.download.speedKBSec = (progressBandwidth < 0) ? 0 : progressBandwidth;
    },
    getBandwidth: function() {
        if (this.technology == enumGameTechno.EXENT_TECHNO) this.setBandwidthExent();
        return this.download.speedKBSec + '&nbsp;' + i18n('downloadSpeedLabel'); 
    },
    getProcessTime: function() {
        var seconds = parseInt(
            this.download.downloadedKBytes > this.download.totalKBytesToPlay ?
            this.download.timeToFull : this.download.timeToPlay);
        var minutes = Math.floor(seconds / 60);
        var hours   = Math.floor(seconds / 3600);
        if (isNaN(seconds) || isNaN(minutes) || isNaN(hours)) {
            return false;
        }
        if (seconds < 60) {
            return '00:00:' + formatNumber(seconds);
        } 
        if (minutes < 60) {
            return '00:' + formatNumber(minutes) + ':' + formatNumber(seconds - minutes * 60);
        }
        minutes = minutes - (hours * 60);
        seconds = seconds - minutes * 60 - hours * 3600;
        return formatNumber(hours) + ':' + formatNumber(minutes) + ':' + formatNumber(seconds);
    },
    getProcessTimeleft: function() {
        var result = this.getProcessTime();
        if (!result) {
            return i18n('ElapsedTime');
        }
        return result + '&nbsp;' + i18n('ElapsedTime_result');
    },
    getDynamicSize: function(sizeKb) {
        if (sizeKb > 1048576) {
            return (Math.round(sizeKb/104857))/10 + ' ' + i18n('sizeGbLabel');
        }
        if (sizeKb > 1024) {
            return (Math.round(sizeKb/102))/10 + ' ' + i18n('sizeMbLabel');
        }
        return Math.round(sizeKb) + ' ' + i18n('sizeKbLabel');
    }
});

function sortByTitle(a, b) {
    return (a.title > b.title);
}

function sortByPriority(a, b) {
    return (a.priority - b.priority);
}

MyGames = Class.create({
    initialize: function() {
        this.downloaded = new Hash();
        this.inDownload = new Hash();
        this.notInDownload = new Hash();
        this.hashCookie = new Array();

        this.constant = {
            langPrefix: getLocale().path,
            userGames: 'usergames',
            inProgress: 'gameInProgress',
            readyBrowserGames: 'fullDownloadBrowserGamesList'
        };
		
        this.myEffects = {
            move: 1,
            moveFast: 0.3,
            moveSlow: 1,
            create: 0.2,
            remove: 0.6,
            noPlayer: 0.8
        };

        this.exentUpdater = null;
        this.gameInProcessTechnoId = null;
        if (isOk) {
            if (DEFINE.get('TYPE') == 'META') {
                if (isTheGoodVersionInstalledMultiTechno(DEFINE.get('PLAYER_EXENT_VERSION'), DEFINE.get('PLAYER_YUMMY_VERSION'))) {
                    this.playerAvailable();
                }
                else {
                    this.playerUpdate();
                }
            } else {
                this.playerAvailable();
            }
        } else {
            this.playerNotAvailable();
        }
    },
    playerNotAvailable: function() {
        var url = new UrlConstructor('profile/download_player');
        url.addVar('isIE', (Prototype.Browser.IE) ? 1 : 0);
        new Ajax.Request(url.construct(), {
            onSuccess: function(transport) {
                var uGames = $(this.constant.userGames);
                uGames.setStyle({
                    display: 'none'
                });
                uGames.update(transport.responseText);
                new Effect.BlindDown(uGames, {
                    duration: this.myEffects.noPlayer
                    });
            }.bind(this)
        });
    },
    playerUpdate: function() {
        var url = new UrlConstructor('profile/update_player');
        new Ajax.Request(url.construct(), {
            onSuccess: function(transport) {
                var uGames = $(this.constant.userGames);
                uGames.setStyle({
                    display: 'none'
                });
                uGames.update(transport.responseText);
                new Effect.BlindDown(uGames, {
                    duration: this.myEffects.noPlayer
                    });
            }.bind(this)
        });
    },
    getGameList: function(xml) {
        var list = new Hash();
        var xmlDoc = getXmlDoc(xml);
        result = xmlDoc.getElementsByTagName('ContentDescriptor');
        for (var i = 0 ; i < result.length ; i++) {
            el = result.item(i);
            list.set(el.getAttribute('Id'), el.getAttribute('codeTechno'));
        }
        return list;
    },
    getAllGames: function() {
        try {
           if (typeof(writeFullyDownloadedListGamesEmulatorAllTechno) != 'undefined') {
                log.debug('Browser games: ' + writeFullyDownloadedListGamesEmulatorAllTechno());
                this.browser = new Hash();
                this.getGameList(writeFullyDownloadedListGamesEmulatorAllTechno()).each(function(g) {
                    this.browser.set(g.key, new MetaGame(g.key, g.value));
                }.bind(this));
            }
        } catch(e) {
            log.err(e);
        }
    },
    playerAvailable : function() {
        ww.show();
        this.getAllGames();
        var url = new UrlConstructor('profile/get_games_info');
        var merged = new Hash();
        merged = this.downloaded.merge(this.inDownload).merge(this.notInDownload);
        if (this.browser) merged = merged.merge(this.browser);
        new Ajax.Request(url.construct(), {
            method: 'post',
            parameters: 'games=' + merged.keys().toJSON(),
            onSuccess: function(transport) {
                var obj = transport.responseText.evalJSON();
                $(this.constant.userGames).update(obj.content);
                if (typeof(obj.games) != 'undefined') this.extendMetaGame(obj.games);
                ww.hide();
                this.render();
            }.bind(this)
        });
    },
    extendMetaGame: function(games) {
        var queueSort = new Array();
        this.downloaded.keys().each(function(technoId) {
            if (typeof(games[technoId]) == 'object')
                Object.extend(this.downloaded.get(technoId), games[technoId]);
            else
                this.downloaded.unset(technoId);
        }.bind(this));
        this.inDownload.keys().each(function(technoId) {
            if (typeof(games[technoId]) == 'object') {
                var metaGame = this.inDownload.get(technoId);
                Object.extend(this.inDownload.get(technoId), games[technoId]);
                log.debug('meta game indownload. techno id: ' + metaGame.technoId + ' technology: ' + metaGame.technology + ' priority: ' + metaGame.priority);
                queueSort.push(metaGame);

            } else {
                this.inDownload.unset(technoId);
            }
        }.bind(this));
        this.notInDownload.keys().each(function(technoId) {
            if (typeof(games[technoId]) == 'object')
                Object.extend(this.notInDownload.get(technoId), games[technoId]);
            else
                this.notInDownload.unset(technoId);
        }.bind(this));
        if (this.browser) {
            this.browser.keys().each(function(technoId) {
                if (typeof(games[technoId]) == 'object')
                    Object.extend(this.browser.get(technoId), games[technoId]);
                else
                    this.browser.unset(technoId);
            }.bind(this));
        }
        
        if (__meta) {
            try {
                var tmp = new Array();
                queueSort.sort(sortByPriority);
                queueSort.each(function(item){
                    tmp.push(item.technoId + '/' + item.technology);
                });
                var queueCookie = tmp.join(',');
                log.debug('set queue cookie. value: ' + queueCookie);
                set_cookie(queueCookie);                
                var queueCookie = get_cookie();
                log.debug('get queue cookie. value: ' + queueCookie);
                var matchCookie = queueCookie.match(/(\d+\/\w+)/gi);
                if (matchCookie && matchCookie.size()) {
                    var inDownload = this.inDownload.clone();
                    this.inDownload = new Hash();
                    matchCookie.each(function(item){
                        log.debug('cookie queue item. item: ' + item);
                        var res = item.split('/');
                        var technoId = res[0];
                        var technology = res[1];
                        var cloneGame = inDownload.get(technoId);
                        if (cloneGame) {
                            this.inDownload.set(technoId, cloneGame);
                            log.debug('set indownload game. technoId: ' + technoId + ' technology: ' + technology);    
                        } else {
                            log.debug('can\'t find indownload game presented in cookie. technoId: ' + technoId + ' technology: ' + technology);
                        }
                    }.bind(this));
                }
            } catch(e) {
                log.err(e);
            }
        } 
    },
    showInProgress: function() {
        if (this.inDownload.size() || this.notInDownload.size()) {
            $(this.constant.inProgress).removeClassName('displayNone');
        }
    },
    addGradient: function(technoId, metaGame) {
        return new Element('img', {
            id: 'bg-' + technoId,
            'class': 'gradientBG gradientGame',
            'src': DEFINE.get('MY_GAMES_GRADIENT')
        });
    },
    addFavorite: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'favourite' + (metaGame.favorite ? '' : ' favourite_inactive')
        }).insert(
            new Element('a', {
                'class': 'tooltip righttip',
                'title': i18n('addFavorite1'),
                'href': '#add_to_favorites'
            }).insert( new Element('span').insert(i18n('addFavorite1')) ).observe('click', this.toggleFavorite.bind(this))
            );
    },
    addGameInfo: function(technoId, metaGame, options) {
        var gameInfo = new Element('div', {
            'class': 'gameInfo'
        });
        gameInfo.insert(new Element('a', {
            href: metaGame.gameUrl
            }).insert(
            new Element('img', {
                'class': 'tooltip tipright gameImage',
                src: metaGame.boxshotUrl,
                title: metaGame.getStatus(),
                alt: metaGame.getStatus()
            })
            ));
        gameInfo.insert(
            new Element('a', {
                'class': 'manual',
                href: 'javascript:showManual(' + metaGame.gameId + ');'
                }).update(i18n('addGameInfo6'))
            );
        gameInfo.insert(new Element('p', {
            'class': 'gameTitle'
        }).insert(
            new Element('a', {
                href: metaGame.gameUrl
                }).update(metaGame.title)
            ));
        if (options && options.showProgressBar) {
            gameInfo.insert(new Element('div', {
                'class': 'progressBarBG'
            }));
            gameInfo.insert(new Element('p', {
                'class': 'numberPercent',
                id: 'percent-' + technoId
                }).update(metaGame.downloadedPercent() + '%'));
        }
        gameInfo.insert(new Element('p', {
            'class': 'infoText',
            id: 'processInfo-' + technoId
            }).update(metaGame.getDownloadedSize() + ' / ' + metaGame.getFullSize()));
        return gameInfo;
    },
    addDownloadingButtons: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'downloadingButtons'
        });
    },
    addDownloadedButtons: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'downloadedButtons'
        });
    },
    addDownloadOnOff: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'downloadOnOff'
        });
    },
    addDownloadPriority: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'downloadPriority'
        }).insert(new Element('div', {
            'class': 'buttonContainer'
        }));
    },
    addDownloadingRemove: function(technoId, metaGame) {
        return new Element('div', {
            'class': 'downloadingRemove'
        }).insert(
            new Element('a', {
                'class': 'buttonRemoveSmall',
                href: '#remove'
            }).observe('click', this.removeGame.bind(this))
        );
    },
    addListStatusAll: function() {
        var btStartStop = $('buttonPauseStart');
        btStartStop.insert(new Element('a', {
            'class': 'buttonPlayAll'
        }).update('Start').observe('click', this.startDownloadList.bind(this)));
    },
    refreshPriority: function(p) {
        if (!p) return;
        var info = this.getInfo(p);
        var container = info.element.down('div.downloadPriority').down().update();
        if (!this.inDownload.get(info.technoId)) return;
        if (info.order != 0) {
            container.insert(new Element('a', {
                'class': 'buttonUp',
                href: '#increase'
            }).observe('click', this.moveGameUp.bind(this)));
        }
        if (++info.order != this.inDownload.size()) {
            container.insert(new Element('a', {
                'class': 'buttonDown',
                href: '#decrease'
            }).observe('click', this.moveGameDown.bind(this)));
        }
    },
    refreshGameInfo: function(p, forceReady) {
        var info = this.getInfo(p);
        var progress = info.element.down('div.progressBarBG');
        if (progress) {
            progress.update();
        } else {
            return false;
        }
        if (info.metaGame.isFullyCached() || forceReady) {
            progress.insert(new Element('div', {
                id: 'progressBar-' + info.technoId,
                'class': 'progressBarFill progressComplete'
            }));
        } else {
            progress.insert(new Element('div', {
                id: 'progressBar-' + info.technoId,
                'class': 'progressBarFill' + (info.metaGame.isReady() ? ' progressReady' : ' progressIncomplete')
            }).setStyle({
                width: info.metaGame.downloadedPercent() + '%'
            }));
            progress.insert(new Element('div', {
                'class': 'progressBarMark'
            }).setStyle({
                marginLeft: info.metaGame.minDownloadedPercent() + '%'
            }).insert(new Element('a', {
                'class': 'progressBarInfo tooltip righttip',
                title: i18n('addGameInfo5')
                }).setStyle({
                cursor: 'default'
            }))
            );
        }
    },
    refreshDownloadingButtons: function(p, options) {
        var info = this.getInfo(p);
        var metaGame = info.metaGame;
        metaGame.update();
        var buttons = info.element.down('div.downloadingButtons').update();
		
        var btPlay = new Element('div', {
            'class': 'buttonPlay buttonWidth1'
        });
        var aPlay = new Element('a', {
            href: '#launch'
        });
        aPlay.insert(new Element('span', {
            'class': 'buttonD_left'
        }));
        aPlay.insert(new Element('span', {
            'class': 'buttonD_center buttonWidth1Center'
        }).insert(
            new Element('strong').update(i18n('addDownloadingButtons3'))
            ));
        aPlay.insert(new Element('span', {
            'class': 'buttonD_right'
        }));
        btPlay.insert(aPlay);
        buttons.insert(btPlay);

        if (metaGame.commandLines.size() > 1) {
            if (options && options.showOptions) {
                var btOptions = new Element('div', {
                    'class': 'buttonOption buttonOptions buttonWidth1 mygames downloading',
                    id: 'options-' + metaGame.technoId
                })
                aOptions = new Element('a', {
                    href: '#options' + (!metaGame.isReady() ? '_inaccessibly' : '_accessibly')
                    });
                aOptions.insert(new Element('span', {
                    'class': 'buttonD_left'
                }));
                aOptions.insert(new Element('span', {
                    'class': 'buttonD_center buttonWidth1Center'
                }).insert(
                    new Element('strong').update(i18n('addDownloadingButtonsOptions'))
                    ));
                aOptions.insert(new Element('span', {
                    'class': 'buttonD_right'
                }));
                btOptions.insert(aOptions);
                buttons.insert(btOptions);
            }
        } else {
            btPlay.addClassName('buttonCentred');
        }

        if (metaGame.isReady()) {
            aPlay.observe('click', this.launch.bind(this));
        } else {
            btPlay.addClassName('buttonInactive');
            if (btOptions) btOptions.addClassName('buttonInactive');
        }
	    
        if (metaGame.isMultiPlayer) {
            btPlay.addClassName('btMultiPlayer');
            if (btOptions) btOptions.addClassName('btMultiPlayerOptions');
            buttons.insert(new Element('a', {
                'class': 'buttonMultiplayer getMultiplayerKey',
                href: '#multi_player_key_' + metaGame.gameId
            }).update(i18n('addDownloadingButtons1'))
                );
            if (options && options.showMultiplayerInfo) {
                buttons.insert(new Element('a', {
                    'class': 'multiplayerInfo tooltip righttip',
                    title: i18n('addDownloadingButtons2')
                }).setStyle({
                    cursor: 'default'
                })
                );
            }
        }
    },
    refreshDownloadedButtons: function(p, options) {
        var info = this.getInfo(p);
        var metaGame = info.metaGame;
        var buttons = info.element.down('div.downloadedButtons').update();

        var btPlay = new Element('a', {
            'class': 'buttonPlay'
        }).observe('click', this.launch.bind(this));
        buttons.insert(btPlay);
        if (metaGame.commandLines.size() > 1) {
            if (options && options.showOptions) {
                var btOptions = new Element('div', {
                    'class': 'buttonOptions mygames btOptionsClass',
                    id: 'options-' + metaGame.technoId
                }).insert(new Element('a', {
                    href: '#options'
                }).insert(new Element('span')));
                buttons.insert(btOptions);
            }
        }
        var btRemove = new Element('a', {
            'class': 'buttonRemove',
            href: '#remove'
        }).update(i18n('addDownloadedButtons3'));
        btRemove.observe('click', this.removeGame.bind(this));
        buttons.insert(btRemove);

        if (metaGame.isMultiPlayer) {
            btPlay.addClassName('btMultiPlayer');
            if (btOptions) btOptions.addClassName('btMultiPlayer');
            var displayKeyButton = new Element('a', {
                'class': 'buttonMultiplayer getMultiplayerKey',
                href: '#multi_player_key_' + metaGame.gameId
            }).update(i18n('addDownloadedButtons1'));
            buttons.insert(displayKeyButton);
            new MultiPlayerKey();
            if (options && options.showMultiplayerInfo) {
                buttons.insert(new Element('a', {
                    'class': 'multiplayerInfo tooltip righttip',
                    title: i18n('addDownloadedButtons2')
                }).setStyle({
                    cursor: 'default'
                })
                );
            }
        }
    },
    refreshDownloadedBrowserButtons: function(p, options) {
        var info = this.getInfo(p);
        var metaGame = info.metaGame;
        var buttons = info.element.down('div.downloadedButtons').update();
		
        var btPlay = new Element('a', {
            'class': 'buttonPlay'
        }).observe('click', this.launch.bind(this));
        buttons.insert(btPlay);
        var btRemove = new Element('a', {
            'class': 'buttonRemove',
            href: '#remove'
        }).update(i18n('addDownloadedButtons3'));
        btRemove.observe('click', this.removeGame.bind(this));
        buttons.insert(btRemove);
    },
    refreshDownloadOnOff: function(p) {
        var info = this.getInfo(p);
        var buttons = info.element.down('div.downloadOnOff');
        var btOnOff = new Element('div', {
            'class': 'buttonContainer'
        });
        if (this.inDownload.get(info.technoId)) {
            btOnOff.insert(new Element('a', {
                'class': 'buttonOn'
            }));
            btOnOff.insert(new Element('a', {
                'class': 'buttonOff buttonOff_inactive'
            }).observe('click', this.removeFromList.bind(this)))
        } else {
            btOnOff.insert(new Element('a', {
                'class': 'buttonOn buttonOn_inactive'
            }).observe('click', this.addToList.bind(this)))
            btOnOff.insert(new Element('a', {
                'class': 'buttonOff'
            }));
        }
        buttons.update(btOnOff);
    },
    refreshListStatusAll: function(isDownloadActive) {
        log.debug("start refreshListStatusAll")
        log.debug("this.isDownloadActive : "+this.isDownloadActive)
        log.debug("isDownloadActive : "+isDownloadActive)
        var btStartStop = $('buttonPauseStart');
        if (!btStartStop || this.isDownloadActive == isDownloadActive) return;
        this.isDownloadActive = isDownloadActive;
        btStartStop.update();
        if (isDownloadActive) {
            var a = new Element('a', {
                'class': 'buttonStopAll'
            }).update('Stop');
            a.observe('click', this.stopDownloadList.bind(this));
        } else {
            var a = new Element('a', {
                'class': 'buttonPlayAll'
            }).update('Start');
            a.observe('click', this.startDownloadList.bind(this))
        }
        a.setStyle({
            cursor: 'pointer'
        });
        btStartStop.insert(a);
        log.debug("end refreshListStatusAll");
    },
    refreshBg: function(technoId, state) {
        log.debug("refreshBg : "+technoId+" / "+state)
        var bg = $('bg-' + technoId);
        var skin = $('skin');
        if (!bg || !skin) return;
        var imgUrl = DEFINE.get('MY_GAMES_GRADIENT');
        if (state == enumGameState.DOWNLOADING) {
            imgUrl = DEFINE.get('MY_GAMES_GRADIENT_HILIGHT');
        }
        if (bg.src != imgUrl) bg.src = imgUrl;
    },
    addOptions: function(metaGame) {
        if (metaGame.commandLines.size() < 1) return;
        var optContainer = new Element('div', {
            id: 'expand-' + metaGame.technoId,
            'class': 'optionExpand'
        }).setStyle({
            'display': 'none'
        });
        var wrapper = new Element('div');
        var ulContainer = new Element('ul', {
            'class': 'optionList'
        });
        metaGame.commandLines.each(function(cmdLine) {
            var li = new Element('li').insert(new Element('a', {
                'class': 'optionSet',
                href: '#option_' + cmdLine.snumber
                }).update(cmdLine.name));
            ulContainer.insert(li);
        });
        wrapper.insert(ulContainer);
        optContainer.insert(wrapper);
        if (this.downloaded.get(metaGame.technoId)) {
            $('optionExpandContainerA').insert(optContainer);
        } else {
            $('optionExpandContainer').insert(optContainer);
        }
    },
    render: function() {
        try {
            this.showInProgress();
		
            this.inDownload.keys().each(function(technoId, iter) {
                var metaGame = this.inDownload.get(technoId);
                if (metaGame.isDownloadNow()) {
                    log.debug('game inprocess. technoId: ' + technoId);
                    this.gameInProcessTechnoId = technoId;
                }
                var li = new Element('li', {
                    id: 'dsort' + iter,
                    'class': 't-' + technoId
                    });
                var wrapper = new Element('div');
                wrapper.insert(this.addGradient(technoId, metaGame));
                wrapper.insert(this.addFavorite(technoId, metaGame));
                wrapper.insert(this.addGameInfo(technoId, metaGame, {
                    showProgressBar: 1,
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                }));
                wrapper.insert(this.addDownloadingButtons(technoId, metaGame));
                wrapper.insert(this.addDownloadOnOff(technoId, metaGame));
                wrapper.insert(this.addDownloadPriority(technoId, metaGame));
                wrapper.insert(this.addDownloadingRemove(technoId, metaGame));
                li.insert(wrapper);
                //li.hide();
                $(this.constant.inProgress).insert(li);
                this.refreshPriority(li);
                this.refreshGameInfo(li);
                this.refreshDownloadingButtons(li, {
                    showProgressBar: 1,
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                });
                this.refreshDownloadOnOff(li);
                if (parseInt(DEFINE.get('MY_GAMES_OPTIONS'))) {
                    this.addOptions(metaGame);
                }
            //Effect.BlindDown(li, {queue: 'end', duration: this.myEffects.create });
            }.bind(this));

            var inDownloadSize = this.inDownload.size();
            this.notInDownload.keys().each(function(technoId, iter) {
                var metaGame = this.notInDownload.get(technoId);
                var li = new Element('li', {
                    id: 'dsort' + (inDownloadSize + iter),
                    'class': 't-' + technoId
                    });
                var wrapper = new Element('div');
                wrapper.insert(this.addGradient(technoId, metaGame));
                wrapper.insert(this.addFavorite(technoId, metaGame));
                wrapper.insert(this.addGameInfo(technoId, metaGame, {
                    showProgressBar: 1,
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                }));
                wrapper.insert(this.addDownloadingButtons(technoId, metaGame));
                wrapper.insert(this.addDownloadOnOff(technoId, metaGame));
                wrapper.insert(this.addDownloadPriority(technoId, metaGame));
                wrapper.insert(this.addDownloadingRemove(technoId, metaGame));
                li.insert(wrapper);
                //li.hide();
                $(this.constant.inProgress).insert(li);
                this.refreshGameInfo(li);
                this.refreshDownloadingButtons(li, {
                    showProgressBar: 1,
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                });
                this.refreshDownloadOnOff(li);
                this.refreshPriority(li);
                if (parseInt(DEFINE.get('MY_GAMES_OPTIONS'))) {
                    this.addOptions(metaGame);
                }
            //Effect.BlindDown(li, {queue: 'end', duration: this.myEffects.create });
            }.bind(this));
		
            var ul = new Element('ul', {
                id: 'downloadGamesId',
                'class': 'downloadGames'
            });

		
            this.downloaded.keys().each(function(technoId, iter) {
                var metaGame = this.downloaded.get(technoId);
                var li = new Element('li', {
                    id: 'csort' + iter,
                    'class': 't-' + technoId
                    });
                var wrapper = new Element('div');
                wrapper.insert(this.addGradient(technoId, metaGame));
                wrapper.insert(this.addFavorite(technoId, metaGame));
                wrapper.insert(this.addGameInfo(technoId, metaGame, {
                    showProgressBar: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_PROGRESSBAR')),
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                }));
                wrapper.insert(this.addDownloadedButtons(technoId, metaGame));
                li.insert(wrapper);
                //li.hide();
                ul.insert(li);
                this.refreshGameInfo(li, true);
                this.refreshDownloadedButtons(li, {
                    showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO')),
                    showOptions: parseInt(DEFINE.get('MY_GAMES_OPTIONS'))
                });
                if (parseInt(DEFINE.get('MY_GAMES_OPTIONS'))) {
                    this.addOptions(metaGame);
                }
            //Effect.BlindDown(li, {queue: 'end', duration: this.myEffects.create });
            }.bind(this));
		
            if (this.browser) {
                var ul = new Element('ul', {
                    id: 'downloadBrowserGamesId',
                    'class': 'downloadGames'
                });
                $(this.constant.readyBrowserGames).insert(ul);
    
                this.browser.keys().each(function(technoId, iter) {
                    var metaGame = this.browser.get(technoId);
                    var li = new Element('li', {
                        id: 'cbsort' + iter,
                        'class': 't-' + technoId
                        });
                    var wrapper = new Element('div');
                    wrapper.insert(this.addGradient(technoId, metaGame));
                    wrapper.insert(this.addFavorite(technoId, metaGame));
                    wrapper.insert(this.addGameInfo(technoId, metaGame, {
                        showProgressBar: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_PROGRESSBAR')),
                        showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
                    }));
                    wrapper.insert(this.addDownloadedButtons(technoId, metaGame));
                    li.insert(wrapper);
                    //li.hide();
                    ul.insert(li);
                    this.refreshGameInfo(li, true);
                    this.refreshDownloadedBrowserButtons(li);
                //Effect.BlindDown(li, {queue: 'end', duration: this.myEffects.create });
                }.bind(this));
            }
		
            this.addListStatusAll();
		
            if (this.gameInProcessTechnoId) {
                this.gameDownloadingStartCB(this.gameInProcessTechnoId);
                this.refreshListStatusAll(true);
            }
            if (typeof(MultiPlayerKey) == 'function') new MultiPlayerKey();
            if (typeof(MFTooltip) == 'function') new MFTooltip();
            if (typeof(Options) == 'function') new Options();

        } catch(e) {
            log.err(e);
        }
    },
    getGameById: function(technoId) {
        if (this.inDownload.get(technoId)) {
            return this.inDownload.get(technoId);
        }
        if (this.downloaded.get(technoId)) {
            return this.downloaded.get(technoId);
        }
        if (this.notInDownload.get(technoId)) {
            return this.notInDownload.get(technoId);
        }
        if (this.browser) {
            if (this.browser.get(technoId)) {
                return this.browser.get(technoId);
            }
        }
        return false;
    },
    getInfo: function(p) {
        var baseLi = p;
        if (!Object.isElement(p)) {
            baseLi = Event.element(p).up('li');
        }
        var technoId = baseLi.className.match(/t-(\d+)/)[1];
        var game = this.getGameById(technoId);
        var order = null;
        try {
            order = parseInt(baseLi.id.match(/.+(\d+)/)[1]);
        } catch(e) { }
        return {
            element: baseLi,
            technoId: technoId,
            technology: game.technology,
            metaGame: game,
            order: order
        }
    },
    launch: function(p) {
        var info = this.getInfo(p);
        if (!info.metaGame.isBrowser) {
            if (typeof(gameManager) == 'object') {
                gameManager.launch(info.technoId, info.metaGame.technology, 1);
            } else {
                var gm = new GameManager();
                gm.launch(info.technoId, info.metaGame.technology, 1);   
            }
        } else {
            log.debug('redirect to game page');
            window.location = info.metaGame.gameUrl + '?autostart=1';
        }
    },
    rebuildOrderDown: function(current) {
        var count = this.inDownload.size() + this.notInDownload.size();
        current.element.id = 'tmp';
        for(var i = (current.order + 1); i < count; i++) {
            var n = $('dsort' + i);
            n.id = 'dsort' + --this.getInfo(n).order;
            this.refreshPriority(n);
        }
        current.element.id = 'dsort' + (count - 1);
        this.refreshPriority(current.element);
    },
    rebuildOrderUp: function(current) {
        //		var count = this.inDownload.size() + this.notInDownload.size();
        current.element.id = 'tmp';
        for (var i = current.order; i >= 1; i--) {
            var n = $('dsort' + (i - 1));
            n.id = 'dsort' + ++this.getInfo(n).order;
        }
        current.element.id = 'dsort0';
        this.inDownload.keys().each(function(technoId) {
            this.refreshPriority($$('li.t-' + technoId).first());
        }.bind(this));
    },
    startDownloadList: function() {
        log.debug('start download list');
        // check dl rights and populate session
        var technoId = this.inDownload.keys().first();
        var firstGame = this.getGameById(technoId);
        var checkGameUrl = new UrlConstructor('profile/game_checker');
        checkGameUrl.addVar('process', 'download');
        checkGameUrl.addVar('technoId', technoId);
        checkGameUrl.addVar('technology', firstGame.technology);
        checkGameUrl.addVar('commandLine', firstGame.commandLines);
        new Ajax.Request(checkGameUrl.construct(), {
            method: 'get',
            //if check ok, then continue download
            onComplete: function() {
                var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
                log.debug('Check up complete. Call buttonStartDownloadListAllTechno params: '+ url.construct());
                this.downloadClick = technoId;
                buttonStartDownloadListAllTechno(url.construct());
            }.bind(this)
        });
    },
    stopDownloadList: function() {
        buttonPauseDownloadListAllTechno();
        var technoId = this.inDownload.keys().first();
        var firstGame = this.getGameById(technoId);
        firstGame.gameInfo.strActive = 0;
    },
    removeFromList: function(p) {
        var info = this.getInfo(p);
        removeToDownloadListAllTechno(info.technoId, info.technology);
        log.debug('remove from download list. techno id: ' + info.technoId + ' technology: ' + info.technology);
        if (info.technology == enumGameTechno.YUMMY_TECHNO) this.removeFromListCB(info.technoId);
    },
    removeFromListCB: function(technoId) {
        this.notInDownload.set(technoId, this.inDownload.unset(technoId));
        var current = this.getInfo($$('li.t-' + technoId).first());
        var count = this.inDownload.size() + this.notInDownload.size();
        setTimeout(function() {
            this.startDownloadList();
        }.bind(this), 5000);
        var rowHeight = parseInt(DEFINE.get('MY_GAMES_QUEUE_OFFSET'));
        new Effect.Opacity(current.element, {
            queue: 'end',
            from: 1.0,
            to: 0,
            duration: this.myEffects.moveFast,
            afterFinish: function() {
                this.refreshDownloadOnOff(current.element);
            }.bind(this)
        });
        for (var i = current.order; i < count; i++) {
            new Effect.Move($('dsort' + i), {
                queue: 'end',
                y: - rowHeight,
                transition: Effect.Transitions.sinoidal,
                duration: this.myEffects.moveFast
                });
        }
        new Effect.Move(current.element, {
            queue: 'end',
            y: rowHeight * (count - current.order),
            transition: Effect.Transitions.full
            });
        new Effect.Opacity(current.element, {
            queue: 'end',
            from: 0,
            to: 1.0,
            duration: this.myEffects.moveFast,
            afterFinish: function() {
                this.rebuildOrderDown(current);
            }.bind(this)
        });
    },
    addToList: function(p) {
        var gm = new GameManager();
        var info = this.getInfo(p);
        gm.addToDownloadList(info.technoId, info.technology, 1, info.metaGame.title);
        if (info.technology == enumGameTechno.YUMMY_TECHNO) this.addToListCB(info.technoId);
    },
    addToListCB: function(technoId) {
        this.inDownload.set(technoId, this.notInDownload.unset(technoId));
        var current = this.getInfo($$('li.t-' + technoId).first());
        var rowHeight = parseInt(DEFINE.get('MY_GAMES_QUEUE_OFFSET'));
        new Effect.Opacity(current.element, {
            queue: 'end',
            from: 1.0,
            to: 0,
            duration: this.myEffects.moveFast,
            afterFinish: function() {
                this.refreshDownloadOnOff(current.element);
            }.bind(this)
        });
        for (var i = current.order; i >= 1; i--) {
            new Effect.Move($('dsort' + (i - 1)), {
                queue: 'end',
                y: rowHeight,
                transition: Effect.Transitions.sinoidal,
                duration: this.myEffects.moveFast
                });
        }
        new Effect.Move(current.element, {
            queue: 'end',
            y: -rowHeight * parseInt(current.order),
            transition: Effect.Transitions.full
            });
        new Effect.Opacity(current.element, {
            queue: 'end',
            from: 0,
            to: 1.0,
            duration: this.myEffects.moveFast,
            afterFinish: function() {
                this.rebuildOrderUp(current);
            }.bind(this)
        });
    },
    removeGame: function(p) {
        var current = this.getInfo(p);
        if (current.metaGame.isActive()) {
            alert(i18n('deleteFromDownloadList1'));
            return;
        }
        try {
            if (confirm(i18n('deleteFromDownloadList2'))) {
                if (current.technology == enumGameTechno.GAMETAP_TECHNO) {
                    deleteGameAllTechno(current.technoId, false, current.technology);
                    if (current.technology == enumGameTechno.YUMMY_TECHNO) this.removeGameCB(current.technoId, false);
                } else {
                    if (confirm(i18n('deleteFromDownloadList3'))) {
                        if (this.notInDownload.get(current.technoId)) return;
                        deleteGameAllTechno(current.technoId, true, current.technology);
                        if (current.technology == enumGameTechno.YUMMY_TECHNO) this.removeGameCB(current.technoId, true);
                    } else { 
                        deleteGameAllTechno(current.technoId, false, current.technology);
                        if (current.technology == enumGameTechno.YUMMY_TECHNO) this.removeGameCB(current.technoId, false);
                    }
                }
            }
        } catch(e) {
            log.err('Delete failed');
        }
    },
    moveFromDownloadedToNotInDownload: function(technoId) {
        log.debug('moveFromDownloadedToNotInDownload technoId: ' + technoId);
        this.notInDownload.set(technoId, this.downloaded.unset(technoId));
        var current = this.getInfo($$('li.t-' + technoId).first());
        Effect.BlindUp(current.element, {
            queue: 'end',
            duration: this.myEffects.remove,
            afterFinish: function() {
                current.element.remove();
                this.renderNotInDownloadGameCB(technoId);
                this.optionsToInDownload(technoId);
            }.bind(this)
        })
    },
    renderNotInDownloadGameCB: function(technoId) {
        var ul = $('downloadGamesId');
        var metaGame = this.notInDownload.get(technoId);
        if (!metaGame) return;
        var li = new Element('li', {
            id: 'dsort' + (this.inDownload.size() + this.notInDownload.size() - 1),
            'class': 't-' + technoId
            });
        var wrapper = new Element('div');
        wrapper.insert(this.addGradient(technoId, metaGame));
        wrapper.insert(this.addFavorite(technoId, metaGame));
        wrapper.insert(this.addGameInfo(technoId, metaGame, {
            showProgressBar: 1,
            showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
        }));
        wrapper.insert(this.addDownloadingButtons(technoId, metaGame));
        wrapper.insert(this.addDownloadOnOff(technoId, metaGame));
        wrapper.insert(this.addDownloadPriority(technoId, metaGame));
        wrapper.insert(this.addDownloadingRemove(technoId, metaGame));
        li.insert(wrapper);
        li.hide();
        $(this.constant.inProgress).insert(li);
        setTimeout(function() {
            this.refreshGameInfo(li);
            this.refreshDownloadingButtons(li, {
                showProgressBar: 1,
                showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
            });
            this.refreshDownloadOnOff(li);
            this.refreshPriority(li);
        }.bind(this), 5000);
        Effect.BlindDown(li, {
            queue: 'end',
            duration: this.myEffects.create
            });
    },
    removeGameCB: function(technoId, saveInfo) {
        var current = this.getInfo($$('li.t-' + technoId).first());
        if (saveInfo) {
            if (this.inDownload.get(current.technoId)) {
                this.removeFromListCB(technoId);
            } else {
                this.moveFromDownloadedToNotInDownload(technoId);
            }
        } else {
            Effect.BlindUp(current.element, {
                queue: 'end',
                duration: this.myEffects.remove,
                afterFinish: function() {
                    if (this.downloaded.get(current.technoId)) {
                        this.downloaded.unset(current.technoId);
                        return true;
                    }
                    if (this.inDownload.get(current.technoId)) {
                        this.inDownload.unset(current.technoId);
                    }
                    if (this.notInDownload.get(current.technoId)) {
                        this.notInDownload.unset(current.technoId);
                    }
                    var count = this.inDownload.size() + this.notInDownload.size();
                    for (var i = current.order; i < (count); i++) {
                        var n = $('dsort' + (i + 1));
                        n.id = 'dsort' + --this.getInfo(n).order;
                    }
                    current.element.remove();
                    this.refreshPriority($('dsort0'));
                    this.refreshPriority($('dsort' + (this.inDownload.size() - 1)));
                }.bind(this)
            });
        }
    },
    moveGameUp: function(event) {
        var current = this.getInfo(event);
        var offset = parseInt(DEFINE.get('MY_GAMES_QUEUE_OFFSET'));
        var oldFirstGameDownloadList = get_first_game_in_downloadlist();
        //increase_game_in_downloadlist(new String(current.technoId));
        increaseDownloadPriorityAllTechno(current.technoId, current.technology);
        var newFirstGameDownloadList = get_first_game_in_downloadlist();
        var previous = this.getInfo($('dsort' + (current.order - 1)));
        current.element.id = 'dsort' + --current.order;
        previous.element.id = 'dsort' + ++previous.order;
        this.refreshPriority(current.element);
        this.refreshPriority(previous.element);
        new Effect.Move(current.element, {
            y: - offset,
            transition: Effect.Transitions.spring,
            duration: this.myEffects.move
            });
        new Effect.Parallel([
            new Effect.Move(previous.element, {
                y: offset,
                transition: Effect.Transitions.sinoidal,
                sync: true
            }),
            new Effect.Pulsate(previous.element, {
                pulses: 1,
                sync: true
            })
            ], {
                duration: this.myEffects.move
                });
        log.debug("oldFirstGameDownloadList : "+oldFirstGameDownloadList+" - newFirstGameDownloadList : "+newFirstGameDownloadList)
        if(oldFirstGameDownloadList[0] != newFirstGameDownloadList[0]){
            buttonPauseDownloadListAllTechno();
            //var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
            setTimeout(function() {
                var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
                buttonStartDownloadListAllTechno(url.construct());
            }.bind(this), 2000);
        //buttonStartDownloadListAllTechno(url.construct());
        }
    },
    moveGameDown: function(event) {
        var current = this.getInfo(event);
        var offset = parseInt(DEFINE.get('MY_GAMES_QUEUE_OFFSET'));
        //decrease_game_in_downloadlist(new String(current.technoId));
        var oldFirstGameDownloadList = get_first_game_in_downloadlist();
        decreaseDownloadPriorityAllTechno(current.technoId, current.technology);
        var newFirstGameDownloadList = get_first_game_in_downloadlist();
        var next = this.getInfo($('dsort' + (current.order + 1)));
        current.element.id = 'dsort' + ++current.order;
        next.element.id = 'dsort' + --next.order;
        this.refreshPriority(current.element);
        this.refreshPriority(next.element);
        new Effect.Move(next.element, {
            y: - offset,
            transition: Effect.Transitions.spring,
            duration: this.myEffects.move
            });
        new Effect.Parallel([
            new Effect.Move(current.element, {
                y: offset,
                transition: Effect.Transitions.sinoidal,
                sync: true
            }),
            new Effect.Pulsate(current.element, {
                pulses: 1,
                sync: true
            })
            ], {
                duration: this.myEffects.move
                });
        log.debug("oldFirstGameDownloadList : "+oldFirstGameDownloadList+" - newFirstGameDownloadList : "+newFirstGameDownloadList)
        if(oldFirstGameDownloadList[0] != newFirstGameDownloadList[0]){
            buttonPauseDownloadListAllTechno();
            //var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
            setTimeout(function() {
                var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
                buttonStartDownloadListAllTechno(url.construct());
            }.bind(this), 2000);
        //buttonStartDownloadListAllTechno(url.construct());
        }
    },
    renderDownloadedGameCB: function(technoId) {
        log.debug('render downloaded game. technoId: ' + technoId);
        try {
            var ul = $('downloadGamesId');
            var metaGame = this.downloaded.get(technoId);
            if (!metaGame)
                return;
            metaGame.exentUpdate();
            var li = new Element('li', {
                'class': 't-' + technoId
            });
            var wrapper = new Element('div');
            wrapper.insert(this.addGradient(technoId, metaGame));
            wrapper.insert(this.addFavorite(technoId, metaGame));
            wrapper.insert(this.addGameInfo(technoId, metaGame, {
                showProgressBar: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_PROGRESSBAR')),
                showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO'))
            }));
            wrapper.insert(this.addDownloadedButtons(technoId, metaGame));
            li.insert(wrapper);
            li.hide();
            ul.insert(li);
            this.refreshGameInfo(li, true);
            this.refreshDownloadedButtons(li, {
                showMultiplayerInfo: parseInt(DEFINE.get('MY_GAMES_DOWNLOADED_SHOW_MULTIPLAYER_INFO')),
                showOptions: parseInt(DEFINE.get('MY_GAMES_OPTIONS'))
            });
            Effect.BlindDown(li, {
                queue: 'end',
                duration: this.myEffects.create
            });
        } catch(e) {
            log.err('problem with render downloaded game. msg: ' + e.message);
        }
    },
    moveGameToCompletedCB: function(technoId) {
        var current = this.getInfo($$('li.t-' + technoId).first());
        if (this.downloaded.get(technoId)) return;
        var rowHeight = parseInt(DEFINE.get('MY_GAMES_QUEUE_OFFSET'));
        new Effect.Parallel([
            new Effect.Move(current.element, {
                y: - rowHeight * (parseInt(current.order) + 1),
                transition: Effect.Transitions.sinoidal,
                sync: true
            }),
            new Effect.Opacity(current.element, {
                from: 1.0,
                to: 0,
                sync: true
            })
            ], {
                duration: this.myEffects.moveSlow,
                afterFinish: function() {
                    this.downloaded.set(technoId, this.inDownload.unset(technoId));
                    var count = this.inDownload.size() + this.notInDownload.size();
                    for (var i = current.order; i < (count); i++) {
                        var n = $('dsort' + i);
                        //log.debug('i = ' + i + 'n = ' + n);
                        n.id = 'dsort' + --this.getInfo(n).order;
                    }
                    current.element.remove();
                    this.refreshPriority($('dsort0'));
                    this.refreshPriority($('dsort' + (this.inDownload.size() - 1)));
                    setTimeout(function() {
                        this.renderDownloadedGameCB(technoId);
                        this.refreshListStatusAll(false);
                        if (parseInt(DEFINE.get('MY_GAMES_OPTIONS'))) {
                            this.optionsToDownloaded(technoId);
                            new Options();
                        }
                        this.startNextGameInList();
                    }.bind(this), 2000);
                }.bind(this)
            });
    },
    startNextGameInList: function() {
        log.debug("startNextGameInList")
        if (!this.inDownload.size()) return false;
        var technoId = this.inDownload.keys().first();
        var metaGame = this.inDownload.get(technoId);
        log.debug('start next game in list. technoId: ' + technoId);
        if (metaGame.technology == enumGameTechno.GAMETAP_TECHNO) {
            log.debug('set active next game in list. technoId: ' + technoId);
            try {
                this.exentUpdater.stop();
                this.exentUpdater = null;
            } catch(e) {
                log.err('try stop periodical executer. msg: ' + e.message);
            }
            this.gameDownloadingStartCB(technoId);
        } else {
            var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
            buttonStartDownloadListAllTechno(url.construct());
        }
    },
    optionsToDownloaded: function(technoId) {
        try {
            if (!$('optionExpandContainerA')) return ;
            $('optionExpandContainerA').insert($('expand-' + technoId).remove());
        } catch(e) {
            log.err('Move options container to "downloaded" failed. ' + e.message);
        }
    },
    optionsToInDownload: function(technoId) {
        try {
            if (!$('optionExpandContainer')) return ;
            $('optionExpandContainer').insert($('expand-' + technoId).remove());
        } catch(e) {
            log.err('Move options container to "in download" failed. ' + e.message);
        }
    },
    updateGameInfo: function(technoId) {
        var game = this.getGameById(technoId);
        var processInfo = $('processInfo-' + technoId);
        var progressBar = $('progressBar-' + technoId);
        var percent = $('percent-' + technoId);
        if (!processInfo || !progressBar || !percent) {
            return false;
        }
        processInfo.update(
            game.getDownloadedSize() + '&nbsp;/&nbsp;' + game.getFullSize() + ' ' +
            '(' + game.getBandwidth() + ') ' +
            game.getProcessTimeleft()
            );
        progressBar.setStyle({
            width: game.downloadedPercent() + '%'
            });
        percent.update(game.downloadedPercent() + '%');
    },
    updateReadyToPlayCB: function(technoId) {
        var progressBar = $('progressBar-' + technoId);
        if (progressBar.hasClassName('progressIncomplete')) {
            progressBar.removeClassName('progressIncomplete').addClassName('progressReady');
            this.refreshDownloadingButtons($$('li.t-' + technoId).first());
        }
    },
    updateProgressCB: function(technoId, downloadedBytes, totalBytesToPlay, totalBytes, timeToPlay, timeToFull, speedKBSec) {
        if (this.downloaded.get(technoId)) return;
        var game = this.getGameById(technoId);
        game.setDownloadProgressInBytes(downloadedBytes, totalBytesToPlay, totalBytes, timeToPlay, timeToFull, speedKBSec);
        this.refreshListStatusAll(true);
        this.refreshBg(technoId, enumGameState.DOWNLOADING);
        this.updateGameInfo(technoId);
    },
    gameDownloadingStartCB: function(technoId) {
        log.debug("start UI download game : "+technoId)
        this.refreshBg(technoId, enumGameState.DOWNLOADING);
        this.refreshListStatusAll(true);
        var game = this.getGameById(technoId);
        if (game.technology == enumGameTechno.YUMMY_TECHNO) return;
        if (this.exentUpdater) return;
        new PeriodicalExecuter(function(pe) {
            try {
                this.exentUpdater = pe;
                if (game.technology == enumGameTechno.GAMETAP_TECHNO) {
                    game.gametapUpdate();
                } else {
                    game.exentUpdate();					
                }
                this.updateGameInfo(technoId);
            } catch(e) {
                log.err(e);
            }
        }.bind(this), 2);
    },
    gameDownloadingStopCB: function(technoId) {
        log.debug("stop UI download game : "+technoId)
        this.refreshBg(technoId, enumGameState.DOWNLOAD_STOP);
        this.refreshListStatusAll(false);
        var game = this.getGameById(technoId);
        var processInfo = $('processInfo-' + technoId);
        if (processInfo) {
            processInfo.update(game.getDownloadedSize() + '&nbsp;/&nbsp;' + game.getFullSize());
        }
        if (this.exentUpdater) {
            try {
                this.exentUpdater.stop();
                this.exentUpdater = null;
            } catch(e) {
                log.err('Stop exent update failed');
            }
        }
    },
    toggleFavorite: function(event) {
        var current = this.getInfo(event);
        var url = new UrlConstructor('profile/toggle_favorite');
        url.addVar('technoId', current.technoId);
        new Ajax.Request(url.construct(), {
            method: 'post',
            onSuccess: function(transport) {
                var obj = transport.responseText.evalJSON();
                var el = current.element.down('div.favourite');
                if (obj.status == 1) el.addClassName('favourite_inactive');
                else if (obj.status == 2) el.removeClassName('favourite_inactive');
            }
        });
    }
});

GameManager = Class.create({
    initialize: function() {
        this.addClass = 'a.addToDownloadList';
        this.launchClass = 'a.launchGame';
        this.browserClass = 'a.launchBrowserGame';
        this.context = $('context').getValue();
        this.inprocess = {
            technoId: null,
            technology: null,
            browser: false
        };
        this.myEffects = {
            showButtons: 0.4
        };
        this.actionClick = false;
        this.downloadClick = false;
        this.redirectionInProcess = false;
        this.blockYummyDownloadNotification = false;
        if(typeof(Engine) == 'object') {
            log.debug('yummy engine detect. init yummy engine');
            this.initYummyEngineEvents();
        } else {
            log.debug('yummy not detected. init yummy engine was skipped');
        }
        
        if (DEFINE.get('TYPE') == 'GT') {
            this.buttonLoading = new ButtonLoading();
            if (!parseInt(MvcSkel.getVar('isAuth'))) {
                log.debug('show download button. user not logged');
                this.buttonLoading.hide();
                $$('.downloadAction').each(function(el) {
                    this.showElement(el);
                }.bind(this));
            }
            if (browserGame) {
                this.buttonLoading.hide();
                $$('.launchBrowserGame').each(function(el) {
                    this.showElement(el);
                }.bind(this));  
            }
        } else {
            this.initGamePageButtons();
        }
                
        $$(this.addClass).each(function(el) {
            if (!el.hasClassName('addToDownloadList') && !el.hasClassName('launchGame')) return;
            el.observe('click', this.despatcher.bind(this));
        }.bind(this));
        $$(this.launchClass).each(function(el) {
            if (!el.hasClassName('addToDownloadList') && !el.hasClassName('launchGame')) return;
            el.observe('click', this.despatcher.bind(this));
        }.bind(this));
        $$(this.browserClass).each(function(el) {
            el.observe('click', this.despatcher.bind(this));
        }.bind(this));
        if (browserGame) {
            this.initAutorun();
        }
    },
   
    onPreCacheComplete: function(technoId, name) {
        log.debug('pre cache complete. technoId:' + technoId + ' name:' + name);
        this.onGameReadyToPlayCB(technoId);
    },
    onCacheComplete: function(technoId, name) {
        log.debug('cache complete. technoId:' + technoId + ' name:' + name);
        // Start Metaboli modification.
        // delete the game from the cookie
        delete_game_in_downloadlist(technoId);
        this.blockYummyDownloadNotification = true;
        // start the next game to download list ONLY YUMMY !!!
        /*var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
		buttonStartDownloadListAllTechno(url.construct());*/
        // End Metaboli modification.
        this.onGameReadyToUse(technoId);
    },
    onInstallComplete: function(technoId, name) {
        log.debug('install complete. technoId:' + technoId + ' name:' + name);
        if (Prototype.Browser.IE) {
    //    CreateShortCuts(technoId, name, DEFINE.get('YUMMY_SHORTCUT_KEY'));
    }
    },
    onDownloadProgressRawNumbers: function(downloadedBytes, totalBytesToPlay, totalBytes, timeToPlay, timeToFull, speedKBSec, technoId, name) {
        if (this.blockYummyDownloadNotification) return ;
        if (this.redirectionCheck(technoId)) return ;
        if (typeof(myGames) == 'object') myGames.updateProgressCB(technoId, downloadedBytes, totalBytesToPlay, totalBytes, timeToPlay, timeToFull, speedKBSec);
        log.debug('download progress. technoId:' + technoId + ' total bytes:' + totalBytes + ' downloaded bytes:' + downloadedBytes);
    },
    onGameEnded: function(technoId, name) {
        log.debug('game ended. technoId:' + technoId + ' name:' + name);
    },
    onGameSessionExpired: function(technoId, name) {
        log.debug('game session expired. technoId:' + technoId + ' name:' + name);
    },
    onGameSessionViolation: function(technoId, name) {
        log.debug('game session violation. technoId:' + technoId + ' name:' + name);
    },
    onGameStarted: function(technoId, name) {
        ww.hide();
        if (this.problematicModal) {
            this.problematicModal.close();
        }
        log.debug('game started. technoId:' + technoId + ' name:' + name);
    },
    onStateChange: function(state, technoId, name) {
        log.debug('state has been changed. state:' + state + ' technoId:' + technoId + ' name:' + name);
        switch(state) {
            case GAME_STATE_NONE :
                this.blockYummyDownloadNotification = true;
                this.onGameDownloadingStopCB(technoId);
                break;
            case GAME_STATE_DOWNLOADING:
                this.blockYummyDownloadNotification = false;
                if (this.redirectionCheck(technoId)) return;
                this.onGameDownloadingStartCB(technoId);
                break;
            case GAME_STATE_PRECACHED:
                break;
            case GAME_STATE_READY:
                break;
            // Start Metaboli modification.
            case "GAME_STATE_REMOVE_DL":
                // delete the gameId in the cookie for remove to download list
                this.blockYummyDownloadNotification = true;
                delete_game_in_downloadlist(technoId);
                break;
            case "GAME_STATE_REMOVE":
                // delete the gameId in the cookie for remove game or game and saves.
                this.blockYummyDownloadNotification = true;
                delete_game_in_downloadlist(technoId);
                break;
            case "GAME_STATE_ADD_DL":
                // add the gameId in the cookie in the first position
                add_game_first_position_queue_list(technoId+"/yummy");
                break;
        // End Metaboli modification.
        }
    },
    onCustomSessionExpireNotice: function(technoId) {
        log.debug('custom session expire notice. technoId:' + technoId);
    },
    onCustomSessionExpired: function(technoId) {
        log.debug('custom session expired. technoId:' + technoId);
    },
    onGamePatching: function(technoId) {
        log.debug('game patcing');
        var url = new UrlSeoConstructor('PROFILE_GAMES');
        var modal = new Control.Modal(false, {
            contents: i18n('yummyOnGamePatching').replace(/\%my_games\%/, url.construct()),
            fade: true, 
            fadeDuration: 0.4,
            opacity: 0.8,
            width: 500,
            containerClassName: 'mfmodal'
        });
        modal.open();
    },
 
    onGameRunning: function(technoId) {
        ww.hide();  
    },
    onGameAddToListCB: function(technoId) {
        if (this.redirectionCheck(technoId)) return;
        if (typeof(myGames) == 'object') myGames.addToListCB(technoId);
    },
    onGameRemoveFromListCB: function(technoId) {
        if (typeof(myGames) == 'object') myGames.removeFromListCB(technoId);
    },
    onGameRemoveCB: function(technoId, saveInfo) {
        if (typeof(myGames) == 'object') myGames.removeGameCB(technoId, saveInfo);
    },
    onGameReadyToPlayCB: function(technoId) {
        if (typeof(myGames) == 'object') myGames.updateReadyToPlayCB(technoId);
    },
    onGameReadyToUse: function(technoId) {
        if (typeof(myGames) == 'object') myGames.moveGameToCompletedCB(technoId);
    },
    onListStopCB: function() {
        if (typeof(myGames) == 'object') myGames.refreshListStatusAll(false);
    },
    onListStartCB: function() {
        if (typeof(myGames) == 'object') myGames.refreshListStatusAll(true);
    },
    onGameDownloadingStartCB: function(technoId) {
        ww.hide();
        if (typeof(myGames) == 'object') myGames.gameDownloadingStartCB(technoId);
    },
    onGameDownloadingStopCB: function(technoId) {
        if (typeof(myGames) == 'object') myGames.gameDownloadingStopCB(technoId);
    },
    redirectionCheck: function(technoId) {
        if (this.redirectionInProcess) return true;
        if (this.context != 'profile_games' && this.actionClick) {
            this.redirectionInProcess = true;
            var url = new UrlSeoConstructor('PROFILE_GAMES');
            window.location = url.construct();
            return true;
        }
        return false;
    },
    getParamsString: function(p) {
        if (!Object.isString(p)) {
            p = Event.element(p);
            if (p.tagName.toLowerCase() != 'a') {
                p = p.up('a');
            }
            if (p.href) {
                return p.href;
            }
        }
        return p;
    },
    getGameInfoFromString: function(str) {
        try {
            var res = this.getParamsString(str).match(/#([a-z]+)_(.+)_([a-z]+)_(\d+)$/i);
            return {
                action: res[1],
                title: res[2],
                technology: res[3],
                technoId: res[4]
            }
        } catch(e) {
            return false;
        }
    },
    despatcher: function(p) {
        try {
            var info = this.getGameInfoFromString(p);
            if (!info) return ;
            if (this.actionClick) return ;
            this.actionClick = true;
            switch (info.action) {
                case 'download' :
                    this.addToDownloadList(info.technoId, info.technology, 1, info.title);
                    break;
                case 'launch' :
                    this.launch(info.technoId, info.technology, 1);
                    break;
                case 'browser' :
                    this.launchBrowserGame(info.technoId, info.technology);
                    break;
            }
        } catch(e) {
            log.err(e);
        }
    },
    initGamePageButtons: function() {
        if (!parseInt(MvcSkel.getVar('isAuth'))) {
            $$('.downloadAction').each(function(el) {
                this.showElement(el);
            }.bind(this));
            return false;
        }
        var metaGame = null;
        $$('.downloadAction').each(function(el) {
            try {
                if (!metaGame) {
                    var info = this.getGameInfoFromString(el.href ? el.href : el.down('.action').href);
                    log.debug('Game techno id: ' + info.technoId);
                    metaGame = new MetaGame(info.technoId, info.technology);
                }
                if (!isOk || !metaGame.isReady()) this.showElement(el);
            } catch(e) {
                log.err(e);
                this.showElement(el);
            }
        }.bind(this));

        $$('.launchAction').each(function(el) {
            try {
                if (!metaGame) {
                    var info = this.getGameInfoFromString(el.href ? el.href : el.down('.action').href);
                    metaGame = new MetaGame(info.technoId, info.technology);
                }
                if (isOk && metaGame.isReady()) this.showElement(el);
            } catch(e) {
                log.err(e);
            }
        }.bind(this));

        if (metaGame && isOk && metaGame.isReady()) {
            var btnMultiPlayer = $$('div.buttonMultiplayer').first();
            var buttonOptions = $$('div.buttonOptions').first();
            if (buttonOptions) this.showElement(buttonOptions, 'end');
            if (btnMultiPlayer) this.showElement(btnMultiPlayer, 'end');
        }
    },
    initGamePageButtonsV2: function() {
        log.debug('init download/launch buttons. user logged');
        this.buttonLoading.hide();
        var launchMetaGame = null;
        $$('.launchAction').each(function(el) {
            try {
                var btn = el.href ? el.href : el.down('.action').href;
                var info = this.getGameInfoFromString(btn);
                metaGame = new MetaGame(info.technoId, info.technology);
                if (isOk && metaGame.isReady()) {
                    this.showElement(el);
                    launchMetaGame = metaGame;
                } 
            } catch(e) {
                log.err(e);
            }
        }.bind(this));
        
        if (launchMetaGame && isOk && launchMetaGame.isReady()) {
            var btnMultiPlayer = $('multiplayer-' + launchMetaGame.technoId);
            if (btnMultiPlayer) this.showElement(btnMultiPlayer, 'end');
        }
        
        if (!launchMetaGame) {
            $$('.downloadAction').each(function(el) {
                try {
                    var btn = el.href ? el.href : el.down('.action').href;
                    var info = this.getGameInfoFromString(btn);
                    metaGame = new MetaGame(info.technoId, info.technology);
                    if (!isOk || !metaGame.isReady()) this.showElement(el);
                } catch(e) {
                    log.err(e);
                    this.showElement(el);
                }
            }.bind(this));
        }
    },
    showElement: function(el, q) {
        q = q ? q : '';
        el.setOpacity(0);
        el.removeClassName('displayNone');
        new Effect.Opacity(el, {
            queue: q,
            from: 0.0,
            to: 1.0,
            duration: this.myEffects.showButtons,
            transition: Effect.Transitions.sinoidal
        });
    },
    initFavorites: function() {
        $$('div.favoriteItem').each(function(el) {
            var info = this.getGameInfoFromString(el.down('a.action').href);
            if (isOk) {
                metaGame = new MetaGame(info.technoId, info.technology);
                if (metaGame.isReady()) this.favoritesShowLaunch(info.technoId);
                else this.favoritesShowDownload(info.technoId);
            } else {
                this.favoritesShowDownload(info.technoId);
            }
        }.bind(this));    
    },
    favoritesShowLaunch: function(technoId) {
        $('play-' + technoId).removeClassName('displayNone');
        if (!$('expand-' + technoId)) return;
        if ($('expand-' + technoId).down('ul.optionList').childElements().size() > 1) {
            $('options-' + technoId).removeClassName('displayNone');
        }
    },
    favoritesShowDownload: function(technoId) {
        $('download-' + technoId).removeClassName('displayNone');
        if (!$('download-info-' + technoId)) return ;
        $('download-info-' + technoId).removeClassName('displayNone');
    },
    addToDownloadList: function(technoId, technology, cmd, title) {
        log.debug('addToDownloadList call. Params: ' + technoId +' '+ technology +' '+ cmd +' '+ title);
        this.playerVersionCheck(technology, function() {
            var checkGameUrl = new UrlConstructor('profile/game_checker');
            checkGameUrl.addVar('process', 'download');
            checkGameUrl.addVar('technoId', technoId);
            checkGameUrl.addVar('technology', technology);
            checkGameUrl.addVar('commandLine', cmd);
            new Ajax.Request(checkGameUrl.construct(), {
                method: 'get',
                onSuccess: function(transport) {
                    var obj = transport.responseText.evalJSON();
                    this.checkUp(obj, function() {
                        var url = new UrlSeoConstructor('ADD_TO_DOWNLOAD_LIST');
                        log.debug('Checkup success. Call addToDownloadListAllTechno params: ' 
                            + url.construct() +' '+ technoId +' '+ cmd +' '+ technology +' '+ title);
                        this.downloadClick = technoId;
                        addToDownloadListAllTechno(url.construct(), technoId, cmd, technology, title);
                    }.bind(this));
                }.bind(this)
            });
        }.bind(this));
    },
    launch: function(technoId, technology, cmd) {
        log.debug('launch call. Params: ' + technoId +' '+ technology +' '+ cmd);
        this.playerVersionCheck(technology, function() {
            var checkGameUrl = new UrlConstructor('profile/game_checker');
            checkGameUrl.addVar('process', 'launch');
            checkGameUrl.addVar('technoId', technoId);
            checkGameUrl.addVar('technology', technology);
            checkGameUrl.addVar('commandLine', cmd);
            new Ajax.Request(checkGameUrl.construct(), {
                method: 'get',
                onSuccess: function(transport) {
                    var obj = transport.responseText.evalJSON();
                    this.checkUp(obj, function() {
                        var url = new UrlSeoConstructor('LAUNCH_GAME');
                        this.inprocess.browser = false;
                        this.inprocess.technoId = technoId;
                        log.debug('call launchGameAllTechno');
                        launchGameAllTechno(url.construct(), technoId, cmd, technology);
                    }.bind(this));
                }.bind(this)
            });
        }.bind(this));
    },
    launchBrowserGame: function(technoId, technology) {
        log.debug('launchBrowserGame call. Params: ' + technoId +' '+ technology);
        if (typeof(playerLogin) == 'undefined' || typeof(ssoToken) == 'undefined') {
            log.err('web player login failed');
            var url = new UrlSeoConstructor('PROFILE_GAMES');
            window.location = url.construct();            
            return false;
        };
        var cntx = $('context').getValue();
        if (!/game_.*/.test(cntx)) {
            var speedLaunchBrowserGame = new UrlSeoConstructor('SPEED_LAUNCH');
            speedLaunchBrowserGame.addVar('gameId', technoId);
            window.location = speedLaunchBrowserGame.construct();
        }
        var checkGameUrl = new UrlConstructor('profile/game_checker');
        checkGameUrl.addVar('process', 'browser');
        checkGameUrl.addVar('technoId', technoId);
        checkGameUrl.addVar('technology', technology);
        new Ajax.Request(checkGameUrl.construct(), {
            method: 'get',
            onSuccess: function(transport) {
                var obj = transport.responseText.evalJSON();
                this.checkUp(obj, function() {
                    $('containerBrowser').removeClassName('displayNone');
                    $('controlsDrawerContainer').removeClassName('displayNone');
                    gameControls.initVolume();
                    this.inprocess.browser = true;
                    this.inprocess.technoId = technoId;
                    $('nameGameProduct').scrollTo();
                    var img = $('btContainer').down('img');
                    if (img) img.src = img.src.replace(/_play/, '_play_disabled');
                    img.up('a').href = 'javascript:void(0)';
                    webPlayer = new WebPlayer(playerLogin, ssoToken, technoId, 'browserPlayer');
                //insertComponentsTechnoEmulator(playerLogin, ssoToken, technoId, 'browserPlayer');
                }.bind(this));
            }.bind(this)
        });
    },
    updateBrowserGameController: function() {
        if (!this.inprocess.browser) return false;
        log.debug('Browser game in process: ' + this.inprocess.technoId);
        var controllerId = new String(player_getJoystickControllerId());
        if (controllerId.empty()) {
            return ;
        //controllerId = 'C218046D-0000-0000-0000-504944564944';
        }
        try {
            var controlUrl = new UrlConstructor('game/browser_controller');
            controlUrl.addVar('controllerId', controllerId);
            controlUrl.addVar('technoId', this.inprocess.technoId);
            log.debug('Controller: ' + controllerId);
            new Ajax.Request(controlUrl.construct(), {
                method: 'get',
                onSuccess: function(transport) {
                    $('drawerJoypad').down('.contentKeyboardsBox').update(transport.responseText);
                    gameControls.joypadActive();
                }.bind(this)
            });
        } catch(e) {
            log.err(e);
        }
    },
    checkUp: function(obj, callback) {
        var run = true;
        if (obj.redirect) {
            log.stop('Need redirect to: ' + obj.redirect);
            window.location = obj.redirect;
            return;
        }
        if (obj.previous) {
            var prevGame = new MetaGame(obj.previous.technoId, obj.previous.technology);
            if (prevGame.isReady()) {
                if (obj.previous.browser) {
                    this.launchBrowserGame(obj.previous.technoId, obj.previous.technology);
                } else {
                    this.launch(obj.previous.technoId, obj.previous.technology, 1);    
                }
                return;
            }
        }
        if (obj.gldeavs) {
            run = false;
            var modalGlde = new Control.Modal(false, {
                contents: i18n('loadingDialog'),
                fade: true, 
                fadeDuration: 0.4,
                opacity: 0.8,
                width: 750,
                containerClassName: 'mfmodal'
            });
            modalGlde.open();
            var urlGldeAvs = new UrlConstructor('Glde/Avs');            
            new Ajax.Request(urlGldeAvs.construct(), {
                onComplete: function(request){
                    modalGlde.update(request.responseText);
                    Event.observe('avsButton', 'click', function() {
                        var exteralUrl = getExternalUrl('https') + 'gamesload/gsp/login.aspx' + 
                        '?provider=metaboli&avs=true&metaboli_avs=true' +
                        '&MasterID=' + obj.info.technoId +
                        '&technology=' + obj.info.technology +
                        '&product_id=' + obj.info.gameId +
                        '&commandLine=' + obj.info.commandLine +
                        '&act=' + obj.info.process +
                        '&st2=' + obj.info.st2;
                        window.open(exteralUrl, '', 'width=640,height=480,menubar=no,toolbar=no,location=no,scrollbars=yes');
                    });
                    Event.observe('modalClose', 'click', function() {
                        modalGlde.close();
                    }.bind(this));
                }.bind(this)
            });
            return;
        }
        /* credit card alerts */
        if (DEFINE.get('CREDITCARD_ALERT') && obj.html) {
            run = false;
            var modal = new Control.Modal(false, {
                contents: obj.html,
                fade: true,
                fadeDuration: 0.4,
                opacity: 0.8,
                overlayCloseOnClick: false,
                containerClassName: 'launch',
                afterOpen: function() {
                    if ($('continueActive') && $('continueUnactive')) {
                        var counter = 15;
                        if ($('timerImg')) {
                            new PeriodicalExecuter(function(pe) {
                                $('timerImg').src = $('timerImg').src.replace(/_(\d+)\.gif$/i, function(str, p1) {
                                    p1 = parseInt(p1);
                                    p1 = (p1 == 1) ? 2 : 1;
                                    return '_' + p1 + '.gif';
                                });
                                $('timerCounter').update(counter);
                                if (counter < 10) {
                                    $('timerCounter').addClassName('s');
                                }
                                if (counter == 0) {
                                    pe.stop();
                                    $('continueUnactive').addClassName('displayNone');
                                    $('continueActive').removeClassName('displayNone');
                                }
                                counter--;
                            }, 1);
                        }
                    }
                    Event.observe('continueActive', 'click', function() {
                        modal.close();
                        callback();
                    });
                }
            });
            modal.open();
            this.actionClick = false;
        }
        /* end of credit card alerts */        
        var er = new ErrorManager(obj);
        if (er.getErrors()) {
            log.err('error(s) detected');
            run = false;
            this.actionClick = false;
        }
        log.debug('checkUp status: ' + (run ? 'true' : 'false'));
        if (run) {
            this.blockYummyDownloadNotification = true;
            if (obj.problematic) {
                this.problematicModal = new Control.Modal(false, {
                    contents: obj.problematic,
                    overlayCloseOnClick: false, 
                    width: 600, 
                    fade: true,
                    fadeDuration: 0.4,
                    opacity: 0.8,
                    containerClassName: 'mfmodal problematic',
                    afterEffect: function() {
                        setTimeout(function() {
                            callback();
                        }, 1000);
                    }
                });
                this.problematicModal.open();
            } else {
                callback();  
            }
        } 
    },
    playerVersionCheck: function(technology, callback) {
        if (!isOk) {
            if (parseInt(MvcSkel.getVar('isAuth')) == 0) {
                var url = new UrlSeoConstructor('INDEX_OFFERS');
                url.addVar('gameId', MvcSkel.getVar('gameId'));
                log.stop('user not logged');
                window.location = url.construct();            
            } else {
                var url = new UrlSeoConstructor('PROFILE_GAMES');
                log.stop('isDrmReadyOnClientComputer failed');
                window.location = url.construct();            
            }
        } else {
            log.debug('isDrmReadyOnClientComputer success');
            if ([enumGameTechno.EXENT_TECHNO, enumGameTechno.YUMMY_TECHNO].include(technology)) {
                if (isTheGoodVersionInstalledMultiTechno(DEFINE.get('PLAYER_EXENT_VERSION'), DEFINE.get('PLAYER_YUMMY_VERSION'))) {
                    ww.show(function() {
                        log.debug('wait window is appear. call callback');
                        callback();
                    });
                } else {
                    var url = new UrlSeoConstructor('PROFILE_GAMES');
                    log.stop('Update player required');
                    window.location = url.construct();            
                }                
            } else {
                ww.show(function() {
                    log.debug('wait window is appear. call callback');
                    callback();
                });
            }
        }
    },
    initAutorun: function() {
        var autorun = $('speedLaunch');
        if (!autorun) return;
        log.debug('try autorun game. params: ' + autorun.value);
        var res = autorun.value.match(/(\d+)_(.+)_(\d+)_(.+)/);
        var technoId = res[1];
        var technology = res[2];
        var commandLine = res[3];
        var action = res[4];
        if (action == 'browser') {
            this.launchBrowserGame(technoId, technology);
        } else if (action == 'launch') {
            this.launch(technoId, technology, commandLine);
        } else {
            this.addToDownloadList(technoId, technology, commandLine, '');
        }
    },
    myact1: function() {
        myGames.moveGameToCompletedCB(441050);
    },
    myact2: function() {
        myGames.moveFromDownloadedToNotInDownload(278854);
    },
    myact3: function() {
        myGames.addToListCB(448054);
    }
});

ButtonLoading = Class.create({
    initialize: function() {
        this.s = $('waitInit');
        if (!this.s) return; 
        this.eff = this.s.down('span');
        this.perExecuter = null;
        this.counter = 1;
        this.initLoading();
    },
    initLoading: function() {
        new PeriodicalExecuter(function(pe) {
            this.perExecuter = pe;
            this.eff.update('.'.times(this.counter++));
            if (this.counter > 3) this.counter = 0;
        }.bind(this), 0.5);
    },
    hide: function() {
        if (this.perExecuter) this.perExecuter.stop();
        if (this.s) this.s.hide();
    }
});

GamePage = Class.create({
    initialize: function() {
        try {
            this.gameId = $('gameId').getValue();
        } catch(e) {
            return false;
        }
        this.initFavorites('addGame');
        this.initFavorites('listGame');
        this.initAddRemoveFavorites();
    },
    initFavorites: function(elId) {
        if (!$(elId)) {
            return false;
        }
        Event.observe(elId, 'mouseover', function(event) {
            clearTimeout(this.ftimer);
            this.showFavoriteTip(elId);
        }.bind(this));
        Event.observe(elId, 'mouseout', function(event) {
            this.closeFavoriteTip(elId);
        }.bind(this));
    },
    showFavoriteTip: function(el) {
        if ($(el).down('div')) {
            $(el).down('div').setStyle({
                display: 'block'
            });
        }
    },
    closeFavoriteTip: function(el) {
        this.ftimer = setTimeout(function() {
            if ($(el).down('div')) {
                $(el).down('div').setStyle({
                    display: 'none'
                });
            }
        }, 1000);
    },
    initAddRemoveFavorites: function() {
        if (!$('addGame') || !$('listGame')) {
            return false;
        }
        Event.observe('addGame', 'click', function() {
            var url = new UrlConstructor('favorite/add');
            url.setAction(true);
            url.addVar('id', this.gameId);
            new Ajax.Request(url.construct(), {
                onSuccess: function(transport, json) {
                    this.toggleFavoritesIcon();
                }.bind(this)
            });
        }.bind(this));
        Event.observe('listGame', 'click', function() {
            var url = new UrlConstructor('favorite/remove');
            url.setAction(true);
            url.addVar('id', this.gameId);
            new Ajax.Request(url.construct(), {
                onSuccess: function(transport, json) {
                    this.toggleFavoritesIcon();
                }.bind(this)
            });
        }.bind(this));
    },
    toggleFavoritesIcon: function() {
        if ($('addGame').getStyle('display') == 'block') {
            $('addGame').setStyle({
                display: 'none'
            });
            $('listGame').setStyle({
                display: 'block'
            });
            if ($('bubbleGT')) {
                $('bubbl2').removeClassName('displayNone');
                $('bubbl1').addClassName('displayNone');
            }
        } else {
            $('addGame').setStyle({
                display: 'block'
            });
            $('listGame').setStyle({
                display: 'none'
            });
            if ($('bubbleGT')) {
                $('bubbl1').removeClassName('displayNone');
                $('bubbl2').addClassName('displayNone');
            }
        }
    }
});

if (typeof(browserGame) == 'undefined') {
    browserGame = false;
}

if (typeof(displayErrorMessage) == 'undefined') {
    function displayErrorMessage(errorCode) {
        log.debug('display error message. code: ' + errorCode);
        var err = new ModalErrorWindow(errorCode);
        err.open();
        if (gameManager) gameManager.actionClick = false;
    }
}

var enumGameState = {
    DOWNLOADING: 'DOWNLOADING',
    DOWNLOAD_STOP: 'DOWNLOAD_STOP',
    RUNNING: 'RUNNING'
};
var gameManager = null;
isOk = (typeof(isOk) == 'undefined') ? false : isOk;

Event.observe(window, 'load', function() {
    log.debug('Player(s) isOk: ' + (isOk ? 'true' : 'false'));
    gameManager = new GameManager();
    if (typeof(__meta) != 'undefined' && __meta) {
        gameManager.initFavorites();
        gameManager.initAutorun();
    }
});

