﻿var HostCommandMonitor = Class.create();

HostCommandMonitor.prototype = {
    initialize: function(commandId, events, requestUrl, retryOnFail) {
        this.CommandId = commandId;
        this.OnMonitor = events.onMonitor;
        this.OnComplete = events.onComplete;
        this.OnFailure = events.onFailure;
        this.RequestUrl = requestUrl || '/hostcommand/gethostcommand';
        this.MonitorCommand();
        this.FailureLimit = 3;
        this.FailureCount = 0;
        this.RetryOnFail = retryOnFail != undefined ? retryOnFail : true;        
    },

    MonitorCommand: function() {
        var _this = this;

        new Ajax.Request(this.RequestUrl, {
            method: 'post',
            parameters: {
                commandId: this.CommandId
            },
            onComplete: function(response) {
                try {
                    var result = response.responseText.evalJSON();
                } catch (err) {
                    _this.OnFailure();
                }

                switch (result.ResponseType) {
                    case "SUCCESS":
                        var command = result.Data;

                        if (_this.OnMonitor)
                            _this.OnMonitor(command);

                        if (command.IsRunning) {
                            setTimeout(function() { _this.MonitorCommand(); }, 2000);
                        } else {
                            _this.OnComplete(command);
                        }
                        break;
                    case "ERROR":
                        _this.OnFailure();
                        break;
                }
            },
            onFailure: function() {
                if (_this.RetryOnFail && _this.FailureCount != _this.FailureLimit) {
                    // Failure limit not reached increase count and retry.
                    _this.FailureCount++;
                    setTimeout(function() { _this.MonitorCommand(); }, 2000);
                } else {
                    // Failure limit reached exit.
                    _this.OnFailure();
                    _this.FailureCount = 0;
                }
            }
        });
    }
};

/*****************************/

var HostCommandForm = Class.create();

HostCommandForm.prototype = {
    initialize: function(formId, commandType, commandCreateURL, onValidate, onCommandSubmitted, onCommandComplete) {
        this.Id = formId;
        this.Form = document.forms[formId];
        this.ButtonId = this.Id + "_button";
        this.StatusLoaderId = this.Id + "_statusloader";
        this.StatusTextId = this.Id + "_statustext";

        this.CommandRunning = false;
        this.CommandCreateURL = commandCreateURL;
        this.CommandType = commandType;
        this.CommandId = '';

        this.OnValidate = onValidate;
        this.OnCommandSubmitted = onCommandSubmitted;
        this.OnCommandComplete = onCommandComplete;                
    },

    UpdateForm: function(running) {
        this.CommandRunning = running;
        this.ShowStatusLoader(running);
    },
    
    ShowStatusLoader: function(visible) {
        $(this.StatusLoaderId).style.display = visible ? "inline" : "none";
    },

    ClearCommandStatusText: function() {
        this.SetCommandStatusText('');
    },

    SetCommandStatusText: function(statusDescription) {
        $(this.StatusTextId).innerHTML = statusDescription;
    },

    Submit: function() {
        var _this = this;
        
        if (_this.CommandRunning) 
           return false;       
                   
        if(_this.OnValidate != null && !_this.OnValidate(_this.Form))
            return;
                        
        _this.UpdateForm(true);
        _this.ClearCommandStatusText();

        new Ajax.Request(_this.CommandCreateURL, {
            method: 'post',
            parameters: Form.serialize(_this.Form),
            onSuccess: function(response) {
                var result = response.responseText.evalJSON();

                switch(result.ResponseType) {
                    case "SUCCESS":
                            _this.CommandCreationSuccess(result.Data.CommandId);
                        break;
                    case "ERROR":
                        _this.CommandCreationFailed(result);                                           
                        break;                    
                }                
            },
            onFailure: function(response) {
                _this.HandleFailed();
            }
        });
    },

    CommandCreationSuccess: function(commandId) {
        if (this.OnCommandSubmitted != null)
            this.OnCommandSubmitted(commandId);
            
        this.CommandId = commandId;
        HostCommandsManager.UpdateHostCommandForms();        
        this.MonitorCommand();
    },
    
    CommandCreationFailed: function(result) {
        if (result.Data.Blocked) {
            this.UpdateForm(false);
            this.ClearCommandStatusText();
            alert("A currently active " + result.Data.BlockedBy + " is blocking you from being able to perform this action.");
        } else {
            this.HandleFailed();
        }
    },
    
    MonitorCommand: function() {
        var _this = this;

        _this.UpdateForm(true);
        _this.ClearCommandStatusText();

        new HostCommandMonitor(_this.CommandId, {
            onMonitor: function(command) {
                _this.SetCommandStatusText(command.CurrentStepText);
            },
            onComplete: function(command) {
                HostCommandsManager.UpdateHostCommandForms();
                _this.UpdateForm(false);
                
                if (command.Succeeded) {                
                    _this.CommandComplete(command);
                    
                    if(_this.OnCommandComplete != null)
                        _this.OnCommandComplete(_this.Form);                        
                } else {
                    _this.CommandFailed(command);
                }
            },
            onFailure: function() {
                _this.HandleFailed();
            }
        });
    },   

    CommandComplete: function(command) {        
        this.SetCommandStatusText("<span class='Yes'><img src='/res/images/icons/tick.png' alt='' />Complete</span>");        
    },

    CommandFailed: function(command) {
        this.SetCommandStatusText("<span class='No'><img src='/res/images/icons/cross.png' alt='' />Failed</span>");
    },
    
    HandleFailed: function() {
        this.UpdateForm(false);
        this.SetCommandStatusText("<span class='No'><img src='/res/images/icons/cross.png' alt='' />Failed</span>");        
        HostCommandsManager.UpdateHostCommandForms(); 
    }
};

