/// <reference path="http://localhost/IndustrialDashboard/Scripts/IndustrialDashboard-debug.js" />
define([
  // Application.
  "app",

  "moment", 

  //templates-loader
  "js/templates-loader"

],

function (app, moment, T) {

    //replace all ServerAudit for the name of your view.
    var ServerAudit = { Models: {}, Views: {}, Collections: {} }

    ServerAudit.Models.QueuedAudit = Backbone.Model.extend({
        defaults: {
            guid: null, 
            message: "", 
            module: null,
            level: null,
            event: null,
            eventObject: null,
            timestamp: null,
            timezone: null,
            appendIP: false, 
            
            processing: false,
            sent: false, 
            stored: false,
        },
        initialize: function (options) {
            this.attributes.guid = (_.isString(options.guid)) ? options.guid : this.guid(); 
        }, 
        guid: function(){
            function s4() {
                return Math.floor((1 + Math.random()) * 0x10000)
                    .toString(16)
                    .substring(1);
            }
            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
                s4() + '-' + s4() + s4() + s4();
        }, 
        save: function (success, error) {
            var that = this; 
            try {
                that.set("processing", true);

                $.ajax({
                    url: app.foldersRoot + "/app/api/server-audit.aspx",
                    type: 'POST',
                    data: {
                        action: "AUDIT", 
                        message: that.get("message"), 
                        module: that.get("module"), 
                        level: that.get("level"), 
                        event: that.get("event"), 
                        eventObject: that.get("event_obj"), 
                        timestamp: this.get("timestamp"), 
                        timezone: this.get("timezone"),
                        appendIP: this.get("appendIP"), 
                    },
                })
                .done(function (resp) {
                    that.set("processing", false);

                    success.call(that, resp.Success);
                })
                .fail(function (resp) {
                    that.set("processing", false);

                    error.call(that);
                });
            } catch (error) {
                console.log("Error while trying to save audit with timestamp [" + this.get("timestamp").toString() + "] to DB."); 
            }
        },
        store: function () {
            localStorage.setItem(("serveraudit-{0}").replace("{0}", this.get("guid")), JSON.stringify(this.toJSON()));
        },
        unstore: function () {
            localStorage.removeItem(("serveraudit-{0}").replace("{0}", this.get("guid"))); 
        },
        setCookie: function (name, value, days) {
            var expires;
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                expires = "; expires=" + date.toGMTString();
            }
            else {
                expires = "";
            }
            document.cookie = name + "=" + value + expires + "; path=/";
        },
        getCookie: function (c_name) {
            var default_value = "";
            var i, x, y, ARRcookies = document.cookie.split(";");
            for (i = 0; i < ARRcookies.length; i++) {
                x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
                y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
                x = x.replace(/^\s+|\s+$/g, "");
                if (x == c_name) {
                    return unescape(y);
                }
            }

            return default_value;
        },
    });

    ServerAudit.Collections.AuditQueue = Backbone.Collection.extend({
        model: ServerAudit.Models.QueuedAudit,
        initialize: function () {
            this.options = {
                isSyncing: false,
                retry: false,
                retryTOUT: null,

                autosync: {
                    enabled: true,
                    tout: null,
                    delay: 1000, 
                }, 
            };

            _.bindAll(this); 

            this.bindEvents();

            this.fetch(); 

            this.sync(); 
        },
        fetch: function () {
            var that = this; 
            var storaged = [];
            var k=0;

            for (var i in localStorage) {
                if (i.indexOf("serveraudit-") != -1) {

                    storaged.push(localStorage.getItem(i));
                    if (k>5) break; // js reduced because they were accumulating when the server has an error
                    k++;
                } 
            }
            
            _.each(storaged, function (item) {
                var itemObj = JSON.parse(item); 
                that.add(new ServerAudit.Models.QueuedAudit(itemObj), { silent: true });
            }); 
            
        },
        sync: _.debounce(function () {
            var that = this;

            if (this.options.autosync.tout != null) {
                clearTimeout(this.options.autosync.tout);
                this.options.autosync.tout = null; 
            }

            if (this.options.isSyncing) { setTimeout(this.sync, 500); return; }
            else {
                this.options.isSyncing = true;
            }

            //if not syncing.
            var items = this.where({ processing: false, sent: false });

            var afterSave = function () {
                try {
                    var sent = that.where({ sent: true });
                    that.remove(sent);
                } catch (error) {

                }


                that.options.isSyncing = false;

                if (that.options.autosync.enabled == true) {
                    that.options.autosync.tout = setTimeout(that.sync, that.options.autosync.delay);
                }
            }

            if (items.length > 0) {
                var ended = _.after(items.length, afterSave);

                _.each(items, function (t) {
                    try {
                        t.save(function (status) {
                            if (status) {
                                t.set("sent", true);
                                t.store(); 
                            }
                            ended.call(that);
                        }, ended);
                    } catch (error) {
                        console.log("Error while trying to sync item. Exception: " + error.toString() + " .");
                    }
                });
            } else {
                afterSave(); 
            }
        }, 600),
        bindEvents: function () {
            this.listenTo(this, 'add', this.fireAdd);
            this.listenTo(this, 'remove', this.fireRemove);
            this.listenTo(this, 'change', this.fireChange);
            this.listenTo(this, 'reset', this.fireReset);
        },
        fireAdd: function (item) {
            item.store(); 
            this.sync(); 
        },
        fireRemove: function (item) {
            item.unstore(); 
        },
        fireChange: function () {
        },
        fireReset: function () {
        },
        getCookie: function (c_name) {
            var default_value = "";
            var i, x, y, ARRcookies = document.cookie.split(";");
            for (i = 0; i < ARRcookies.length; i++) {
                x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
                y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
                x = x.replace(/^\s+|\s+$/g, "");
                if (x == c_name) {
                    return unescape(y);
                }
            }

            return default_value;
        }, 
    });

    ServerAudit.Models.Main = Backbone.Model.extend({
        defaults: {
            queue: null, 
        },
        initialize: function () {
            this.attributes.queue = new ServerAudit.Collections.AuditQueue(); 
        },
        add: function (message, module, level, event, eventObject, timestamp, timezone, appendIP) {
            try {
                var item = null; 
                if (!_.isString(message) && _.isObject(message) && message.save != null && message.save != undefined) {
                    item = message; 
                }

                if (!item) {
                    item = new ServerAudit.Models.QueuedAudit({
                        message: message,
                        module: module,
                        level: level,
                        event: event,
                        eventObject: eventObject,
                        timestamp: timestamp,
                        timezone: timezone,
                        appendIP: appendIP, 
                    }); 
                }

                this.get("queue").add(item); 
            } catch (error) { }
        }
    }); 

    // Required, return the module for AMD compliance.
    return ServerAudit;

});
