//
// Copyright (C) 2007 rPath, Inc
// All Rights Reserved
//

var SITE_BASE_URL =  '/rbuilder/';
var JSONRPC_INTERFACE = SITE_BASE_URL + 'jsonrpc/';

function fromDatabaseTimestamp(timestamp) {
    // Converts YYYYMMDDmmhhss to a Javascript Date object
    // using MochiKit.Date.
    var tStr = String(timestamp);
    var iso8601Str = tStr.slice(0,4)+"-"+tStr.slice(4,6)+"-"+
                     tStr.slice(6,8)+"T"+tStr.slice(8,10)+":"+
                     tStr.slice(10,12)+":"+tStr.slice(12,14)+"Z";
    return isoTimestamp(iso8601Str);
}

// ctor
function LaunchedAMI(launchedAMIId) {
    this.launchedAMIId = launchedAMIId;
    bindMethods(this);
    this.getLaunchedAMIData();
    this.updateStatus();
}

// attributes
LaunchedAMI.prototype.launchedAMIId = null;
LaunchedAMI.prototype.data = null;
LaunchedAMI.prototype.state = null;
LaunchedAMI.prototype.raaReady = false;
LaunchedAMI.prototype.dns_name = null;
LaunchedAMI.prototype.serverOffset = null;
LaunchedAMI.prototype.launchedAt = null;
LaunchedAMI.prototype.expiresAfter = null;

LaunchedAMI.prototype.updateTimeLeft = function() {

    var timeLeftId = $('timeLeft');
    var currentTimeWithOffset = new Date().getTime() + this.serverOffset;

    var timeLeftMS = this.expiresAfter.getTime() - currentTimeWithOffset;
    var timeLeftMinutes = Math.max(0, Math.ceil((timeLeftMS / 1000) / 60));
    var timeLeftString = "Tour has expired!";

    if (timeLeftMinutes > 0) {
        timeLeftString = "Tour has approximately " + timeLeftMinutes + " minute" + (timeLeftMinutes == 1 ? " " : "s ") + "remaining";
    }

    timeLeftId.innerHTML = timeLeftString;
    callLater(10, this.updateTimeLeft);

}

// status updater
LaunchedAMI.prototype.updateStatus = function() {

    // callback for launch status
    var callback = function(aReq) {

        var req = evalJSONRequest(aReq);
        this.state = req[0];
        this.dns_name = req[1];

        if (this.state == 'pending') {
            callLater(5, this.updateStatus);
        }
        else {
            this.checkRAA();
        }
        this.updatePageWithNewState();
    };

    var req = new JsonRpcRequest(JSONRPC_INTERFACE,
        "getLaunchedAMIInstanceStatus");
    req.setCallback(bind(callback, this));
    req.send(true, [ [], this.launchedAMIId]);

};

LaunchedAMI.prototype.updatePageWithNewState = function() {
    var state;

    if (this.raaReady) {
        state = 'ready';
        $('ec2address').innerHTML = this.dns_name;
        $('rapPassword').innerHTML = this.data['raaPassword'];

        this.launchedAt   = fromDatabaseTimestamp(this.data['launchedAt']);
        this.expiresAfter = fromDatabaseTimestamp(this.data['expiresAfter']);
        this.serverOffset = new Date().getTime() - this.launchedAt.getTime();
        setIpAddress(this.dns_name);
        showElement("div_success");
        // reset location of "bottom" div after sections displayed
        resetBottomDiv($(steps[current][DIVNAME]));
        this.updateTimeLeft();
    }
    else {
        state = this.state;
    }

    // resetting state of <li> elements
    var currentFound = false;
    var liEl = $('ec2LaunchStatusList');
    forEach (liEl.getElementsByTagName('li', 'ec2LaunchStatusList'), function (e) {
        if (e.id.indexOf(state) < 0) {
            if (!currentFound)  {
                setElementClass(e, 'completedState');
            }
        }
        else {
            currentFound = true;
            if (state == 'ready') {
                setElementClass(e, 'completedState');
            }
            else {
                setElementClass(e, 'currentState');
            }
        }
    });

};

LaunchedAMI.prototype.getLaunchedAMIData = function() {

    // callback for launch status
    var callback = function(aReq) {
        var req = evalJSONRequest(aReq);
        this.data = req;
    };

    var req = new JsonRpcRequest(JSONRPC_INTERFACE, "getLaunchedAMI");
    req.setCallback(bind(callback, this));
    req.send(false, [this.launchedAMIId]);

};

LaunchedAMI.prototype.checkRAA = function() {

    // callback for launch status
    var callback = function(aReq) {
        var req = evalJSONRequest(aReq);
        if (!req) {
            callLater(5, this.checkRAA);
            this.raaReady = false;
        }
        else {
            this.raaReady = true;
        }
        this.updatePageWithNewState();
    };

    var req = new JsonRpcRequest(JSONRPC_INTERFACE, "checkHTTPReturnCode");
    req.setCallback(bind(callback, this));
    req.send(true, ['http://'+this.dns_name+'/', [200,301,302]]);

};

LaunchedAMI.prototype.extendTour = function() {

    // callback for extend tour
    var callback = function(aReq) {
        var req = evalJSONRequest(aReq);
        logDebug("Tour extended!");
        this.getLaunchedAMIData()
        this.updatePageWithNewState();
    };

    var req = new JsonRpcRequest(JSONRPC_INTERFACE, "extendLaunchedAMITimeout");
    req.setCallback(bind(callback, this));
    req.send(true, [this.launchedAMIId]);
};

// ctor
function EC2Launcher(blessedAMIId) {
    this.blessedAMIId = blessedAMIId;
    connect("startButtonImage", "onclick", this, "launchAMI");
    bindMethods(this);
}

// attributes
EC2Launcher.prototype.blessedAMIId = null;
EC2Launcher.prototype.launchedAMI = null;

// functions
EC2Launcher.prototype.launchAMI = function(e) {

    // callback for launch request
    var callback = function(aReq) {
        req = evalJSONRequest(aReq);
        this.launchedAMI = new LaunchedAMI(req);
    };

    // errorback for launch request (e.g. if the backend ISEs... ugh)
    var errback = function () {
        hideElement('div_during_launch');
        showElement('div_timeout');
        setNodeAttribute('startButtonImage', 'src', getNodeAttribute('startButtonImage', 'src').replace(/_[hd]\./, "_n."));
        connect("startButtonImage", "onclick", this, "launchAMI");
        behavior_hover("startButtonImage");
        resetBottomDiv($(steps[current][DIVNAME]));
    };

    // request the backend to launch the AMI instance
    var req = new JsonRpcRequest(JSONRPC_INTERFACE,
        "launchAMIInstance");
    req.setCallback(bind(callback, this));
    req.setErrback(bind(errback, this));
    req.send(true, [ [], this.blessedAMIId]);

    // Update status button
    disconnectAll('startButtonImage');
    setNodeAttribute('startButtonImage', 'src', getNodeAttribute('startButtonImage', 'src').replace(/_[nh]\./, "_d."));
    showElement('div_during_launch');
    hideElement('div_timeout');
    hideElement('div_success');

    // reset location of "bottom" div after sections displayed
    resetBottomDiv($(steps[current][DIVNAME]));

};