/*****************************/

var PingHostCommandForm = Class.create();

PingHostCommandForm.prototype = Object.extend(new HostCommandForm(), {
    retries: 0,
    CommandComplete: function(command) {
        this.SetCommandStatusText("<span class='Yes'><img src='/res/images/icons/tick.png' alt='' />Yes</span>");
    },
    CommandFailed: function(command) {
        this.SetCommandStatusText("<span class='No'><img src='/res/images/icons/cross.png' alt='' />No</span>");
        
        if(this.retries++ == 2) { return; } // IF ping fails 3 times stop.        
        
        var _this = this;
        setTimeout(function() { _this.Submit(); }, 5000);
    }   
});

/*****************************/

var UptimeHostCommandForm = Class.create();

UptimeHostCommandForm.prototype = Object.extend(new PingHostCommandForm(), {
    CommandComplete: function(command) {
        this.SetCommandStatusText("<span class='Yes'><img src='/res/images/icons/tick.png' alt='' />Yes</span> up for " + command.ResultData + "</span>");
    }    
});

/*****************************/

var IsGuestRuningHostCommandForm = Class.create();

IsGuestRuningHostCommandForm.prototype = Object.extend(new PingHostCommandForm());

/*****************************/

var ResetGuestPasswordCommandForm = Class.create();

ResetGuestPasswordCommandForm.prototype = Object.extend(new HostCommandForm(), {    
    CommandComplete: function(command) {
        this.SetCommandStatusText("<span class='Yes'><img src='/res/images/icons/tick.png' alt='' />Complete, your new password is </span> <b>" + command.ResultData + "</b>");
    } 
});

/*****************************/

var HostCommandsManager = {
    guestDomainId: '',
    forms: new Hash(),

    Initialize: function(guestDomainId) {
        this.guestDomainId = guestDomainId;
    },

    RegisterForm: function(formId, hostCommandForm) {
        this.forms[formId] = hostCommandForm;
    },

    Submit: function(formId) {
        var form = this.forms[formId];

        form.Submit();
    },

    UpdateHostCommandForms: function() {
        var _this = this;
        
        new Ajax.Request('/hostcommand/updatehostcommandforms', {
            method: 'post',
            parameters: {
                guestDomainId: _this.guestDomainId,
                formsData: _this.forms.toJSON()
            },
            onComplete: function(response) {
                var results = $H(response.responseText.evalJSON());

                results.each(function(pair) {
                    var form = _this.forms[pair.key];
                    
                    if (pair.value.CommandExists && !form.CommandRunning) {
                        form.CommandId = pair.value.CommandId;
                        form.MonitorCommand();                        
                    }
                });
            }
        });
    }

};

/*****************************/

var HostCommandStatusPage = Class.create();

