
define([   
    'app',
    'js/templates-loader',
    'moment',
    'components/ag-grid/ag-grid-module',
    'components/modal-covers/modal-assign-cover',
    'components/modal-temperatures-history/modal-temperatures-history',
],
    function (app, T, moment, AgGridModule, AssignCoverModal, TemperaturesHistoryModal) {

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

        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                screenTitle: 'Covers Report',
                start: new moment().subtract(2, 'days').format('YYYY-MM-DD'),
                end: new moment().format('YYYY-MM-DD'),               
                isLoading: false,
                isLoadingRt: false,
                remainingSeconds: 1,
                refreshIn: 'Refresh IN 1',
                renderCompleted: 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.columnDefs = options.columnDefs.map(colDef => {
                    if (colDef.field === 'Status') {
                        colDef.cellRenderer = this.statusCellRenderer;
                    }
                    return colDef;
                });
                AgGridModule.prototype.initialize.call(this, options);
            },
        
            formatStatusColumn: function() {
                this.columnDefs = this.columnDefs.map(colDef => {
                    if (colDef.field === 'Status') {
                        return {
                            ...colDef,
                            cellRenderer: this.statusCellRenderer
                        };
                    }
                    return colDef;
                });
            },

            editCellRenderer: function(params) {
                return `<i class="fa fa-pencil edit-icon edit-button" 
                style="cursor: pointer; color: #007bff;" 
                data-row-id="${params.node.id}" 
                data-row="${encodeURIComponent(JSON.stringify(params.data))}">
            </i>`;
            },
        
            statusCellRenderer: function(params) {
                const value = params.value;
                let statusClass = '';
                let statusText = '';
        
                if (value === 'L' || value === 'Lost') {
                    statusClass = 'bg-red-500 text-white';
                    statusText = 'LOST';
                } else if (value === 'G' || value === 'Good') {
                    statusClass = 'bg-green-500 text-white';
                    statusText = 'GOOD';
                }
        
                return `<div class="flex justify-center mt-2">
                <span class="px-2 py-1 rounded-full text-xs font-semibold ${statusClass} w-16 text-center">
                  ${statusText}
                </span>
              </div>`;
            },
            getGridApi: function () {
                return AgGridModule.prototype.getGridApi.call(this);
            }
        });


        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'covers-report',
            id: 'covers-report',
            title: 'Covers Report',
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click #refreshBtnRt': this.refreshBtnRt_click,
                    'click #calendarStartBtn': function() { $('#dateStartTbx').datepicker('show'); },
                    'click #calendarEndBtn': function() { $('#dateEndTbx').datepicker('show'); },
                    'click .edit-button': this.editCoverBtn_click,
                    'click #assignCoverBtn': this.assignCoverBtn_click,
                    'click .history-temps': this.showHistoryTemps,
                   
                };
            },
            refreshInterval : 10,
            bindings: 'data-bind',
            bindingSources: {},
            itemsColl: [],
            ItemsCollRealTime: [],
            subviews: {},
            viewParams: null,           
            isPaused: false,            
            AssignCoverModal : {},
            columns : [
                { field: 'CoverNumber', headerName: 'Cover', flex: 1, showFilter: true },
                { field: 'HeatNumber', headerName: 'Heat', flex: 1, showFilter: true },
                { field: 'Started', headerName: 'Started', flex: 1, showFilter: false ,fieldType: 'Datetime', format:'MM/DD HH:mm'},
                { field: 'Ended', headerName: 'Ended', flex: 1, showFilter: false ,fieldType: 'Datetime', format:'MM/DD HH:mm'},
                { field: 'TimeUnderCover', headerName: 'Under Cover', flex: 1,minWidth: 150, showFilter: false ,  cellRenderer: function(params) {
                    const value = params.value;
                    const hours = Math.floor(value / 3600);
                    const minutes = Math.floor((value % 3600) / 60);
                    const seconds = value % 60;
                    return `${hours}h ${minutes}m ${seconds}s`;
                }},
            ],         
            columnsRt : [
                { field: 'CoverNumber', headerName: 'Cover', flex: 1, showFilter: false, rowGroup: true ,},
                { field: 'HeatNumber', headerName: 'Heat', flex: 1, showFilter: true },
                { field: 'Started', headerName: 'Started', flex: 1, showFilter: false,  fieldType: 'Datetime', format:'MM/DD HH:mm' },
                { field: 'TimeUnderCover', headerName: 'Under Cover', flex: 1,minWidth: 150, showFilter: false ,  cellRenderer: function(params) {
                    const value = params.value;
                    const hours = Math.floor(value / 3600);
                    const minutes = Math.floor((value % 3600) / 60);
                    const seconds = value % 60;
                    return `${hours}h ${minutes}m ${seconds}s`;
                }},
                { field: 'TempSensor1', headerName: 'S. A', flex: 1, showFilter: false },
                { field: 'TempSensor2', headerName: 'S. B', flex: 1, showFilter: false },
                { field: 'Status', headerName: 'Status', flex: 1, showFilter: false },
                { field: 'PeakTemperature', headerName: 'Peak', flex: 1, showFilter: false },
                { field: '', headerName: '', maxWidth: 60, showFilter: false,fieldType: 'edit' },
                { field: '', headerName: '', maxWidth: 60, showFilter: false, cellRenderer: function(params) {
                    return `<i class="fa fa-area-chart history-temps" 
                                    style="cursor: pointer; color: #007bff;" 
                                    data-row-id="${params.node.id}" 
                                    data-row="${encodeURIComponent(JSON.stringify(params.data))}">
                                </i>`;
                } },
            ],           
            initialize: function () {
                var that = this;
                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.agGridModule = new AgGridModule({
                    columnDefs: this.columns,
                    rowData: [],
                    fileName:'covers-report'
                });

                var gridOptionsAgGridRT = {
                    autoGroupColumnDef: {
                        headerName: 'Cover',
                        cellRenderer: 'agGroupCellRenderer',
                        field: 'CoverNumber',
                    },
                    groupDisplayType: 'groupRows' // Grouping rows dynamically
                };

                this.agGridModuleRt = new CustomAgGridModule({
                    columnDefs: this.columnsRt,
                    rowData: [],
                    fileName:'covers-report-rt',
                    pagination:'hidden',
                    gridOptions: gridOptionsAgGridRT
                });

                this.itemsColl = new Screen.Collections.Items();
                this.ItemsCollRealTime = new Screen.Collections.ItemsRealTime();
                
                this.autoRefresh = {
                    enabled: false
                    , toid: null
                    , every: 1000 
                },
                this.model.set({
                    remainingSeconds: that.refreshInterval,
                    refreshIn: `Refresh In ${that.refreshInterval}`
                });
                this.bindEvents();
            },

            bindEvents: function () {
                this.listenTo(this.itemsColl, 'fetch', this.collection_ready);
                this.listenTo(this.ItemsCollRealTime, 'fetch', this.collection_rt_ready);                
            },

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

                this.viewParams = viewParams;

                
                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) {
                                //storing internationalization data
                                that.options.i18n[that.template] = i18nJED;

                                //loading the view and appeding it to the views's $el.
                                that.$el.html(tmp());

                                that.applyBindings();

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


                                // Render the AgGridModule and append it to the container
                                that.agGridModule.render();
                                that.$el.find('.grid-container').append(that.agGridModule.$el);

                                // Render the AgGridModule and append it to the container
                                that.agGridModuleRt.render();
                                that.$el.find('.grid-container-rt').append(that.agGridModuleRt.$el);
                                
                                
                                                               
                                //appending view to the main container
                                that.append(thatContainer, that.$el);

                                //Set model with view params here to prevent changes on the model when the view bindings are applied.
                                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');
                               
                                that.model.set(fixedParams);

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

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

                                that._refreshRt({
                                    reset: true,
                                    params: _.extend(
                                        {},
                                        params,
                                        {
                                        }
                                    ),
                                });
                                that.startAutoRefresh();
                                that.refreshProcessesRt();
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            // ------------------------
            // -------- History -------
            // ------------------------
            refresh: function (viewParams) {

                var fixedParams = _.extend({}, Screen.Models.Main.prototype.defaults, viewParams);

                if (viewParams.start)
                    fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.end)
                    fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
    
                this.model.set(fixedParams);

                this._refresh({
                    reset: true,
                    params: _.extend(
                        {},
                        fixedParams,
                        {}
                    ),
                });
            },
     
            _refresh: function (opt) {
                this.itemsColl.reset();
                this.refreshProcesses(opt);
            },
            collection_ready: function () {
                try {
                    var that = this;
                    const collectionData = that.itemsColl;
                    setTimeout(
                        function () {
                            that.agGridModule.setRowDataAsCollection(collectionData);
                            that.agGridModule.hideOverlay();                              
                            that.model.set({
                                isLoading: false
                            });                      
                        },
                        100
                    );
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            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({
                    start: attrs.start,
                    end: attrs.end
                });

            },
        
            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'),                                  
                                }
                            ),
                            false
                        ),
                        { trigger: false, }
                    );

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

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



            
            // --------------------------
            // -------- Real-Time -------
            // --------------------------
            resumeAutoRefresh: function() {
                this.isPaused = false;
                this._refreshRt(); // Immediately trigger a refresh
            },
            _refreshRt: function (opt) {
                var that = this;
                var currentSeconds = this.model.get('remainingSeconds');
            
                // Check if paused
                if (this.isPaused) {
                    // If paused, just reschedule the next check without changing anything
                    if (this.autoRefresh.enabled == true) {
                        if (this.autoRefresh.toid != null) {
                            clearTimeout(this.autoRefresh.toid);
                        }
                        this.autoRefresh.toid = setTimeout(
                            function () {
                                that._refreshRt();
                            },
                            this.autoRefresh.every // Run every 1 second
                        );
                    }
                    return; // Exit the function early if paused
                }
            
                // If not paused, proceed with normal refresh logic
                
                // Decrement the countdown
                currentSeconds = (currentSeconds > 0) ? currentSeconds - 1 : this.refreshInterval - 1;
                
                this.model.set({
                    remainingSeconds: currentSeconds,
                    refreshIn: `Refresh In ${currentSeconds}`
                });
            
                // Check if it's time to refresh the data (every 10 seconds)
                if (currentSeconds % 10 === 0 || opt) {
                    this.model.set({
                        refreshIn: `Refresh In ${10}`
                    });
            
                    this.ItemsCollRealTime.reset();
                    this.refreshProcessesRt(opt);
                    this.model.set('isLoadingRt', true);
                }
            
                // Schedule the next update
                if (this.autoRefresh.enabled == true) {
                    if (this.autoRefresh.toid != null) {
                        clearTimeout(this.autoRefresh.toid);
                    }
                    this.autoRefresh.toid = setTimeout(
                        function () {
                            that._refreshRt();
                        },
                        this.autoRefresh.every // Run every 1 second
                    );
                }
            },
                     
            collection_rt_ready: function () {
                    var that = this;
                    that.agGridModuleRt.gridReadyPromise.then(() =>{

                        // Step 1: Track expanded group keys
                    var expandedGroupKeys = [];
                    that.agGridModuleRt.gridApi.forEachNode(function (node) {
                        if (node.expanded) {
                            expandedGroupKeys.push(node.key);
                        }
                    });
            
                    const collectionData = that.ItemsCollRealTime;
                    setTimeout(function () {
                        // Step 2: Refresh grid with new data
                        that.agGridModuleRt.setRowDataAsCollection(collectionData);
                        that.agGridModuleRt.hideOverlay();
            
                        // Step 3: Reapply the expanded state
                        that.agGridModuleRt.gridApi.forEachNode(function (node) {
                            if (expandedGroupKeys.includes(node.key)) {
                                node.setExpanded(true);
                            }
                        });
            
                        that.model.set({
                            isLoadingRt: false
                        });
                    }, 100);
                        
                        console.log("Grid is Ready");
                    }).catch(() => {
                        console.error("Grid is not ready");
                    });
                    
                   
            },
            
                           
            refreshProcessesRt: function (options) {
                var that = this,
                    attrs = this.model.toJSON(),
                    opt = _.extend({}, options, { params: {}, });
                if ((opt.refresh == true) || (opt.reset == true)) {
                    this.model.set('isLoadingRt', true);
                    that.agGridModuleRt.showLoadingOverlay();  // Show loading overlay
                }

                this.ItemsCollRealTime.fetch({
                    start: attrs.start,
                    end: attrs.end
                });

            },

            refreshBtnRt_click: function (e) {
                try {
                    var params = this.model.toJSON();
                    
                    // Reset the countdown to 10
                    this.model.set({
                        remainingSeconds: 10,
                        refreshIn: 'Refresh In 10'
                    });


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

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



            // Auto Refresh
            
            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._refreshRt(); },
                            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;
            },
    

            // ---------------------------------
            // -------- Common functions -------
            // ---------------------------------

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

                    setTimeout(function() {
                        that.model.set({renderCompleted: true});
                    }, 1000);  
                }

                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 (viewParams) {
                try {
                    this.refresh(viewParams);
                } catch (Error) { }
            },
            editCoverBtn_click: function(event) {
                var that = this;
                this.isPaused = true; // Set isPaused to true when opening the modal

                var button = $(event.currentTarget);
                var rowData = button.data('row');
                var parsedRowData = JSON.parse(decodeURIComponent(rowData));
                var data = [];

                // If the cover has a heat assigned : unassignModal else AssignModal 
                if(parsedRowData.HeatNumber){
                    data = {
                        CoverNumber: parsedRowData.CoverNumber,
                        HeatNumber: parsedRowData.HeatNumber,
                        action: 'U'
                    };
                    this.AssignCoverModal = new AssignCoverModal.Views.UnassignCover({
                         parent: this,
                         data: data,
                         rowModel: null,
                         bus: null,
                     });
                    
                }
                else {
                    data = {
                        CoverNumber: parsedRowData.CoverNumber,
                        action: 'A'
                    };
                    this.AssignCoverModal = new AssignCoverModal.Views.AssignHeatCover({
                         parent: this,
                         data: data,
                         rowModel: null,
                         bus: null,
                     });
                }

                this.listenTo(that.AssignCoverModal, 'close', function () {
                    try {
                        that.resumeAutoRefresh();
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                });
                this.AssignCoverModal.show();
            },
            assignCoverBtn_click: function() {
                var that = this;
                this.AssignCoverModal = new AssignCoverModal.Views.AssignHeatCover({
                    parent: this,
                    data: null,
                    rowModel: null,
                    bus: null,
                });
                this.listenTo(that.AssignCoverModal, 'close', function () {
                    try {
                        that.resumeAutoRefresh();
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                });
                this.AssignCoverModal.show();

            },
            showHistoryTemps: function(event) {
                var that = this;
                this.isPaused = true; // Set isPaused to true when opening the modal

                var button = $(event.currentTarget);
                var rowData = button.data('row');
                var parsedRowData = JSON.parse(decodeURIComponent(rowData));
                var modal = new TemperaturesHistoryModal.Views.TemperaturesHistoryModal(
                    {data: parsedRowData
                    }
                );
                modal.show();
            }
        });

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

                var fixedParameters = [
                    { Name: '@Start', Type: 'DATETIME', Value: params.start, },
                    { Name: '@End', Type: 'DATETIME', Value: params.end, }
                ];
                _.each(fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });


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

                                if ((resp) && (resp.Table)) {                                    
                                    that.set(resp.Table);
                                    that.trigger('fetch', that,resp.Table);
                                }
                                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;
            },

        });

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

                var fixedParameters = [
                    { Name: '@Start', Type: 'DATETIME', Value: params.start, },
                    { Name: '@End', Type: 'DATETIME', Value: params.end, },
                    { Name: '@RealTime', Type: 'BIT', Value: 1, }
                ];
                _.each(fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });


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

                                if ((resp) && (resp.Table)) {                             
                                    that.set(resp.Table);
                                    that.trigger('fetch', that,resp.Table);
                                }
                                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;
            },

        });

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