﻿WeembaNotificationsSubscription = function(options) {

    // variable initialization
    if (typeof this.subscribed == 'undefined') {
        this.subscribed = false;
        this.firsttimesubscription = true;
        this.subscriptions = new Array(0);
        this.errorCount = 0;
        this.cancel = false;
        this.savednotifications = new Array(0);
    }

    // options and defaults        
    var defaults = {
        autosubscribetime: 5000,
        url: null,
        timeout: 10000,
        errorsToGiveUp: 10,
        subscribing: function() { },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            console.error(textStatus + "\\n" + ((errorThrown != null) ? errorThrown : ''));
        },
        giveup: function(XMLHttpRequest, textStatus, errorThrown) { }
    };
    this.options = $.extend(defaults, options);

    // check subscription url
    if (this.options.url == null)
        throw new Exception("No URL specified.");

    // auto subscribe
    var instance = this;
    if (this.options.autosubscribetime == 0) {
        $().ready(function() {
            instance.Subscribe();
        });
    } else if (this.options.autosubscribetime > 0) {
        setTimeout(function() {
            instance.Subscribe();
        }, this.options.autosubscribetime);
    }

    // when navigating off cancel subscriptions
    $(window).bind("beforeunload", function() {
        instance.cancel = true;
    });

}

// Send request to the server
WeembaNotificationsSubscription.prototype.Subscribe = function() {

    // if cancel subscription
    // or already subscribed
    // or no subscriptions
    if (this.cancel || this.subscribed || this.subscriptions.length == 0)
        return;

    // check subscription url
    if (this.options.url == null)
        throw "No URL specified";

    // trigger subscribing event
    if (this.firsttimesubscription) {
        this.firsttimesubscription = false;
        this.options.subscribing();
    }

    this.subscribed = true;
    var instance = this;
    var error = '';

    $.ajax({
        type: "POST",
        dataType: "text",
        url: instance.options.url,
        success: function(msg) {
            instance.errorCount = 0;
            msg = msg.replace("{}", "");
            if (msg.length > 0) {
                var notifications = eval("(" + msg + ")");
                instance.savednotifications.push(notifications);
                instance.processNotifications(notifications);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            XMLHttpRequest.abort();
            instance.options.error(XMLHttpRequest, textStatus, errorThrown);
            instance.errorCount++;
            if (instance.errorCount >= instance.options.errorsToGiveUp)
                instance.options.giveup(XMLHttpRequest, textStatus, errorThrown);
            error = textStatus;
        },
        complete: function(XMLHttpRequest, textStatus) {
            instance.subscribed = false;
            if (instance.errorCount >= instance.options.errorsToGiveUp) return;
            if (error == '')
                instance.Subscribe(); // request again
            else {
                // wait a few seconds before subscribing again
                setTimeout(function() {
                    instance.Subscribe();
                }, 3000);
            }
        },
        timeout: instance.options.timeout,
        data: { sessionId: instance.options.sessionId, realtimeIDs: instance.getRealtimeIds() }
    });

}

// stop subscriptions
WeembaNotificationsSubscription.prototype.UnSubscribe = function() {
    this.cancel = true;
}

// function to get unique ids for subscription
WeembaNotificationsSubscription.prototype.getRealtimeIds = function() {
    var ids = new Array();
    $(this.subscriptions).each(function() {
        if (ids[this.id] == undefined);
        ids.push(this.id);
    });
    return ids.join(";");
}

// run callback functions of subscribed elements
WeembaNotificationsSubscription.prototype.processNotifications = function(notifications) {
    if (this.subscriptions.length == 0) return;
    var instance = this;
    var notif = notifications;
    $.each(instance.subscriptions, function(j, subscription) {
        if (subscription.id != '') {
            $.each(notif, function(i, notification) {
                if (subscription.id == notification.Id)
                    subscription.callback(notification.Data);
            });
        } else {
            subscription.callback(notif);
        }
    });
}

// subscribe to user notifications
WeembaNotificationsSubscription.prototype.addEventSubscription = function(callback, owner) {
    this.subscriptions.push({ id: '', callback: callback, owner: owner });
}

// subscribe to a project updates
WeembaNotificationsSubscription.prototype.addProjectSubscription = function(projectId, callback, owner) {
    this.subscriptions.push({ id: 'proj' + projectId, callback: callback, owner: owner });
}

// remove subscription
WeembaNotificationsSubscription.prototype.removeSubscription = function(owner) {
    var indexes = new Array(0);
    $.each(this.subscriptions, function(i, subscription) {
        if (subscription.owner == owner)
            indexes.push(i);
    });
    $.each(indexes, function(i, index) {
        this.subscriptions.splice(index, 1);
    });
}