HostCommandStatusPage.prototype = {
    initialize: function(commandId, returnUrl, errorUrl, title, openVncStep) {
        this.CommandId = commandId;
        this.ReturnUrl = returnUrl;
        this.ErrorUrl = errorUrl;
        this.Title = title;
        this.OpenVncStep = openVncStep;

        this.SetHostCommandProceedUrl = '/hostcommand/sethostcommandproceed';

        // Add handler to stop navigation away from page accidently.
        window.onbeforeunload = function confirmExit() {
            return "Are you sure you would like to leave the command status page, if you leave the page you will not be able to view the status of your command.";
        };

        this.MonitorCommand();
    },

    MonitorCommand: function() {
        var _this = this;
        _this.VncLoaded = false;
        _this.InputShown = false;
        $("StatusHeading").innerHTML = _this.Title;

        new HostCommandMonitor(_this.CommandId, {
            onMonitor: function(command) {
                _this.SetProgress(command);
                _this.ShowTechnicalDetails(command);

                if (command.InputRequired && !_this.InputShown) {
                    _this.InputShown = true;
                    _this.ShowInputRequired(command);
                }

                if (!_this.VncLoaded && command.CompletedSteps.length >= _this.OpenVncStep && command.GuestBooting) {
                    _this.ShowVncWindow(command);
                    _this.VncLoaded = true;
                }
            },
            onComplete: function(command) {

                // Replace the onbeforeunload function so that the page cannot be navigated away from.
                window.onbeforeunload = null;

                if (command.Succeeded) {
                    setTimeout(function() {
                        window.location = _this.ReturnUrl;
                    }, 3000);
                } else {
                    window.location = _this.ErrorUrl;
                }
            },
            onFailure: function() {
                window.onbeforeunload = null;
                window.location = _this.ErrorUrl;
            }
        });
    },

    SetProgress: function(command) {
        var progress = command.ProgressComplete;
        var progressLevel = $("ProgressLevel");

        if (command.ShowResultData) {
            var result = $("ResultData");
            result.show();

            if (command.ResultData != null) {
                result.innerHTML = command.ResultData;
            }
        }

        new Effect.Morph(progressLevel, { style: { width: (progress < 0) ? 0 : progress + "%"} });
    },

    ShowTechnicalDetails: function(command) {
        var technicalDetails = $("TechnicalDetails");

        technicalDetails.innerHTML = "";

        for (var i = 0; i < command.CompletedSteps.length; i++) {
            var completedStep = command.CompletedSteps[i];
            technicalDetails.innerHTML += "<div class='TechnicalDetail'>" + completedStep + "... <span class='Done'>Done</span></div>";
        }

        var currentStep = command.CurrentStepText;

        if (currentStep != '')
            technicalDetails.innerHTML += "<div class='TechnicalDetail'>" + currentStep + "...</div>";
    },

    ShowVncWindow: function(command) {
        var vncWindow = $("VncWindow");
        vncWindow.style.display = "block";
        var innHtml = '<applet code="VncViewer.class" archive="/res/java/VncViewer.jar" width="800" height="624">'
				    + '<param name="PORT" value="' + command.RescuePort + '" />'
				    + '<param name="HOST" value="' + command.RescueServer + '" />'
				    + '<param name="PASSWORD" value="' + command.RescuePassword + '" />'
				    + '<param name="Open New Window" value="no" />'
				    + '<param name="trustAllVncCerts" value="yes" />'
				    + '<param name="View only" value="yes" />'
				    + '</applet>';
        vncWindow.innerHTML = innHtml;
        window.onbeforeunload = null;
    },

    ShowInputRequired: function(command) {
        var message = '<p>'
                        + 'Your VPS should have finished setup but has not responded to ping. What would you like to do?'
                        + '</p>'
                        + '<div class="Buttons">'
                        + '<input type="image" src="/generatedimage/index?title=Continue&type=button" OnClick="ProceedWithProcess(\'true\');" />'
                        + '&nbsp;'
                        + '<input type="image" src="/generatedimage/index?title=Cancel&type=button" OnClick="ProceedWithProcess(\'false\');" />'
                        + '</div>';

        ShowErrorMessage(message, "Warning");
    },

    ProceedWithProcess: function(proceedTask) {

        var _this = this;

        if (proceedTask == 'true') {
            ShowErrorMessage("Proceeding...", "Success");
        }
        else {
            ShowErrorMessage("Cancelling...", "Failure");
        }

        new Ajax.Request(_this.SetHostCommandProceedUrl, {
            method: 'post',
            parameters: {
                commandId: this.CommandId,
                proceed: proceedTask
            },
            onComplete: function(response) {

            },
            onFailure: function() {
                window.onbeforeunload = null;
                window.location = _this.ErrorUrl;
            }
        });
    }
};
