﻿Type.registerNamespace('Roblox.Launch');

Roblox.Launch._LaunchGamePage = null;

Roblox.Launch.RequestGame = function(behaviorID, placeID) {
    Roblox.PlaceLauncher.Service.LogJoinClick();
    if (checkRobloxInstall()) {
        var launcher = new RBX.PlaceLauncher($find(behaviorID));
        launcher.RequestGame(placeID);
    }
}
Roblox.Launch.RequestGroupBuildGame = function(behaviorID, placeID) {
    Roblox.PlaceLauncher.Service.LogJoinClick();
    if (checkRobloxInstall()) {
        var launcher = new RBX.PlaceLauncher($find(behaviorID));
        launcher.RequestGroupBuildGame(placeID);
    }
}

Roblox.Launch.RequestGameJob = function(behaviorID, gameJobID) {
    Roblox.PlaceLauncher.Service.LogJoinClick();
    if (checkRobloxInstall()) {
        var launcher = new RBX.PlaceLauncher($find(behaviorID));
        launcher.RequestGameJob(gameJobID);
    }
}

Roblox.Launch.RequestFollowUser = function(behaviorID, userId) {
    Roblox.PlaceLauncher.Service.LogJoinClick();
    if (checkRobloxInstall()) {
        var launcher = new RBX.PlaceLauncher($find(behaviorID));
        launcher.RequestFollowUser(userId);
    }
}

