//SCREEN-BOILERPLATE
//this boilerplate builds screens that are gonna be shown in the <div class='content'> tag of our main HTML.
//do not build app components with this boilerplate, only screens (reports)

define([
  // Application variable, always include it to have access to app methods.
  'app',

  //templates-loader: this loads templates async.
    'js/templates-loader',

    
    'backgrid',
    'modules/modal2',
    'chart',
    'moment',
    'chartjs-date-fns-adapter',
    'modules/navigation-buttons/navigation-buttons',
    'backgrid/moment-cell',
    'backgrid/grouped-columns',
    'js/multiselect/virtual-select.min',

],
    function (app, T, Backgrid, Modal, ChartJS, moment, ChartJsDateFnsAdapter, NavigationButton) {

    var Screen = { Models: {}, Views: {}, Collections: {} }

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            profileSelected: null,
            areaSelected: null,
            screenSelected: null,

        },
        initialize: function () {
            this.profilesByScreenColl = new Screen.Collections.ItemsColl();
            this.parentsScreensColl = new Screen.Collections.ItemsColl();
            this.profilesColl = new Screen.Collections.ItemsColl();
            this.modulesActionsColl = new Screen.Collections.ItemsColl();
            this.updatedProfilesColl = new Screen.Collections.ItemsColl();
        },


        fetch: function (params) {
            var that = this;
            var qp = new Core.Database.QueryParameters();

            Core.Json.CallProcedure(
                app.DatabaseNames.System + '.SECURITY.GetProfilesByScreen',
                qp,
                {
                    onSuccess: function (resp) {
                        try {

                            if (resp && resp.Table) {           
                                that.profilesColl.setDataColl(resp.Table);
                                that.profilesByScreenColl.setDataColl(resp.Table1);
                                that.parentsScreensColl.setDataColl(resp.Table2);
                                that.modulesActionsColl.setDataColl(resp.Table3);
                            }
                            else {
                                if ((resp) && (resp.Message)) {
                                    app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                    console.error(resp.Message);
                                    that.set({
                                        hasData: false,
                                        isLoading: false,                                       

                                    });

                                }
                                else {
                                    app.views.topMessages.showMessage("Server response not valid.", { stay: 5000, });
                                    console.error("Server response not valid.");
                                    that.set({
                                        hasData: false,
                                        isLoading: false,                                       
                                    });
                                }

                            }


                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return this;

        },
        getIdentityRoles: function (params) {
            var that = this;
            var identityRoles = [];
            var qp = new Core.Database.QueryParameters();
            

            qp.Add("id", "INT", params.identityId); 
            Core.Json.CallProcedure(
                app.DatabaseNames.System + '.SECURITY.GetIdentityModulesActions',
                qp,
                {
                    onSuccess: function (resp) {
                        try {

                            if (resp.Table1) {
                               identityRoles = resp.Table1
                            }
                            else {
                                if ((resp) && (resp.Message)) {
                                    app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                    console.error(resp.Message);
                                    that.set({
                                        hasData: false,
                                        isLoading: false,

                                    });

                                }
                                else {
                                    app.views.topMessages.showMessage("Server response not valid.", { stay: 5000, });
                                    console.error("Server response not valid.");
                                    that.set({
                                        hasData: false,
                                        isLoading: false,
                                    });
                                }

                            }


                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    Async: false,
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return identityRoles;

        },

        updateRoleScreenIdentity: function (params) {
            var that = this;
            var qp = new Core.Database.QueryParameters();

            this.fixedParameters = [
                { Name: '@IdentityId', Type: 'INT', Value: params.identityId, },
                { Name: '@ActionId', Type: 'INT', Value: params.actionId, },
                { Name: '@ModuleId', Type: 'INT', Value: params.moduleId, },
                { Name: '@ProfileId', Type: 'INT', Value: params.profileId, },
                { Name: '@CleanActions', Type: 'BIT', Value: params.cleanActions, },
            ];
            _.each(this.fixedParameters, function (qpParams) {
                qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
            });

            Core.Json.CallProcedure(
                app.DatabaseNames.System + '.SECURITY.UpdateRoleScreenIdentity',
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if (resp.Table) {
                                that.updatedProfilesColl.setDataColl(resp.Table);
                                that.trigger('build-sidebar');
                                that.trigger('role-changed');
                                
                            }
                            else {
                                if ((resp) && (resp.Message)) {

                                    console.error(new Error(resp.Message).stack);
                                    app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                    that.trigger('role-changed')
                                }
                                else {
                                    console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    app.views.topMessages.showMessage('SERVER_RESPONSE_NOT_VALID', { stay: 5000, });
                                }

                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);
                    },
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return this;

        },
    });

        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'profiles-permissions',
            id: 'profiles-permissions',
            title: 'Profiles Permissions',
            isCacheable: false,
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                   // 'click #closeButton': this.closeSideBar_click,
                };
            },
            bindings: 'data-bind',
            subviews: null,
            viewParams: null,
            autoRefresh: null,
            pauseTimer: false,

            initialize: function () {
                this.options.state = app.view_states.loading;
                this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

                var that = this;
                this.model = new Screen.Models.Main();

                this.autoRefresh = {
                    enabled: null
                    , toid: null
                    , every: 5 * 1000
                };

                this.bindEvents();

            },
            bindEvents: function () {
                this.listenTo(this.model, 'change:profileSelected', this.profileSelectedChanged);
                this.listenTo(this.model, 'change:screenSelected', this.screenSelectedChanged);
                this.listenTo(this.model, 'change:areaSelected', this.areaSelectedChanged);
                this.listenTo(this.model, 'build-info-modal', this.buildInfoModal);
                this.listenTo(this.model, 'role-changed', this.buildRoleGrid);
                this.listenTo(this.model, 'build-sidebar', this.buildSideBar);
            },

            profileSelectedChanged: function () {
                var that = this;
                that.model.set('areaSelected', null);
                that.model.set('screenSelected', null);
                document.getElementsByClassName("screens-grid-container")[0].innerHTML = ''
                document.getElementsByClassName("role-grid-container")[0].innerHTML = ''
            },

            areaSelectedChanged: function () {
                var that = this;
                if (that.model.get('areaSelected') == null) {
                    document.getElementsByClassName("parents-screen-grid-container")[0].innerHTML = ''
                }
                that.model.set('screenSelected', null);
            },
            screenSelectedChanged: function () {
                var that = this;

                if (that.model.get('screenSelected') == null) {
                    this.$el.find('screens-grid-container').html('');
                    document.getElementsByClassName("screens-grid-container")[0].innerHTML = ''
                }
                document.getElementsByClassName("role-grid-container")[0].innerHTML = ''
            },
            render: function (container, urlParams) {
                var that = this;
                var thatContainer = (this.options.container) ? this.options.container : container;
                this.options.container = thatContainer;

                var customPath = '/app/custom-screens/' + this.template + '/';

                T.render.call(
                    this,
                    this.template,
                    function (tmp) {
                        if (!that.options.i18n) that.options.i18n = {};

                        app.getI18NJed(
                            that,
                            that.template,
                            function (i18nJED) {
                                that.options.i18n[that.template] = i18nJED;
                                that.$el.html(tmp());


                                var profilesGrid = new Backgrid.Grid({
                                    className: 'backgrid table table-hover table-condensed',
                                    columns: [

                                        {
                                            name: 'Name',
                                            editable: false,
                                            label: 'Profiles',
                                            sortable: true,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell ',
                                                events: {
                                                    "click": "onClick"
                                                },
                                                onClick: function () {
                                                    that.model.set('profileSelected', this.model);
                                                    profilesGrid.$el.find('td').removeClass('highlight-profile');

                                                    $(this.el).addClass('highlight-profile');
                                                    that.buildParentScreenGrid();
                                                },
                                            }),
                                        },


                                    ],
                                    collection: that.model.profilesColl,
                                });
                                that.$el.find('.profiles-grid-container').append(profilesGrid.render().el);

                                

                                that.applyBindings();

                                //appending view to the main container
                                that.append(thatContainer, that.$el);

                                that.refresh();

                               // that.startAutoRefresh();

                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            buildParentScreenGrid: function () {
                var that = this;

                var parentsScreenGrid = new Backgrid.Grid({
                    className: 'backgrid table table-hover table-condensed',
                    columns: [

                        {
                            name: 'ParentName',
                            editable: false,
                            label: 'Area',
                            cell: Backgrid.StringCell.extend({
                                className: 'string-cell align-center-cell ',
                                events: {
                                    "click": "onClick"
                                },
                                onClick: function () {
                                    that.model.set('areaSelected', this.model);
                                    parentsScreenGrid.$el.find('td').removeClass('highlight-profile');

                                    $(this.el).addClass('highlight-profile');
                                    that.buildChildScreenGrid();
                                },

                            }),
                        },


                    ],
                    collection: that.model.parentsScreensColl,
                });
                that.$el.find('.parents-screen-grid-container').empty().append(parentsScreenGrid.render().el);

            },
            buildChildScreenGrid: function () {
                var that = this;
                //Get the area selected
                var parentNameSelected = that.model.get('areaSelected').get('ParentName');
                // Get the Screen for that area
                var childScreenCollection = new Screen.Collections.ItemsColl(that.model.profilesByScreenColl.filter(x => (x.get('ParentName') == parentNameSelected) && (x.get('ScreenName') != null )));

                var childScreenGrid = new Backgrid.Grid({
                    className: 'backgrid table table-hover table-condensed',
                    columns: [

                        {
                            name: 'ScreenName',
                            editable: false,
                            label: 'Screen',
                            cell: Backgrid.StringCell.extend({
                                className: 'string-cell align-center-cell ',
                                events: {
                                    "click": "onClick"
                                },
                                onClick: function () {
                                    that.model.set('screenSelected', this.model);
                                    childScreenGrid.$el.find('td').removeClass('highlight-profile');

                                    $(this.el).addClass('highlight-profile');
                                    that.buildRoleGrid();
                                },

                            }),
                        },


                    ],
                    collection: childScreenCollection,
                });
                that.$el.find('.screens-grid-container').empty().append(childScreenGrid.render().el);

            },
            async buildRoleGrid() {
                var that = this;

                //Get Module Selected
                var moduleIdSelected = that.model.get('screenSelected').get('ModuleId');

                var roleGridCollection = new Screen.Collections.ItemsColl(that.model.modulesActionsColl.filter(x => x.get('ModuleId') == moduleIdSelected)); 

                roleGridCollection
                async function fetchRolesOfIdentity() {
                    try {
                        var identityRoles  = await that.model.getIdentityRoles({ identityId: that.model.get('profileSelected').get('Id') });
                        var roleGrid = new Backgrid.Grid({
                            className: 'backgrid table table-hover table-condensed',
                            columns: [
                                {
                                    name: 'Name',
                                    editable: false,
                                    label: 'Role',
                                    cell: Backgrid.Cell.extend({
                                        className: 'string-cell align-center-cell ',
                                        identityRoles: identityRoles,
                                        events: {
                                            "change input[type='radio']": "onChange"
                                        },
                                        render: function () {
                                            //filter identityRoles by module Selected
                                            var identityRoles = this.identityRoles.filter(x => x.ModuleId == moduleIdSelected);

                                            if (identityRoles.length > 1) {
                                                // Logic to check if both have 1 on role read and read/write to check only the read/write
                                                const groupedByModuleId = identityRoles.reduce((acc, curr) => {
                                                    if (!acc[curr.ModuleId]) {
                                                        acc[curr.ModuleId] = [];
                                                    }
                                                    acc[curr.ModuleId].push(curr);
                                                    return acc;
                                                }, {});

                                                Object.values(groupedByModuleId).forEach(group => {
                                                    // Check if all values are true in the group
                                                    const allTrue = group.every(item => item.Value === true);

                                                    if (allTrue) {
                                                        // If all values are true, change the Value of the item with Code "read" to false
                                                        group.forEach(item => {
                                                            if (item.Code === "read") {
                                                                item.Value = false;
                                                            }
                                                        });
                                                    }
                                                });
                                            }
                                            

                                            this.$el.empty();
                                            var radio = $('<input type="radio" name="role" value="' + this.model.get('Name') + '">');

                                            // si la identity Tiene el rol en True
                                            if (identityRoles.some(x => (x.ActionId == this.model.get('Id')) && (x.Value == true))) {  //|| this.model.get('selected') == true) {
                                                this.model.set('selected', true);
                                                radio.prop('checked', true);
                                            }

                                            var name = $('<span>').text(this.model.get('Name'));
                                            this.$el.append(radio).append(name);
                                            return this;
                                        },
                                        onChange: function (e) {
                                            var value = $(e.target).val();


                                            modal = new Modal.Views.Main({
                                                focusOk: false,
                                                focusSelector: '#btn-cancel',
                                                title: 'Profiles Screen Role',
                                                message: 'Are you sure you want to give Role: ' + this.model.get('Name') + ' to Profile: ' + that.model.get('profileSelected').get('Name') + ' for Screen ' + that.model.get('screenSelected').get('ScreenName') + '?',
                                                buttons_type: "CONTINUE-CANCEL",
                                            });
                                            this.listenToOnce(modal, "continue", function (modal) {
                                                try {
                                                    that.model.updateRoleScreenIdentity({ identityId: that.model.get('profileSelected').get('Id'), actionId: this.model.get('Id'), profileId: that.model.get('profileSelected').get('ProfileId') ,moduleId: moduleIdSelected, cleanActions: false });
                                                }
                                                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                            });

                                            this.listenToOnce(modal, "cancel", function (modal) {
                                                try {
                                                    that.buildRoleGrid();
                                                }
                                                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                            });
                                            modal.show();
                                        }
                                    }),
                                },
                            ],
                            collection: roleGridCollection,
                        });

                        that.$el.find('.role-grid-container').empty().append(roleGrid.render().el);


                        //button to clear roles
                        // Create the button element
                        var clearButton = $('<button>', {
                            text: 'Clear',
                            class: 'btn btn-danger clr-btn',
                            click: function (e) {
                                var value = $(e.target).val();
                                modalClear = new Modal.Views.Main({
                                    focusOk: false,
                                    focusSelector: '#btn-cancel',
                                    title: 'Profiles Screen Role',
                                    message: 'Are you sure you want to clear all roles for Profile: ' + that.model.get('profileSelected').get('Name') + ' for Screen: '+ that.model.get('screenSelected').get('ScreenName') + '?',
                                    buttons_type: "CONTINUE-CANCEL",
                                });
                                that.listenToOnce(modalClear, "continue", function (modalClear) {
                                    try {
                                        that.model.updateRoleScreenIdentity({ identityId: that.model.get('profileSelected').get('Id'), actionId: this.model.get('Id'), moduleId: moduleIdSelected, profileId: that.model.get('profileSelected').get('ProfileId') , cleanActions: true });
                                        
                                    }
                                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                });

                                that.listenToOnce(modalClear, "cancel", function (modalClear) {
                                    try {
                                        that.buildRoleGrid();
                                    }
                                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                });
                                modalClear.show();
                            }
                        });

                        // Append the button to the container after the grid
                        that.$el.find('.role-grid-container').append(clearButton);
                     
                    } catch (error) {
                       
                    }
                }

                fetchRolesOfIdentity();

                

            },

            buildSideBar: function () {
                var that = this;

                var SidebarView = Backbone.View.extend({
                    el: '#user-list',
                    render: function () {
                        this.$el.empty();
                        $('#offcanvasRight').addClass('show');
                        $('#screen-content').addClass('blur');
                        $('#overlay').addClass('show');
                        return this;
                    }
                });

                    var sidebarViewInstance = new SidebarView();
                sidebarViewInstance.render();

                var updatedProfiles = new Backgrid.Grid({
                    className: 'backgrid table table-hover table-condensed updated-profiles',
                    columns: [

                        {
                            name: 'UserName',
                            editable: false,
                            label: 'Username',
                            sortable: true,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: 'string-cell align-center-cell ',
                            }),
                        },

                    ],
                    collection: that.model.updatedProfilesColl,
                });
                that.$el.find('.updated-profiles-container').empty().append(updatedProfiles.render().el);
                $(document).on('click', '#closeButton', function () {
                    $('#offcanvasRight').removeClass('show');
                    $('#screen-content').removeClass('blur');
                    $('#overlay').removeClass('show');
                });

                $(document).on('click', '#overlay', function () {
                    $('#offcanvasRight').removeClass('show');
                    $('#screen-content').removeClass('blur');
                    $('#overlay').removeClass('show');
                });

            },
            refresh: function (isAutoRefresh) {
                if (!isAutoRefresh) {
                    this.model.set({
                        isLoading: true,
                        hasData: false,
                    });
                }
                else {
                    this.model.set({
                        isLoading: false,
                        hasData: true,
                    });
                }
                

                this.model.fetch();
            },
            process_fetched: function () {
                this.model.set({
                    isLoading: false,
                    hasData: true,
                });
            },

        refreshBtn_click: function (e) {
            this.refresh();

        },
            //Auto refresh
            _refresh: function (opt) {
                if (this.autoRefresh.toid != null) {
                    clearTimeout(this.autoRefresh.toid);
                    this.autoRefresh.toid = null;
                }

                if (!this.pauseTimer) {
                    var isAutoRefresh = true;
                    this.refresh(isAutoRefresh);
                } 

                if (this.autoRefresh.enabled == true) {
                    var that = this;

                    this.autoRefresh.toid = setTimeout(
                        function () { that._refresh(); },
                        this.autoRefresh.every
                    );
                }
            },
            startAutoRefresh: function () {
                try {
                    if (this.autoRefresh.enabled !== true) {
                        var that = this;

                        if (this.autoRefresh.toid != null) {
                            clearTimeout(this.autoRefresh.toid);
                            this.autoRefresh.toid = null;
                        }

                        this.autoRefresh.enabled = true;

                        //use a timeout to execute the first refresh to return the handle to the start function caller.
                        //So when the caller finish it will do the first refresh.
                        this.autoRefresh.toid = setTimeout(
                            function () { that._refresh(); },
                            1
                        );
                    }
                } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
            },
            stopAutoRefresh: function () {
                if (this.autoRefresh.toid != null) {
                    clearTimeout(this.autoRefresh.toid);
                    this.autoRefresh.toid = null;
                }
                this.autoRefresh.enabled = false;
            },

        append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.options.state == app.view_states.loading
                || this.options.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.options.state = app.view_states.shown;
                container.append(el);

                this.options.onappend(this);
            }

            if (this.options.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.options.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        },
        bindViewScopedEvents: function () {
            var that = this;
        },
        unbindViewScopedEvents: function () {

        },
        close: function () {
            this.options.state = app.view_states.closed;
            this.stopAutoRefresh();
            this.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        },
        closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.close();
            });
        },
        show: function () {
            this.options.state = app.view_states.shown;

            this.showSubviews();
            this.bindEvents();
            this.$el.show();
        },
        showSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.show();
            });
        },
        hide: function () {
            this.options.state = app.view_states.hidden;

            this.hideSubviews();

            this.$el.hide();
            this.unbind();
            this.stopListening();
        },
        hideSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.hide();
            });
        },
        preRender: function () {
            app.models.subnavbar.set("subnavbar", false);
        },
        reRender: function (urlParams) {
            try {
                this.refresh(viewParams);
            } catch (Error) { }
        },

    });

    Screen.Collections.ItemsColl = Backbone.Collection.extend({
        setDataColl: function (data) {
            var newColl,
                that = this;
            newColl = data;
            that.set(newColl).trigger('fetch', that, data);
        },
    });


    // Required, return the module for AMD compliance.
    return Screen;
});