//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',
  'moment',


  'modules/modal2',

  'components/ag-grid/ag-grid-module',
  'chart',
  'backgrid/infinator',
  'backgrid/moment-cell',
  'backgrid/grouped-columns',

  "js/jquery.floatThead/jquery.floatThead",
  'js/jquery.contextMenu/jquery.contextMenu',
  "js/bootstrap-slider/bootstrap-slider.min"
],
  function (app, T, Backgrid, moment, Modal, AgGridModule, Chart) {

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

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
      defaults: {
        start: new moment().subtract(2, 'days').format('YYYY-MM-DD'),
        end: new moment().format('YYYY-MM-DD'),




        shiftId: '-',
        shifts: [{ label: 'D', value: 1 }, { label: 'N', value: 2 }],

        hasData: false,
        isLoading: false,
        isExcelExporting: false,
        grid: [],
        searchText: '',
        isPageLoading: false,
      },
      computeds: {
        start$: {
          deps: ['start'],
          get: function (value) {
            return value;
          },
          set: function (value) {
            return { start: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value, };
          },
        },
        end$: {
          deps: ['end'],
          get: function (value) {
            return value;
          },
          set: function (value) {
            return { end: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value, };
          },
        },
      },


    });

    var CustomAgGridModule = AgGridModule.extend({
      initialize: function (options) {
        this.bus = options.bus;
        this.itemsColl = options.delaysColl;

        options.onGridReady = this.onGridReady.bind(this);

        this.columnDefs = [
          {
            headerName: 'Caster',
            valueGetter: function (params) {
              return params.data.DelayAreaAssetId === 1000
                ? 'Caster 1'
                : 'Caster 2';
            },
            minWidth: 70, sortable: false
          },
          {
            headerName: 'Total Delays',
            field: 'TotalDelayMinutes',
            cellRenderer: this.formatDurationRenderer.bind(this),
            minWidth: 70,
            flex: 1
          },
          { field: 'DelayCategoryName', headerName: 'Area', flex: 1, minWidth: 70, sortable: false },
          { field: 'DelayCount', headerName: 'Count', minWidth: 70 }

        ];

        options.columnDefs = this.columnDefs;

        AgGridModule.prototype.initialize.call(this, options);
      },
      formatDurationRenderer: function (d) {
        var minutes = Number(d.data.TotalDelayMinutes);
        var totalSeconds = minutes * 60;

        var h = Math.floor(totalSeconds / 3600);
        var m = Math.floor((totalSeconds % 3600) / 60);
        var s = totalSeconds % 60;

        return h + "H " + m + "m " + s + "s";
      },
      onGridReady(params) {
        this.gridApi = params.api;
        this.columnApi = params.columnApi;
        this.lastSortModel = [];
        this.gridApi.addEventListener('sortChanged', event => {
      this.lastSortModel = event.columns[0] || [];
      this.bus.trigger('gridSorted');
    });
      },
      getGridApi() {
        return this.gridApi;
      }
    });


    var DelayCodesAgGridModule = AgGridModule.extend({
      initialize: function (options) {
        this.bus = options.bus;
        this.itemsColl = options.delayCodesColl;  // note: delayCodesColl
        options.onGridReady = this.onGridReady.bind(this);
        this.columnDefs = [
          {
            headerName: 'Caster',
            valueGetter: function (params) {
              return params.data.DelayAreaAssetId === 1000
                ? 'Caster 1'
                : 'Caster 2';
            },
            minWidth: 70,
            sortable: false
          },
          { field: 'DelayCodeName', headerName: 'Cause', flex: 1, minWidth: 80, sortable: false },
          { field: 'DelayCategoryName', headerName: 'Area', flex: 1, minWidth: 70, sortable: false },
          {
            headerName: 'Total Delay',
            field: 'TotalDelayMinutes',
            cellRenderer: this.formatDurationRenderer.bind(this),
            flex: 1,
            minWidth: 100

          },
          { field: 'DelayCount', headerName: 'Count', flex: 1, minWidth: 50 }
        ];

        // inject into options and call base
        options.columnDefs = this.columnDefs;
        AgGridModule.prototype.initialize.call(this, options);
      },

      // reuse your duration renderer
      formatDurationRenderer: function (d) {
        var minutes = Number(d.data.TotalDelayMinutes);
        var totalSeconds = minutes * 60;
        var h = Math.floor(totalSeconds / 3600);
        var m = Math.floor((totalSeconds % 3600) / 60);
        var s = totalSeconds % 60;
        return h + 'H ' + m + 'm ' + s + 's';
      },
      onGridReady(params) {
        this.gridApi = params.api;
        this.columnApi = params.columnApi;
          this.gridApi.addEventListener('sortChanged', event => {
      this.lastSortModel = event.columns[0] || [];
      this.bus.trigger('gridSorted');
    });
      },
      getGridApi() {
        return this.gridApi;
      }
    });


    Screen.Views.Main = Backbone.Epoxy.View.extend({
      template: 'caster-delays-by-date',
      id: 'caster-delays-by-date',
      title: 'Caster Delays By Date',
      categoryChart: null,
      events: function () {
        return {
          'click #refreshBtn': this.refreshBtn_click,
          "click #exportExcelBtn": this.exportToExcel,
          'click #calendarStartBtn': this.calendarStartBtn_click,
          'click #calendarEndBtn': this.calendarEndBtn_click,
          'click #viewToggle .toggle-btn': 'onViewToggle',
          'click #redirectToDelayMg': this.redirectToDelayMg,
          'click #metricToggle .metric-btn': this.onMetricToggle,

        };
      },
      bindings: 'data-bind',
      bindingSources: null,
      grids: null,
      itemsColl: null,
      subviews: null,
      viewParams: null,
      initialize: function () {
        this.options.state = app.view_states.loading;
        this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };
        this.bus = _.extend({}, Backbone.Events);
        // Init AgGridModule:
        this.agGridModule = new CustomAgGridModule({
          delaysColl: this.itemsColl,
          bus: this.bus,
          rowData: [],
          fileName: 'caster-delays-by-date'
        });

        this.delayCodesGridModule = new DelayCodesAgGridModule({
          delayCodesColl: this.delayCodesColl,
          bus: this.bus,
          rowData: [],
          fileName: 'caster-delay-codes'
        });
        this.categoryChart = null;
        this.currentViewType = 'area';

        this.bus.on('gridSorted', this.processes_ready, this);
        this.bus.on('gridSorted', this.delayCodesProcesses_ready, this);


        var that = this;

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

        this.grids = {};
        this.itemsColl = new Backbone.Collection();
        this.delayCodesColl = new Backbone.Collection();
        this.currentMetric = 'count';
        this._updateMetricToggleUI();


        this.bindingSources = {};

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


        this.bindEvents();

        this.bus.on("refreshGrid", this._refresh, this);
        this.bus.on("modalAcceptBtn", this.onModalAcceptBtn, this);
      },
      _updateMetricToggleUI: function () {
        var metric = this.currentMetric || 'count';
        var $all = this.$('#metricToggle .metric-btn');
        var $active = this.$('#metricToggle .metric-btn[data-metric="' + metric + '"]');

        $all
          .removeClass('bg-blue-600 text-white')
          .addClass('bg-white text-blue-600');

        $active
          .removeClass('bg-white text-blue-600')
          .addClass('bg-blue-600 text-white');
      },
      onViewToggle: function (e) {
        var $btn = this.$(e.currentTarget);
        var mode = this.currentViewType = $btn.data('value');

        var $area = this.$('#areaSection'),
          $cause = this.$('#causeSection');

        if (mode === 'area') {
          // show area, hide cause
          $area
            .addClass('opacity-100 pointer-events-auto')
            .removeClass('opacity-0 pointer-events-none');
          $cause
            .addClass('opacity-0  pointer-events-none')
            .removeClass('opacity-100  pointer-events-auto');
        } else {
          // show cause, hide area
          $cause
            .addClass('opacity-100  pointer-events-auto')
            .removeClass('opacity-0  pointer-events-none');
          $area
            .addClass('opacity-0  pointer-events-none')
            .removeClass('opacity-100  pointer-events-auto');
        }
        // 1) restyle pills
        var $buttons = this.$('#viewToggle .toggle-btn');
        $buttons
          .removeClass('bg-blue-600 text-white')
          .addClass('bg-white text-blue-600');
        $btn
          .removeClass('bg-white text-blue-600')
          .addClass('bg-blue-600 text-white');

        this._updateMetricToggleUI();

        // optionally re-fetch/refresh
        this._refresh({ reset: true, params: this.model.toJSON() });
      },

      onMetricToggle: function (e) {
        var $btn = this.$(e.currentTarget);
        var metric = this.currentMetric = $btn.data('metric');
        var $all = this.$('#metricToggle .metric-btn');

        // restyle buttons
        $all
          .removeClass('bg-blue-600 text-white')
          .addClass('bg-white text-blue-600');
        $btn
          .removeClass('bg-white text-blue-600')
          .addClass('bg-blue-600 text-white');

        // re‐draw whichever chart is visible
        if (this.currentViewType === 'area') {
          this.processes_ready();
        } else {
          this.delayCodesProcesses_ready();
        }
      },



      calendarStartBtn_click: function () {
        $('#dateStartTbx').datepicker('show');
      },
      calendarEndBtn_click: function () {
        $('#dateEndTbx').datepicker('show');
      },
      redirectToDelayMg: function () {
        var that = this;
        try {

          var startDelay = that.model.get('start').slice(0, 10).replace(/-/g, '');

          var endDelay = '';
          if (that.model.get('end') && that.model.get('end') !== '') {
            let endDate = new Date(that.model.get('end').slice(0, 10));
            endDate.setDate(endDate.getDate() + 1);

            // Format to YYYYMMDD
            endDelay = endDate.toISOString().slice(0, 10).replace(/-/g, '');
          }

          Backbone.history.navigate('!/caster-delays-manager/' + startDelay + '/' + endDelay, { trigger: true });
        }
        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
      },

      onModalAcceptBtn: function () {
        this.refreshBtn_click();
      },
      bindEvents: function () {
        this.listenTo(this.itemsColl, 'backgrid:rowclick', this.processes_backgrid_rowclick)
          .listenTo(this.itemsColl, 'fetch', this.processes_ready)
          .listenTo(this.model, 'triggerFetch', this.refreshBtn_click)
          .listenTo(this, 'data:ready', this.onDataReady);


      },
      removeHighlightRow: function () {
        var previousIndex = this.model.get('index');
        var rowsView = this.model.get('grid').body.rows;


        if (rowsView && rowsView[previousIndex] && rowsView[previousIndex].$el)
          rowsView[previousIndex].$el.removeClass("onRightClickSelectedRow");


      },
      _refresh: function (opt) {
        var that = this,
          qp = new Core.Database.QueryParameters();

        // set up your params exactly as you were doing
        qp.Add('@Start', 'DATE', this.model.get('start'));
        qp.Add('@End', 'DATE', this.model.get('end'));
        qp.Add('@IncludeUndeclared', 'INT', 1);
        // Casters area root so EAF delays never aggregate into (or mislabel in) the caster pareto.
        qp.Add('@DelayAreaAssetId', 'INT', 1);

        // call once
        Core.Json.CallProcedure(
          app.DatabaseNames.MES + '.DEL.GetDelaysForPareto',
          qp,
          {
            onSuccess: function (resp) {
              // Table 1 → itemsColl
              if (resp && resp.Table) {
                that.itemsColl.reset(resp.Table);
              }
              // Table 2 → delayCodeColl
              if (resp && resp.Table1) {
                that.delayCodesColl.reset(resp.Table1);
              }
              // notify view that data’s here
              that.trigger('data:ready');
            },
            onFailure: function (err) { console.error(err); },
            Secured: true,
            Async: true
          },
          app.ConnectionStrings.app
        );
      },
      onDataReady: function () {
        // 1) update your grid off itemsColl
        this.agGridModule.setRowDataAsCollection(this.itemsColl);
        this.agGridModule.hideOverlay();

        // 2) update your first chart off itemsColl…
        this.processes_ready();

        // 3) update your second grid/chart off delayCodeColl
        this.delayCodesProcesses_ready();
      },


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

        this.viewParams = viewParams;

        // Initialize the loading state
        that.model.set({ isPageLoading: true });

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

        //the screens have a custompath, so it has to be specified in the customPath variable that is
        //then sent to the template loader.
        var customPath = '/app/pages/caster/' + 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();

                that.$el.find('.input-date').datepicker();

                that.agGridModule.render();

                that.$('#categoryGrid').append(that.agGridModule.$el);
                that.delayCodesGridModule.render();
                that.$('#detailsGrid').append(that.delayCodesGridModule.$el);

                var displayValuesPlugin = {
                  id: 'displayValues',
                  afterDatasetsDraw(chart) {
                    var ctx = chart.ctx;
                    chart.data.datasets.forEach((dataset, i) => {
                      var meta = chart.getDatasetMeta(i);
                      meta.data.forEach((bar, index) => {
                        var val = dataset.data[index];
                        ctx.fillStyle = dataset.borderColor[index] || '#000';
                        ctx.font = 'bold 12px sans-serif';
                        ctx.textAlign = 'center';
                        ctx.fillText(val, bar.x, bar.y - 6);
                      });
                    });
                  }
                };

                var canvas = that.$('#categoryChart');
                if (!canvas.length) {
                  console.error('Canvas #categoryChart not found');
                } else {
                  var ctx = canvas[0].getContext('2d');
                  that.categoryChart = new Chart(ctx, {
                    type: 'bar',
                    data: {
                      labels: [],
                      datasets: [{

                        data: []
                      }]
                    },
                    options: {
                      responsive: true,
                      plugins: {
                        legend: { display: false },
                      },
                      scales: {
                        y: { beginAtZero: true, grace: '10%', display: true, text: 'Count' }
                      }
                    },
                    plugins: [displayValuesPlugin]
                  });
                }



                var $ctx2 = that.$('#delayCodesChart');
                if (!$ctx2.length) {
                  console.error('No #delayCodesChart found');
                } else {
                  var ctx2 = $ctx2[0].getContext('2d');
                  that.delayCodesChart = new Chart(ctx2, {
                    type: 'bar',
                    data: {
                      labels: [],
                      datasets: [{

                        data: [],
                        backgroundColor: [],
                        borderColor: [],
                        borderWidth: 1
                      }]
                    },
                    options: {
                      responsive: true,
                      plugins: {
                        legend: { display: true }
                      },

                      scales: { y: { beginAtZero: true, grace: '10%', display: true, text: 'Count' } }
                    },
                    plugins: [displayValuesPlugin]
                  });
                }

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

                var fixedParams = _.extend({}, viewParams);
                if (fixedParams.start)
                  fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                if (fixedParams.end)
                  fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.shiftId)
                  fixedParams.shiftId = (viewParams.shiftId != '-' && viewParams.shiftId != null) ? parseInt(viewParams.shiftId) : '-';


                that.model.set(fixedParams);

                //Call first refresh.
                var params = that.model.toJSON();

                that._refresh({
                  reset: true,
                  params: _.extend(
                    {},
                    params,
                    {
                    }
                  ),
                });

                that.model.set({ isPageLoading: false });


              },
              true,
              customPath
            );
          },
          customPath, "delays_report"
        );
      },