Roblox.Launch.StartGame = function(visitUrl, type, authenticationUrl, authenticationTicket) {
    urchinTracker("Visit/Try/" + type);

    var prefix = null;
    try {
        prefix = "RobloxProxy/";
        var launcher = Roblox.Client.CreateLauncher(false);
        if (!launcher) {
            if (window.external) {
                try {
                    window.external.StartGame(authenticationTicket, authenticationUrl, visitUrl);
                }
                catch (ex) {
                    throw "window.external fallback failed, Roblox must not be installed or IE cannot access ActiveX";
                }
            }
            else {
                throw "launcher is null or undefined and external is missing";
            }
        }
        else {
            //launcher is non-null
            prefix = "RobloxProxy/StartGame/";
            try {
                try {
                    launcher.AuthenticationTicket = authenticationTicket;
                }
                catch (err) {
                    // This is an older version of the Launcher. Ignore the error
                }
                launcher.StartGame(authenticationUrl, visitUrl);
            }
            catch (err) {
                Roblox.Client.ReleaseLauncher(launcher);
                throw err;
            }
            Roblox.Client.ReleaseLauncher(launcher);
        }
    }
    catch (err) {
        var message = err.message;

        if (message == "User cancelled") {
            urchinTracker("Visit/UserCancelled/" + type);
            return false;
        }

        try {
            var y = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (err3) {
            message = "FailedXMLHTTP/" + message;
        }

        if (!Roblox.Client.isRobloxBrowser()) {
            urchinTracker("Visit/Redirect/" + prefix + encodeURIComponent(message));
            window.location = Roblox.Launch._LaunchGamePage;
        }
        else
            urchinTracker("Visit/Fail/" + prefix + encodeURIComponent(message));

        return false;
    }

    urchinTracker("Visit/Success/" + type);
    return true;
}

Roblox.Launch.CheckRobloxInstall = function(installPath) {
    if (!Roblox.Client.IsRobloxInstalled())
        window.location = installPath;
    else {
        Roblox.Client.Update();
        return true;
    }
}

Type.registerNamespace('RBX');

RBX.PlaceLauncher = function(modalBehavior) {
    this._modalBehavior = modalBehavior;

    this._popup = $get(this._modalBehavior.get_PopupControlID());
    this._cancelButton = $get("Cancel", this._popup);
    this._cancelHandler = null;

    this._cancelled = false;
}

RBX.PlaceLauncher.prototype = {

    // TODO: This should only be called once.  What if you call it again???
    RequestGame: function(placeID) {

        this._showDialog();

        // Now send a request to the Grid...
        var onGameSuccess = function(result, context) { context._onGameStatus(result); };
        var onGameError = function(result, context) { context._onError(result); };
        var self = this;
        var gameDelegate = function() { Roblox.PlaceLauncher.Service.RequestGame(placeID, onGameSuccess, onGameError, self); };

        this.StartUpdatePolling(gameDelegate);

        return false;
    },

    // TODO: This should only be called once.  What if you call it again???
    RequestGroupBuildGame: function(placeID) {

        this._showDialog();

        // Now send a request to the Grid...
        var onGameSuccess = function(result, context) { context._onGameStatus(result, true); };
        var onGameError = function(result, context) { context._onError(result); };
        var self = this;
        var gameDelegate = function() { Roblox.PlaceLauncher.Service.RequestGroupBuildGame(placeID, onGameSuccess, onGameError, self); };

        this.StartUpdatePolling(gameDelegate);

        return false;
    },
    // TODO: This should only be called once.  What if you call it again???
    RequestFollowUser: function(userId) {

        this._showDialog();

        // Now send a request to the Grid...
        var onGameSuccess = function(result, context) { context._onGameStatus(result); };
        var onGameError = function(result, context) { context._onError(result); };
        var self = this;
        var gameDelegate = function() { Roblox.PlaceLauncher.Service.RequestFollowUser(userId, onGameSuccess, onGameError, self); };

        this.StartUpdatePolling(gameDelegate);

        return false;
    },

    // TODO: This should only be called once.  What if you call it again???
    RequestGameJob: function(gameJobID) {

        this._showDialog();

        // Now send a request to the Grid...
        var onGameSuccess = function(result, context) { context._onGameStatus(result); };
        var onGameError = function(result, context) { context._onError(result); };
        var self = this;
        var gameDelegate = function() { Roblox.PlaceLauncher.Service.RequestGameJob(gameJobID, onGameSuccess, onGameError, self); };

        this.StartUpdatePolling(gameDelegate);

        return false;
    },


    _onGameStatus: function(result) {
        if (this._cancelled)
            return;

        this._updateStatus(result.status);

        if (result.status == 2) {
            Roblox.Launch.StartGame(result.joinScriptUrl, "Join", result.authenticationUrl, result.authenticationTicket);
            this._modalBehavior.hide();
        }
        else if (result.status < 2 || result.status==6) {
            // Try again
            var onSuccess = function(result, context) { context._onGameStatus(result); };
            var onError = function(result, context) { context._onGameError(result); };
            var self = this;
            var call = function() { Roblox.PlaceLauncher.Service.CheckGameJobStatus(result.jobId, onSuccess, onError, self); };
            window.setTimeout(call, 2000);
        }
    },

    _updateStatus: function(status) {
        $get("Starting", this._popup).style.display = 'none';
        $get("Spinner", this._popup).style.display = (status < 3 || status == 7 || status == 8 || status == 6) ? 'block' : 'none';
        $get("Waiting", this._popup).style.display = status == 0 ? 'inline' : 'none';
        $get("Loading", this._popup).style.display = status == 1 ? 'inline' : 'none';
        $get("Joining", this._popup).style.display = status == 2 ? 'inline' : 'none';
        $get("Expired", this._popup).style.display = status == 3 ? 'inline' : 'none';
        $get("Error", this._popup).style.display = status == 4 ? 'inline' : 'none';
        $get("GameEnded", this._popup).style.display = status == 5 ? 'inline' : 'none';
        $get("GameFull", this._popup).style.display = status == 6 ? 'inline' : 'none';
        $get("Updating", this._popup).style.display = status == 7 ? 'inline' : 'none';
        $get("Updated", this._popup).style.display = status == 8 ? 'inline' : 'none';
    },

    _onGameError: function(result) {
        this._updateStatus(4);
    },

    StartUpdatePolling: function(joinGameDelegate) {
        try {
            var launcher = Roblox.Client.CreateLauncher(false);
            var result = launcher.IsUpToDate;

            if (result || result == undefined) {
                try {
                    launcher.PreStartGame();
                }
                catch (e)
                { }
                
                joinGameDelegate();
                return;
            }

            //Now we need to poll until it is finished
            var onSuccess = function(result, launcher, context) { context._onUpdateStatus(result, launcher, joinGameDelegate); };
            var onError = function(result, context) { context._onUpdateError(result); };
            var self = this;

            this.CheckUpdateStatus(onSuccess, onError, launcher, joinGameDelegate, self);
        }
        catch (e) {
            //alert("Missing IsUpToDate, falling back");
            Roblox.Client.ReleaseLauncher(launcher);
            //Something went wrong, fall back to the old method of Update + Join in parallel
            joinGameDelegate();
        }
    },

    CheckUpdateStatus: function(onSuccess, onError, launcher, joinGameDelegate, self) {
        try {
            var result = launcher.IsUpToDate;
            if (result || result == undefined) {
                onSuccess(8, launcher, self);
            }
            else {
                onSuccess(7, launcher, self);
            }
        }
        catch (e) {
            //We have the old DLL loaded, so just pretend it was succesful like in the olden days
            onSuccess(8, launcher, self);
        }
    },


    _onUpdateStatus: function(result, launcher, joinGameDelegate) {
        if (this._cancelled)
            return;

        this._updateStatus(result);

        if (result == 8) {
            Roblox.Client.ReleaseLauncher(launcher);
            joinGameDelegate();
        }
        else if (result == 7) {
            // Try again
            var onSuccess = function(result, launcher, context) { context._onUpdateStatus(result, launcher, joinGameDelegate); };
            var onError = function(result, context) { context._onUpdateError(result); };
            var self = this;
            var call = function() { self.CheckUpdateStatus(onSuccess, onError, launcher, joinGameDelegate, self); };
            window.setTimeout(call, 2000);
        }
        else {
            alert("Unknown status from CheckUpdateStatus");
        }
    },

    _onUpdateError: function(result) {
        this._updateStatus(2);
    },


    _onCancel: function(e) {
        this._cancelled = true;
        this._modalBehavior.hide();
        return false;
    },

    _showDialog: function() {
        // Listen for cancel
        this._cancelHandler = Function.createDelegate(this, this._onCancel);
        $addHandler(this._cancelButton, 'click', this._cancelHandler);

        this._modalBehavior.show();
    },

    dispose: function() {
        if (this._cancelHandler && _cancelButton) {
            $removeHandler(_cancelButton, 'click', this._cancelHandler);
            this._cancelHandler = null;
        }

        RBX.PlaceLauncher.callBaseMethod(this, 'dispose');
    }
}

RBX.PlaceLauncher.registerClass('RBX.PlaceLauncher', null, Sys.IDisposable);