define([
  // Application.
  "app",
],

function (app) {

    var SecurityManager = { Models: {}, Collections: {}, };

    SecurityManager.init = function (ctx, module, app) {
        app.models.securityManager = new module.Model();
        app.models.securityManager.start();
    }; 

    SecurityManager.Models.Action = Backbone.Model.extend({
        defaults: {
            id: null,
            code: null, 
            name: null,
            value: null,
        },
    });

    SecurityManager.Collections.Actions = Backbone.Collection.extend({
        model: SecurityManager.Models.Action, 
    }); 

    SecurityManager.Models.Module = Backbone.Model.extend({
        defaults: {
            id: null,
            code: null, 
            name: null,
            value: null,
            actions: null, 
        },
        initialize: function () {
            this.attributes.actions = new SecurityManager.Collections.Actions(); 
        }, 
    });

    SecurityManager.Collections.Modules = Backbone.Collection.extend({
        model: SecurityManager.Models.Module,
        fetch: function (opt) {
            var options = {
                method: "set",
                async: true,
                callback: null,
            };

            options = _.extend(options, (opt) ? opt : {});

            var that = this,
                QP = new Core.Database.QueryParameters();

            Core.Json.CallProcedure(app.DatabaseNames.System + ".FrontEnd.GetUserSecurityModulesActions", QP, {
                onSuccess: function (response) {
                    if (response && response.Table) {
                        var records = response.Table;
                        var actions = response.Table1; 

                        var mdls = [];
                        var actionsMdls = {};

                        for (var i = 0, len = records.length; i < len; i++) {
                            var data = records[i];
                            var obj = _.clone(SecurityManager.Models.Module.prototype.defaults);

                            var obj = {
                                id: data.ModuleId, 
                                code: data.Code, 
                                name: data.Name, 
                                value: data.Value, 
                            }; 

                            mdls.push(obj);
                        }

                        for (var i = 0, len = actions.length; i < len; i++) {
                            var data = actions[i];

                            var obj = {
                                id: data.ActionId,
                                code: data.Code, 
                                name: data.Name,
                                value: data.Value,
                            };

                            if (!actionsMdls[data.ModuleId]) actionsMdls[data.ModuleId] = [];
                            actionsMdls[data.ModuleId].push(obj); 
                        }

                        that[options.method](mdls);
                        that.each(function (t) {
                            var acs = actionsMdls[t.get("id")];
                            t.get("actions").set(acs); 
                        }); 

                        if (options.callback != null && _.isFunction(options.callback))
                            options.callback.call(this, that);
                    }
                },
                Async: options.async,
                CachePerUser: true, 
            }, app.ConnectionStrings.app);

            return this;
        }
    });

    SecurityManager.Model = Backbone.Model.extend({
        defaults: {
            modules: null, 
        },
        toid: null,
        delay: 1000 * 5,
        refreshing: false,
        initialize: function ()
        {
            this.attributes.modules = new SecurityManager.Collections.Modules(); 

            _.bindAll(this);
            this.bindEvents(); 
        },
        bindEvents: function () {
            //this.listenTo(this.get("modules"), "change", function (a, b, c) {
            //    a; 
            //}); 
        }, 
        fetch: function (opt)
        {
            try
            {
                clearTimeout(this.toid);
                
                this.get('modules').fetch(opt);
            }
            catch (Error) { console.error(Error); }
            finally
            {
                if (this.refreshing)
                    this.toid = setTimeout(this.fetch, this.delay);
            }
        },
        start: function ()
        {
            if (!this.refreshing)
            {
                this.refreshing = true;

                this.fetch({ method: "reset", async: false });
            }

            return this;
        },
        stop: function ()
        {
            clearTimeout(this.toid);

            this.refreshing = false;

            return this;
        },
        getModule: function (code) {
            try {
                var modules = this.get("modules").filter(function (t) {
                    return t.get("code").toUpperCase() == code.toUpperCase();
                });

                return modules.length > 0 ? modules[0] : null; 
            } catch (error) {
                return null; 
            }
        },
        getModuleAction: function (module, actionCode) {
            try{
                var module = (_.isString(module)) ? this.getModule(module) : module;
                if (module) {
                    var actions = module.get("actions").filter(function (t) {
                        return t.get("code").toUpperCase() == actionCode.toUpperCase();
                    });

                    return actions.length > 0 ? actions[0] : null; 
                }
            } catch (error) {
                console.log(error); 
            }

            return null; 
        }, 
        getModuleActionValue: function (moduleCode, actionCode) {
            /// <param name="moduleCode" type="String">module code</param>
            /// <param name="actionCode" type="String">action code</param>
            /// <returns type="Boolean" />
            try {
                var module = this.getModule(moduleCode);
                if (module && module.get("value") == true) {
                    var action = this.getModuleAction(module, actionCode);

                    return (action) ? action.get("value") : false; 
                }
            } catch (error) {
                console.log(error); 
            }

            return false; 
        }, 
    });

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

});
