//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([
    'app',
    'js/templates-loader',
    'backbone',
    'modules/modal2',
    'components/ag-grid/ag-grid-module',
],
    function (app, T, Backbone, Modal, AgGridModule) {

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

        // -----------------------------------------------------------------
        // Collections
        // -----------------------------------------------------------------
        Screen.Collections.Items = Backbone.Collection.extend({
            fetch: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                qp.Add('@search', 'VARCHAR', (params && params.search) ? params.search : '');
                qp.Add('@onlyActives', 'BIT', false);
                qp.Add('@fromRow', 'INT', 0);
                qp.Add('@rowsToFetch', 'INT', 100000);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.GetGrades',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                var rows = (resp && resp.Table) ? resp.Table : [];
                                if (resp && !resp.Table && resp.Message) console.error(resp.Message);
                                that.trigger('fetch', that, rows);
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                            that.trigger('fetch', that, []);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );

                return this;
            },

            upsertItem: function (id, props, success, error) {
                var that = this,
                    QP = new Core.Database.QueryParameters();

                QP.Add('@id', 'INT', id);
                _.each(props, function (p) { QP.Add('@' + p.name, p.type, p.value); });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.UpsertGrade',
                    QP,
                    {
                        onSuccess: function (data) {
                            try {
                                if (data && data.Table && data.Table.length > 0) {
                                    var row = data.Table[0];
                                    if (row.Id && !row.Message) {
                                        if (_.isFunction(success)) success(that, _.pluck(data.Table, 'Id'));
                                    } else if (_.isFunction(error)) {
                                        error(that, row.Message || null);
                                    }
                                } else if (_.isFunction(error)) {
                                    error(that, data && data.Message ? data.Message : null);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onError: function () { if (_.isFunction(error)) error(that); },
                        Async: true,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
            },

            removeItem: function (id, success, error) {
                var that = this,
                    QP = new Core.Database.QueryParameters();

                QP.Add('@id', 'INT', id);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.RemoveGrade',
                    QP,
                    {
                        onSuccess: function (data) {
                            try {
                                if (data && data.Table && data.Table.length > 0) {
                                    var row = data.Table[0];
                                    if (row.Id) {
                                        if (_.isFunction(success)) success(that, row.Id);
                                    } else if (_.isFunction(error)) {
                                        error(that, row.Message || null);
                                    }
                                } else if (_.isFunction(error)) {
                                    error(that);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onError: function () { if (_.isFunction(error)) error(that); },
                        Async: true,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
            },
        });

        Screen.Collections.GradeGroups = Backbone.Collection.extend({
            fetch: function (options) {
                var that = this,
                    qp = new Core.Database.QueryParameters();
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.GetGradeGroups',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.reset(resp.Table);
                                    that.trigger('fetch', that);
                                    if (options && _.isFunction(options.success)) options.success(that);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        Async: true,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });

        Screen.Collections.ScrapRecipes = Backbone.Collection.extend({
            fetch: function (options) {
                var that = this,
                    qp = new Core.Database.QueryParameters();
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.GetScrapRecipes',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.reset(resp.Table);
                                    that.trigger('fetch', that);
                                    if (options && _.isFunction(options.success)) options.success(that);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        Async: true,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });

        Screen.Collections.GradeChemistry = Backbone.Collection.extend({
            fetch: function (gradeId, options) {
                var that = this,
                    qp = new Core.Database.QueryParameters();
                qp.Add('@gradeId', 'INT', gradeId);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAT.GetGradeChemistry',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.reset(resp.Table);
                                    that.trigger('fetch', that, resp.Table);
                                    if (options && _.isFunction(options.success)) options.success(resp.Table);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        Async: true,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });

        // -----------------------------------------------------------------
        // Model
        // -----------------------------------------------------------------
        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                search: '',
                activeFilter: 'all',            // 'all' | 'active' | 'inactive'
                statusOptions: [
                    { label: 'All', value: 'all' },
                    { label: 'Active', value: 'active' },
                    { label: 'Inactive', value: 'inactive' },
                ],
                groupFilter: null,

                // Dropdown sources (populated after GetGradeGroups / GetScrapRecipes)
                gradeGroupsForFilter: [],   // [{label, value}] — value = GradeGroupId
                gradeGroupsForEdit: [],     // same shape
                scrapRecipesForEdit: [],    // [{label, value}] — value = Recipe Name

                // KPIs
                totalCount: 0,
                activeCount: 0,
                groupsCount: 0,

                hasData: false,
                isLoading: false,
                hasPermission: false,

                // Edit modal state
                editId: null,
                editTitle: '',
                editName: '',
                editDescription: '',
                editGroupId: null,
                editRecipeName: null,
                editActive: false,
                editSaving: false,
                editError: '',

                // Chemistry modal state
                chemistryGradeName: '',
            },
        });

        // -----------------------------------------------------------------
        // Custom AG Grid module: delegate cell clicks to action buttons
        // -----------------------------------------------------------------
        var CustomAgGridModule = AgGridModule.extend({
            initialize: function (options) {
                this.mainView = options.mainView;
                AgGridModule.prototype.initialize.call(this, options);
            },
            onCellClicked: function (params) {
                var mainView = this.mainView;
                if (!params || !params.data || !mainView) {
                    return AgGridModule.prototype.onCellClicked.call(this, params);
                }
                var target = params.event && params.event.target;
                if (!target) {
                    return AgGridModule.prototype.onCellClicked.call(this, params);
                }

                if (target.classList.contains('grades-chemistry-btn') || target.closest('.grades-chemistry-btn')) {
                    mainView.openChemistryModal(params.data);
                    return;
                }
                if (target.classList.contains('grades-edit-btn') || target.closest('.grades-edit-btn')) {
                    mainView.openEditModal(params.data);
                    return;
                }
                if (target.classList.contains('grades-delete-btn') || target.closest('.grades-delete-btn')) {
                    mainView.confirmDelete(params.data);
                    return;
                }

                AgGridModule.prototype.onCellClicked.call(this, params);
            }
        });

        // -----------------------------------------------------------------
        // Column definitions for the main grid
        // -----------------------------------------------------------------
        function buildMainColumnDefs(that) {
            function activeRenderer(params) {
                if (params.value === true || params.value === 1) {
                    return '<span class="active-cell"><i class="fa fa-check-circle" aria-hidden="true"></i></span>';
                }
                return '<span class="active-cell"><i class="fa fa-times-circle" aria-hidden="true"></i></span>';
            }

            function actionsRenderer(params) {
                var canWrite = that.model.get('hasPermission');
                var disabledAttr = canWrite ? '' : ' disabled';
                return '' +
                    '<div class="grades-actions-cell">' +
                        '<button type="button" class="grades-action-btn grades-chemistry-btn" title="View chemistry">' +
                            '<i class="fa fa-flask" aria-hidden="true"></i>' +
                        '</button>' +
                        '<button type="button" class="grades-action-btn grades-edit-btn" title="Edit"' + disabledAttr + '>' +
                            '<i class="fa fa-pencil" aria-hidden="true"></i>' +
                        '</button>' +
                        '<button type="button" class="grades-action-btn grades-delete-btn" title="Delete"' + disabledAttr + '>' +
                            '<i class="fa fa-trash-o" aria-hidden="true"></i>' +
                        '</button>' +
                    '</div>';
            }

            return [
                { field: 'Name',             headerName: 'Name',        flex: 1,   minWidth: 100, pinned: 'left', showFilter: true,  cellClass: 'text-center' },
                { field: 'Group',            headerName: 'Group',       flex: 1.2, minWidth: 140, showFilter: true,  cellClass: 'text-left' },
                { field: 'Description',      headerName: 'Description', flex: 2,   minWidth: 200, showFilter: true,  cellClass: 'text-left' },
                { field: 'ScrapRecipeName',  headerName: 'Scrap Recipe',flex: 1.2, minWidth: 140, showFilter: true,  cellClass: 'text-center' },
                {
                    field: 'Active', headerName: 'Active', width: 90, sortable: true,
                    cellClass: 'text-center',
                    cellRenderer: activeRenderer,
                },
                {
                    colId: 'actions', headerName: 'Actions',
                    width: 150, pinned: 'right', sortable: false, resizable: false,
                    suppressCellSelection: true,
                    cellRenderer: actionsRenderer,
                },
            ];
        }

        // -----------------------------------------------------------------
        // Column definitions for the chemistry modal grid
        // -----------------------------------------------------------------
        function buildChemistryColumnDefs() {
            return [
                { field: 'ElementCode', headerName: 'Element', flex: 1, minWidth: 80,  cellClass: 'text-center' },
                { field: 'Min',         headerName: 'Min',     flex: 1, minWidth: 80,  cellClass: 'text-center' },
                { field: 'Aim',         headerName: 'Aim',     flex: 1, minWidth: 80,  cellClass: 'text-center' },
                { field: 'Max',         headerName: 'Max',     flex: 1, minWidth: 80,  cellClass: 'text-center' },
            ];
        }

        // -----------------------------------------------------------------
        // View
        // -----------------------------------------------------------------
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'grades',
            id: 'grades',
            title: 'Grades and Chemistries',
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click .btn-export-to-excel': this.onExportClick,
                    'click #grades-save-edit-btn': this.onSaveEdit,
                };
            },
            bindings: 'data-bind',

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

                if (!this.model) this.model = new Screen.Models.Main();

                this.itemsColl = new Screen.Collections.Items();
                this.gradeGroupsColl = new Screen.Collections.GradeGroups();
                this.scrapRecipesColl = new Screen.Collections.ScrapRecipes();
                this.chemistryColl = new Screen.Collections.GradeChemistry();

                this.allRows = [];

                this.subviews = {};
                this.viewParams = null;

                this.getPermissions();

                this.agGridModule = new CustomAgGridModule({
                    mainView: this,
                    columnDefs: buildMainColumnDefs(this),
                    rowData: [],
                    fileName: 'lab-grades',
                    screenTitle: this.title,
                    pagination: 'hidden',
                    gridOptions: {
                        wrapHeaderText: true,
                        autoHeaderHeight: true,
                    },
                });

                this.chemistryAgGridModule = new AgGridModule({
                    columnDefs: buildChemistryColumnDefs(),
                    rowData: [],
                    fileName: 'lab-grades-chemistry',
                    screenTitle: 'Grade Chemistry',
                    pagination: 'hidden',
                    gridOptions: {
                        wrapHeaderText: true,
                        autoHeaderHeight: true,
                    },
                });

                this.bindEvents();
            },

            getPermissions: function () {
                var write = $.inArray('mes_config_grades_readWrite', app.models.user.get('roles'));
                this.model.set('hasPermission', write !== -1);
            },

            bindEvents: function () {
                // Filters (search / active / group) are deferred — they stay in the model
                // via Epoxy bindings but only take effect when the user clicks Refresh.
                this.listenTo(this.itemsColl, 'fetch', this.processes_ready);
            },

            render: function (container, viewParams) {
                var that = this;

                this.viewParams = viewParams;

                var thatContainer = (this.options.container) ? this.options.container : container;
                this.options.container = thatContainer;

                var customPath = '/app/pages/lab/' + 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());
                                that.applyBindings();

                                // Mount grids
                                that.agGridModule.render();
                                that.$el.find('#grades-grid').append(that.agGridModule.$el);

                                that.chemistryAgGridModule.render();
                                that.$el.find('#chemistry-grid').append(that.chemistryAgGridModule.$el);

                                that.append(thatContainer, that.$el);

                                // Kick off the lookups + first data fetch
                                that.loadLookups();
                                that._refresh();
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            // -----------------------------------------------------------------
            // Data loading
            // -----------------------------------------------------------------
            loadLookups: function () {
                var that = this;
                this.gradeGroupsColl.fetch({
                    success: function () {
                        // String() on the value: option attributes in the DOM are strings,
                        // and jQuery.fn.val() uses strict equality to match — keep the model
                        // side in the same type so the binding can resolve a selection.
                        var options = that.gradeGroupsColl.map(function (m) {
                            return { label: m.get('Name'), value: String(m.get('Id')) };
                        });
                        that.model.set({
                            gradeGroupsForFilter: options,
                            gradeGroupsForEdit: options,
                            groupsCount: options.length,
                        });
                        // If grades have already arrived, enrich Group names now.
                        if (that.allRows && that.allRows.length > 0) {
                            that.applyClientSideFilter();
                        }
                    }
                });

                this.scrapRecipesColl.fetch({
                    success: function () {
                        var options = [{ label: '', value: null }].concat(
                            that.scrapRecipesColl.map(function (m) {
                                return { label: m.get('Name'), value: m.get('Name') };
                            })
                        );
                        that.model.set('scrapRecipesForEdit', options);
                    }
                });
            },

            _refresh: function () {
                var that = this;
                this.model.set('isLoading', true);
                this.agGridModule.gridReadyPromise
                    .then(function () { that.agGridModule.showLoadingOverlay(); })
                    .catch(function () { });
                this.itemsColl.fetch({});
            },

            processes_ready: function (coll, rows) {
                var that = this;
                try {
                    this.allRows = (rows || []).slice();
                    this.model.set({
                        hasData: this.allRows.length > 0,
                        isLoading: false,
                    });
                    // Wait for the grid to be ready before pushing row data — the
                    // wrapper's setRowData silently stashes data into gridOptions
                    // if gridApi isn't set yet, and onGridReady never re-reads it.
                    this.agGridModule.gridReadyPromise
                        .then(function () {
                            that.applyClientSideFilter();
                            that.agGridModule.hideOverlay();
                        })
                        .catch(function () { });
                } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            applyClientSideFilter: function () {
                var that = this;
                var attrs = this.model.toJSON();
                var search = (attrs.search || '').toLowerCase().trim();
                var activeFilter = attrs.activeFilter;
                var groupFilter = attrs.groupFilter;

                // Epoxy renders `optionsDefault: { value: null }` as `<option value="">`,
                // so when that default option is selected the model gets `""` — not `null` —
                // synced back. Treat '' and null equivalently for "no filter".
                var hasGroupFilter = (groupFilter !== null && groupFilter !== undefined && groupFilter !== '');

                // The SP returns GradeGroupId but not the group name. Enrich each row with
                // the name from gradeGroupsColl so the grid column and the search box can
                // match on group name. This may run before lookups finish — in that case
                // Group stays blank and a later applyClientSideFilter re-enriches it.
                var groupsById = {};
                this.gradeGroupsColl.each(function (m) {
                    groupsById[m.get('Id')] = m.get('Name');
                });

                var enriched = _.map(this.allRows, function (r) {
                    return _.extend({}, r, { Group: groupsById[r.GradeGroupId] || '' });
                });

                var filtered = _.filter(enriched, function (row) {
                    if (search) {
                        var name = (row.Name || '').toLowerCase();
                        var desc = (row.Description || '').toLowerCase();
                        var group = (row.Group || '').toLowerCase();
                        var recipe = (row.ScrapRecipeName || '').toLowerCase();
                        if (name.indexOf(search) === -1
                            && desc.indexOf(search) === -1
                            && group.indexOf(search) === -1
                            && recipe.indexOf(search) === -1) return false;
                    }
                    if (activeFilter === 'active'   && !(row.Active === true || row.Active === 1)) return false;
                    if (activeFilter === 'inactive' &&  (row.Active === true || row.Active === 1)) return false;
                    // != (not !==) — the <select> returns a string, GradeGroupId is numeric
                    if (hasGroupFilter && row.GradeGroupId != groupFilter) return false;
                    return true;
                });

                this.agGridModule.gridReadyPromise
                    .then(function () { that.agGridModule.setRowData(filtered); })
                    .catch(function () { });

                this.model.set({
                    totalCount: filtered.length,
                    activeCount: _.filter(filtered, function (r) { return r.Active === true || r.Active === 1; }).length,
                });
            },

            // -----------------------------------------------------------------
            // Edit modal
            // -----------------------------------------------------------------
            openEditModal: function (rowData) {
                if (!this.model.get('hasPermission')) return;
                this.model.set({
                    editId: rowData.Id,
                    editTitle: rowData.Name || '',
                    editName: rowData.Name || '',
                    editDescription: rowData.Description || '',
                    // String() because option values in the rendered <select> are HTML
                    // attribute strings; jQuery.fn.val(int) uses strict equality and
                    // would not match <option value="5"> against the integer 5, leaving
                    // the dropdown blank when the modal opens.
                    editGroupId: rowData.GradeGroupId != null ? String(rowData.GradeGroupId) : null,
                    editRecipeName: rowData.ScrapRecipeName || null,
                    editActive: rowData.Active === true || rowData.Active === 1,
                    editSaving: false,
                    editError: '',
                });
                this.$el.find('#editGradeModal').modal('show');
            },

            onSaveEdit: function () {
                var that = this;
                var attrs = this.model.toJSON();

                if (!attrs.editId) return;
                if (!attrs.editName || !attrs.editName.trim()) {
                    this.model.set('editError', 'Name is required.');
                    return;
                }

                this.model.set({ editSaving: true, editError: '' });

                this.itemsColl.upsertItem(
                    attrs.editId,
                    [
                        { name: 'name',          type: 'VARCHAR',      value: attrs.editName.trim() },
                        { name: 'description',   type: 'VARCHAR',      value: attrs.editDescription != null ? attrs.editDescription : '' },
                        { name: 'gradeGroupId',  type: 'INT',          value: (attrs.editGroupId != null && attrs.editGroupId !== '') ? parseInt(attrs.editGroupId, 10) : null },
                        { name: 'active',        type: 'BIT',          value: attrs.editActive ? 1 : 0 },
                        { name: 'recipeName',    type: 'VARCHAR(MAX)', value: attrs.editRecipeName || null },
                    ],
                    function () {
                        try {
                            that.model.set({ editSaving: false });
                            that.$el.find('#editGradeModal').modal('hide');
                            app.views.topMessages.showMessage('Grade saved.', { stay: 4000 });
                            that._refresh();
                        } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    function (coll, msg) {
                        try {
                            that.model.set({
                                editSaving: false,
                                editError: msg ? app.translate(app, msg) : 'Save failed.',
                            });
                        } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    }
                );
            },

            // -----------------------------------------------------------------
            // Delete with confirm modal
            // -----------------------------------------------------------------
            confirmDelete: function (rowData) {
                if (!this.model.get('hasPermission')) return;
                var that = this;

                var modal = new Modal.Views.Main({
                    focusOk: false,
                    focusSelector: '#btn-cancel',
                    title: app.translate([this, app], 'delete_item_modal_confirm_title'),
                    message: app.translate([this, app], 'delete_item_modal_confirm_message'),
                    buttons_type: 'CONTINUE-CANCEL',
                });

                this.listenToOnce(modal, 'continue', function () {
                    that.itemsColl.removeItem(
                        rowData.Id,
                        function () {
                            app.views.topMessages.showMessage('Grade removed.', { stay: 4000 });
                            that._refresh();
                        },
                        function (coll, msg) {
                            app.views.topMessages.showMessage(msg ? app.translate(app, msg) : 'Delete failed.', { stay: 6000 });
                        }
                    );
                });

                modal.show();
            },

            // -----------------------------------------------------------------
            // Chemistry modal
            // -----------------------------------------------------------------
            openChemistryModal: function (rowData) {
                var that = this;
                this.model.set({ chemistryGradeName: rowData.Name || '' });

                var $modal = this.$el.find('#chemistryModal');

                // The chemistry grid was rendered while the modal was hidden, so it
                // computed its size as 0x0. Resize it once the modal is fully visible.
                $modal.off('shown.bs.modal.grades').on('shown.bs.modal.grades', function () {
                    var api = that.chemistryAgGridModule.gridApi;
                    if (api && api.sizeColumnsToFit) api.sizeColumnsToFit();
                    if (api && api.onGridSizeChanged) api.onGridSizeChanged();
                });

                this.chemistryAgGridModule.gridReadyPromise
                    .then(function () {
                        that.chemistryAgGridModule.setRowData([]);
                        that.chemistryAgGridModule.showLoadingOverlay();
                    })
                    .catch(function () { });

                $modal.modal('show');

                this.chemistryColl.fetch(rowData.Id, {
                    success: function (rows) {
                        that.chemistryAgGridModule.gridReadyPromise
                            .then(function () {
                                that.chemistryAgGridModule.setRowData(rows || []);
                                that.chemistryAgGridModule.hideOverlay();
                                var api = that.chemistryAgGridModule.gridApi;
                                if (api && api.sizeColumnsToFit) api.sizeColumnsToFit();
                            })
                            .catch(function () { });
                    }
                });
            },

            // -----------------------------------------------------------------
            // Toolbar handlers
            // -----------------------------------------------------------------
            onExportClick: function () {
                if (this.agGridModule) this.agGridModule.exportToExcel(false);
            },

            refreshBtn_click: function () {
                this._refresh();
                window.scrollTo(0, 0);
            },


            // -----------------------------------------------------------------
            // View lifecycle
            // -----------------------------------------------------------------
            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) {
                    this.options.state = app.view_states.shown;
                    container.append(el);
                    this.options.onappend(this);
                }
                if (this.options.state == app.view_states.hidden) container.append(el);
                if (this.options.state == app.view_states.closed) return;
            },
            bindViewScopedEvents: function () { },
            unbindViewScopedEvents: function () { },
            close: function () {
                this.options.state = app.view_states.closed;
                try { this.$el.find('#editGradeModal').modal('hide'); } catch (e) { }
                try { this.$el.find('#chemistryModal').modal('hide'); } catch (e) { }
                if (this.agGridModule && this.agGridModule.destroy) this.agGridModule.destroy();
                if (this.chemistryAgGridModule && this.chemistryAgGridModule.destroy) this.chemistryAgGridModule.destroy();
                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 () {
                try { this._refresh(); } catch (e) { }
            },
        });

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