processes_ready: function() {
  try {
    // 1) keep grid in sync
    this.agGridModule.setRowDataAsCollection(this.itemsColl);
    this.agGridModule.hideOverlay();

    // 2) get the user‐sort (colId & asc/desc) from lastSortModel
    const sortDef  = this.agGridModule.lastSortModel || {};
    const sortCol  = sortDef.colId;                   // e.g. "TotalDelayMinutes" or "DelayCount"
    const sortAsc  = sortDef.sort === 'asc';

    // 3) choose the chart’s data field
    const metricField = this.currentMetric === 'minutes'
      ? 'TotalDelayMinutes'
      : 'DelayCount';

    // 4) pick the field to sort by:
    //    - if the grid is sorted, use that column
    //    - otherwise sort by your metric descending by default
    const sortField = sortCol || metricField;
    let sorted = _.sortBy(this.itemsColl.models, m => m.get(sortField));
    if (!sortAsc) sorted = sorted.reverse();

    // 5) only take top 10
    sorted = sorted.slice(0, 10);

    // 6) unpack into labels, values, colors
    const labels = [], values = [], colors = [];
    sorted.forEach(m => {
      const caster = m.get('DelayAreaAssetId') === 1000 ? 'C1 ' : 'C2 ';
      labels.push(caster + m.get('DelayCategoryName'));
      values.push(m.get(metricField));
      colors.push(m.get('DelayCategoryColor') || '#ccc');
    });

    // 7) redraw chart
    const ds = this.categoryChart.data.datasets[0];
    this.categoryChart.data.labels           = labels;
    ds.data                                    = values;
    ds.backgroundColor                         = colors;
    ds.borderColor                             = colors;
    this.categoryChart.options.scales.y.title = {
      display: true,
      text: this.currentMetric === 'minutes'
        ? 'Total Delay (min)'
        : 'Count'
    };
    this.categoryChart.update();
  }
  catch (e) {
    console.error(e);
  }
},


