function UploadTracker (formele, cb, uploadID) {
    this.form       =   formele;
    this.callback   =   cb;
    this.session    =   UploadTracker._generateSession();
    this.stopped    =   false;
    this.uploadID   =   uploadID;
    
    var action = this.form.action;
    if (action.match(/\bclient_up_sess=(\w+)/)) {
        action = action.replace(/\bclient_up_sess=(\w+)/, "client_up_sess=" + this.session);
    } else {
        action += (action.match(/\?/) ? "&" : "?");
        action += "client_up_sess=" + this.session;
    }
    this.form.action = action;
    
    this._startCheckStatus();
}

UploadTracker.prototype.stopTracking = function () {
    this.stopped = true;
};

UploadTracker._generateSession = function () {
    var str = Math.random() + "";
    return curSession = str.replace(/[^\d]/, "");
};

UploadTracker.prototype._startCheckStatus = function () {
    var uptrack = this;
    if (uptrack.stopped) return true;
    
    var url = '/__upload_status';
    var params = "client_up_sess=" + uptrack.session + "&rand=" + Math.random();
    
    var ajaxReq = new Ajax.Request(url, {
        method: 'get',
        parameters: params,
        onComplete: function(response)  {
            if(response && response.responseText) {
                var retVal = response.responseText.evalJSON();
                if (retVal) {
                    // Calculate the transfer rate and remaining time
                    if (uptrack.lastdone != undefined && uptrack.lasttime != undefined){
                        var transferRate = (retVal.done - uptrack.lastdone) / (retVal.nowtime - uptrack.lasttime);
                        var timeRemaining = (retVal.total - retVal.done) / transferRate;
                    } else {
                        var transferRate = 0;
                        var timeRemaining = 0;
                    }
                    uptrack.lastdone = retVal.done;
                    uptrack.lasttime = retVal.nowtime;
                    retVal.transferrate = transferRate;
                    retVal.timeremaining = timeRemaining;
                    
                    // Call callback, set new timeout
                    uptrack.callback(retVal, uptrack.uploadID);
                }
            }
            setTimeout(uptrack._startCheckStatus.bind(uptrack), 1000);
        }
    });
};