delayCodesProcesses_ready: function() {
  try {
    // 1) keep grid in sync
    this.delayCodesGridModule.setRowDataAsCollection(this.delayCodesColl);
    this.delayCodesGridModule.hideOverlay();

    // 2) user‐sort
    const sortDef  = this.delayCodesGridModule.lastSortModel || {};
    const sortCol  = sortDef.colId;
    const sortAsc  = sortDef.sort === 'asc';

    // 3) metric field
    const metricField = this.currentMetric === 'minutes'
      ? 'TotalDelayMinutes'
      : 'DelayCount';

    // 4) which field to sort by?
    const sortField = sortCol || metricField;
    let sorted = _.sortBy(this.delayCodesColl.models, m => m.get(sortField));
    if (!sortAsc) sorted = sorted.reverse();
    sorted = sorted.slice(0, 10);

    // 5) unpack + legend build
    const labels = [], values = [], colors = [], cats = {};
    sorted.forEach(m => {
      const prefix = m.get('DelayAreaAssetId') === 1000 ? 'C1 ' : 'C2 ';
      const cat    = m.get('DelayCategoryName');
      const col    = m.get('DelayCategoryColor') || '#888';
      cats[cat]    = { prefix, color: col };

      labels.push(prefix + m.get('DelayCodeName'));
      values.push(m.get(metricField));
      colors.push(col);
    });
    const legendItems = _.map(cats, (info, cat) => ({
      text:        info.prefix + cat,
      fillStyle:   info.color,
      strokeStyle: info.color,
      hidden:      false,
      lineCap:     'round'
    }));

    // 6) redraw cause chart
    const chart = this.delayCodesChart;
    const ds    = chart.data.datasets[0];
    chart.data.labels                                  = labels;
    ds.data                                            = values;
    ds.backgroundColor                                 = colors;
    ds.borderColor                                     = colors;
    chart.options.plugins.legend.labels.generateLabels = () => legendItems;
    chart.options.scales.y.title = {
      display: true,
      text: this.currentMetric === 'minutes'
        ? 'Total Delay (min)'
        : 'Count'
    };
    chart.update();
  }
  catch(e) {
    console.error(e);
  }
},



      search_keypress: function (e) {
        if (e.keyCode === 13) {
          $('#search').blur();
          this.refreshBtn_click();
        }
      },
      refreshProcesses: function (options) {
        var that = this,
          attrs = this.model.toJSON(),
          opt = _.extend({}, options, { params: {}, });

        if ((opt.refresh == true) || (opt.reset == true)) {
          this.model.set('isLoading', true);
          that.agGridModule.showLoadingOverlay();  // Show loading overlay
        }

        this.itemsColl.fetch({
          ...attrs,
          refresh: true,
        });





      },
      refreshBtn_click: function (e) {
        try {
          var params = this.model.toJSON();
          app.router.navigate(
            app.router.resolveURL(
              app.router.currentModule,
              _.extend(
                {},
                params,
                {
                  start: new moment(params.start, 'YYYY-MM-DD').format('YYYYMMDD'),
                  end: new moment(params.end, 'YYYY-MM-DD').format('YYYYMMDD'),
                  shiftId: (params.shiftId == null || params.shiftId == "") ? '-' : params.shiftId,
                }
              ),
              false
            ),
            { trigger: false, }
          );

          this._refresh({
            reset: true,
            params: _.extend(
              {},
              params,
              {}
            ),
          });

          window.scrollTo(0, 0);
        }
        catch (Error) { console.error(Error.stack); }
      },

      //Common functions
      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 () {
        var that = this;
      },
      unbindViewScopedEvents: function () {

      },
      close: function () {
        this.options.state = app.view_states.closed;

        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 (viewParams) {
        try {
          this.refresh(viewParams);
        } catch (Error) { }
      },

    });

    Screen.Collections.Delays = Backbone.Collection.extend({
      isFetching: false,
      currentPage: 1,
      pageSize: 100,

      fixedParameters: [],

      fetch: function (params) {
        var that = this;
        var qp = new Core.Database.QueryParameters();
        options = params ? _.clone(params) : {};
        if (options.refresh) {
          this.resetPagination(true);
          this.fixedParameters = [
            { Name: '@Start', Type: 'DATE', Value: params.start },
            { Name: '@End', Type: 'DATE', Value: params.end },
            { Name: '@IncludeUndeclared', Type: 'INT', Value: 1 }, // TODO: Add select in the main site
            // Casters area root so EAF delays never aggregate into (or mislabel in) the caster pareto.
            { Name: '@DelayAreaAssetId', Type: 'INT', Value: 1 },
          ];
        }

        _.each(this.fixedParameters, function (qpParams) {
          qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
        });


        Core.Json.CallProcedure(
          app.DatabaseNames.MES + '.DEL.GetDelaysForPareto',
          qp,
          {
            onSuccess: function (resp) {
              try {

                if ((resp) && (resp.Table)) {
                  newColl = resp.Table;
                  var method = (options.refresh) ? 'set' : 'add';
                  that[method](newColl);
                  that.trigger('fetch', that, newColl);

                  if (newColl.length == 0 && method == 'add')
                    that.currentPage--;

                  that.isFetching = false;


                }
                else {
                  if ((resp) && (resp.Message)) {
                    console.error(new Error(resp.Message).stack);
                    app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000, });
                  }
                  else {
                    app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000, });
                    console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                  }
                }
              }
              catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            onFailure: function (resp) {
              console.error(resp);
            },
            Secured: true,
            Async: true,
          },
          app.ConnectionStrings.app
        );
        return this;
      },
      getNextPage: function (options) {
        if (!this.isFetching) {
          this.currentPage++;
          options = (_.isObject(options)) ? options : {};
          this.fetch(options);
        }
      },
      resetPagination: function (force) {
        if (!this.isFetching || force == true) {
          this.currentPage = 1;
        } else {
          _.delay(this.resetPagination, 100);
        }
      },

    });



    return Screen;
  });