//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/navigation-buttons/navigation-buttons',
    'backgrid/moment-cell',
    'js/autocomplete/backbone.autocomplete',
    'backgrid/grouped-columns',

    "js/jquery.floatThead/jquery.floatThead",
    'js/multiselect/virtual-select.min',

],
    function (app, T, Backgrid, moment, NavigationButton) {

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


        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                furnaceCodes: [{ label: 'A', value: 1 }, { label: 'B', value: 2 }],
                furnaceCode: 1,

                //URL parameters

                heatName: null,
                gradeName: '-',
                time: '-',
                hasData_process: false,
                isLoading_process: true,

                heatId: null,
                direction: null,
                navigation: null,
                heatNames: [],
                enterPress: false,

                appendGrid: true,

                hideExcelBtn: true,
                hideNavitaionBtns: true,
                realTimeData:true,
            },
            computeds: {
                hasData: {
                    deps: ['hasData_process'],
                    get: function (process) {
                        return process;
                    },
                },
                isLoading: {
                    deps: ['isLoading_process'],
                    get: function (process) {
                        return process;
                    },
                },
            },
            initialize: function () {
                this.labGridCollection = new Screen.Collections.LabGrid();
                this.limitsCompare = null;
            },
            fetchCatalogs: function () {
                var that = this;
                var qp = new Core.Database.QueryParameters();
                qp.Add('@HeatName', 'VARCHAR(10)', that.get('heatName'));
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.LAB.GetAutocompleteHeats',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    if (resp.Table) {
                                        that.set({
                                            heatNames: resp.Table,
                                            heatName: resp.Table[0] && resp.Table[0].value ? resp.Table[0].value : '',
                                        });
                                    }
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                        console.error(resp.Message);
                                        that.set({
                                            hasData_process: false,
                                            isLoading_process: false,


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

                                }


                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                        Secured: true,
                        Async: false,
                    },
                    app.ConnectionStrings.app
                );
            },
            fetch: function () {
                var that = this;
                var qp = new Core.Database.QueryParameters();
                var grade = '-';
                qp.Add('@timeZoneCode', 'CHAR(10)', app.models.user.get('timezoneCode'));
                qp.Add('@HeatName', 'VARCHAR(10)', that.get('heatName'));
                qp.Add('@getRealTimeData', 'BIT', that.get('heatName') ? false : true);
                that.set({
                    realTimeData: that.get('heatName') ? false : true,
                });
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.LAB.GetChemistrySamplesWithCalculatedByHeat',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    grade = resp.Table3 && resp.Table3[0] && resp.Table3[0].GradeName ? resp.Table3[0].GradeName : '-';

                                    that.set({
                                        gradeName: 'Grade: ' + grade,
                                    })

                                    if (resp.Table4) that.trigger('fetch-nav-buttons', resp.Table4);
                                    that.trigger('buildGrid', resp.Table, resp.Table1, resp.Table2,resp.Table5);
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                        console.error(resp.Message);
                                        that.set({
                                            hasData_process: false,
                                            isLoading_process: false,
                                        });
                                    }
                                    else {
                                        app.views.topMessages.showMessage("Server response not valid.", { stay: 5000, });
                                        console.error("Server response not valid.");
                                        that.set({
                                            hasData_process: false,
                                            isLoading_process: false,
                                        });
                                    }

                                }


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

                return this;

            },

        });

        Screen.Collections.LabGrid = Backbone.Collection.extend({
            setDataColl: function (data) {
                this.set(data).trigger('fetch', data);
            }
        });
        Screen.generateID = function (viewParams) {
            try {
                //if the viewparams change the view id, then evaluate the viewparams here
                //and return the appropiate id.refreshbtn
                return 'lab-real-time';
            } catch (Error) { }
        }

        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'lab-real-time',
            id: 'lab-real-time',
            title: 'Lab Heat Report',
            isCacheable: false,
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click #goRealTimeBtn': this.goRealTimeBtn_click,
                };
            },
            bindings: 'data-bind',
            subviews: null,
            viewParams: null,
            labGrid: [],

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


                this.NavigationButtonView = new NavigationButton.Views.Main();

                var that = this;
                this.model = new Screen.Models.Main();
                this.autoRefresh = {
                    enabled: null
                    , toid: null
                    , every: 15 * 1000
                };

                this.bindEvents();

            },
            bindEvents: function () {
                this.listenTo(this.model.labGridCollection, 'fetch', this.process_fetched);
                this.listenTo(this.model, 'buildGrid', this.buildGrid);
                this.listenTo(this.model, 'fetch-nav-buttons', this.fetchnavbuttons);
            },

            fetchnavbuttons: function (resp) {
                this.NavigationButtonView.setDataColl(resp);
            },
            goRealTimeBtn_click: function () {
                var that = this;
                this.model.set({
                    heatName: null,
                    heatNames: [],
                });
                document.querySelector('#heat-picker-multi-select').setOptions([]);
                document.querySelector('#heat-picker-multi-select').setValue(null);
                this.UpdateURL();
                this.refresh();
            },
            buildGrid: function (chemistriesTable, elementOrderTable, sampleTimesTable, limitsByGrade) {
                var that = this;
                if (chemistriesTable.length === 0) {
                    this.model.set({
                        hasData_process: false,
                        isLoading_process: false,
                    });
                    this.UpdateURL();
                    return;
                }
                this.$el.find('.lab-real-time-grid-container').html('');
                var keys = null,
                    columnsName = [];
                this.model.set({
                    appendGrid: false,
                });

                var newTable = [];
                var completeTable = [];
                var limits = [];
                var model = null;

                var chemistries = [];
                //First we push into "newTable" the chemistries with an order number
                _.each(elementOrderTable, function (obj) {
                    chemistries = _.findWhere(chemistriesTable, { Code: obj.Code });
                    if (chemistries) {
                        newTable.push($.extend(obj, chemistries));
                    }
                });

                //Then we push into "newTable" the chemistries with out an order number
                _.each(chemistriesTable, function (obj) {
                    elementOrder = _.findWhere(elementOrderTable, { Code: obj.Code });
                    if (!elementOrder) {
                        elementOrder = { Code: obj.Code, Min: null, Aim: null, Max: null };
                        newTable.push($.extend(obj, elementOrder));
                    }

                });
                if (newTable && newTable[0]) {
                    columnsName = [];
                    keys = Object.keys(newTable[0]);
                    var timeRow = {};
                    var commentsRow = {};
                    var sample = [];
                    var order = [];
                    order.push("Code");

                    var element = [];
                    _.each(keys, function (obj, i) {
                        sample = _.findWhere(sampleTimesTable, { HeatTypeSample: obj });
                        if (obj === 'Code') {
                            timeRow[obj] = 'Datetime';
                            commentsRow[obj] = 'Comments';
                        } else if (sample) {
                            timeRow[obj] = new moment(sample.Timestamp).format('MM/DD/YYYY HH:mm:ss');
                            commentsRow[obj] = sample.Comments;
                        } else {
                            timeRow[obj] = '-';
                            commentsRow[obj] = '-';
                        }
                        element = _.findWhere(sampleTimesTable, { rn: i });
                        if (element) {
                            order.push(element.HeatTypeSample);
                        }
                    });

                    if (!this.model.get('realTimeData')) {
                        order.push("Min");
                        order.push("Aim");
                        order.push("Max");
                    }
                    completeTable.push(timeRow);
                    completeTable.push(commentsRow);
                    _.each(newTable, function (obj) {
                        completeTable.push(obj);
                    });

                    //var completeTableOrdered = JSON.parse(JSON.stringify(completeTable, order, 4));
                    var completeTableOrdered = JSON.parse(JSON.stringify(completeTable));
                    this.model.labGridCollection.reset();
                    this.model.labGridCollection.setDataColl(completeTableOrdered);
                    var matchKeys = [];
                    var currentKey = null;


                    // variables for limits purposes
                    var currentColumn = null;
                    var currentRow = null;
                    var currentValue = null;
                    var currentLimits = null;
                    var min = null;
                    var aim = null;
                    var max = null;
                    var currenttd = null;
                    var AuxCurrentlimits = null;

                    var keyOrder = null;
                    _.each(keys, function (obj, i) {
                        keyOrder = order[i];
                        matchKeys.push({ obj: obj, keyOrder: keyOrder });
                        if (keyOrder) {
                            columnsName.push({
                                "name": keyOrder,
                                "editable": false,
                                "label": keyOrder === 'Code' ? '' : keyOrder,
                                "cell": Backgrid.StringCell.extend({
                                    className: function () {
                                        currentKey = _.findWhere(matchKeys, { obj: obj });
                                        if (currentKey.keyOrder != 'Min' && currentKey.keyOrder != 'Max' && currentKey.keyOrder != 'Aim' && currentKey.keyOrder != 'Code') {
                                            model = this.model.toJSON();
                                            if (model.Code === 'Datetime' || model.Code === 'Comments') {
                                                return 'string-cell align-center-cell no-editable';
                                            } else {
                                                currentColumn   = currentKey.keyOrder;
                                                currentRow      = model.Code;
                                                currentValue    = model[currentKey.keyOrder];
                                                currentLimits   = _.findWhere(limitsByGrade, { HeatTypeSample: currentColumn, Code: currentRow });                                            
                                                if (!currentLimits) {
                                                    AuxCurrentlimits = {
                                                        Aim: model.Aim,
                                                        Code: model.Code,
                                                        GradeName: '-',
                                                        HeatTypeSample: currentColumn,
                                                        Max: model.Max,
                                                        Min: model.Min,                                                        
                                                    }
                                                   return that.getElementClass(currentValue, model.Min, model.Max, AuxCurrentlimits);
                                                }
                                                if (currentLimits) {
                                                    min = currentLimits.Min ? currentLimits.Min : '-';
                                                    max = currentLimits.Max ? currentLimits.Max : '-';
                                                    return that.getElementClass(currentValue, min, max, currentLimits);

                                                }
                                                
                                                else {
                                                    return 'string-cell align-center-cell';
                                                }
                                            }
                                        }
                                        else return 'string-cell align-center-cell no-editable';
                                    }
                                }),
                            });
                        }
                    });
                    var columnLayout = [];
                    _.each(keys, function (obj) {
                        if (obj != 'Code') {
                            columnLayout.push({ 'name': obj });
                        }
                    });
                    if (!this.model.get('realTimeData')) {
                        columnLayout.push({
                            name: that.model.get('gradeName'), children:
                                [
                                    { name: 'Min' }
                                    , { name: 'Aim' }
                                    , { name: 'Max' }
                                ]
                        })
                    };
                    that.labGrid = new Backgrid.Grid({
                        className: 'backgrid table table-hover table-condensed samples-table',
                        header: Backgrid.Extension.GroupedHeader.extend({
                            columnLayout: columnLayout,
                            initialize: function (options) {
                                Backgrid.Extension.GroupedHeader.prototype.initialize.apply(this, arguments);
                            },
                            render: function () {
                                var that = this;
                                Backgrid.Extension.GroupedHeader.prototype.render.apply(this, arguments);
                                return this;
                            },
                        }),
                        columns: columnsName,
                        row: Backgrid.Row.extend({
                            initialize: function (options) {
                                Backgrid.Row.prototype.initialize.apply(this, arguments);
                            },
                        }),
                        collection: that.model.labGridCollection,
                    });
                    that.$el.find('.lab-real-time-grid-container').append(that.labGrid.render().el);
                    that.model.set({ labGrid: that.labGrid });
                    this.model.set({
                        hasData_process: true,
                        isLoading_process: false,
                    })
                }

                that.setFixedHeader();
                that.setTooltip();

            },

            setFixedHeader: function () {
                var container = this.$el.find(".lab-real-time-grid-container");
                var table = container.find(".samples-table")
                table.floatThead({
                    scrollingTop: function () {
                        try {
                            return $(".fixed-subnavbar").height() + ($("header").height() / 2);
                        } catch (error) { return 111; }
                    },
                    zIndex: 500,
                    useAbsolutePositioning: false,
                });

            },
            setTooltip: function () {
                var gridElement = document.getElementById('lab-real-time-grid');
                var aTags = gridElement.getElementsByTagName("td");   
                var tooltipText = null;
                for (const element of aTags) {
                    tooltipText = $(element).attr("class").substring(
                        $(element).attr("class").indexOf("*") + 1,
                        $(element).attr("class").lastIndexOf("*")
                    );
                   
                    $(element).attr("title", tooltipText);
                    $(element).css("cursor", "pointer");
                }

                
            },

            render: function (container, urlParams) {
                var that = this;
                var thatContainer = (this.options.container) ? this.options.container : container;
                this.options.container = thatContainer;

                this.viewParams = urlParams;

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

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

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

                                that.applyBindings();

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

                                //rendering Navigation Buttons
                                that.NavigationButtonView.render(that.$el.find(".navigation-buttons"), null);


                                var fixedParams = _.extend({}, urlParams);
                                if (fixedParams && fixedParams.heatName && fixedParams.heatName.length === 7) {
                                    that.model.set(fixedParams);
                                } else {
                                    that.UpdateURL();
                                }
                                that.model.fetchCatalogs();

                                that.renderMultipicker();

                                that.refresh();
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            renderMultipicker: function () {
                var that = this;
                var heatNamesPicker = new VirtualSelect.init({
                    ele: '#heat-picker-multi-select',
                    options: that.model.get('heatNames'),
                    multiple: false,
                    search: true,
                    placeholder: 'Select Heat',
                    hasOptionDescription: false,
                    showSelectedOptionsFirst: true,
                    hideClearButton: true,
                    onServerSearch: that.onSampleSelectServerSearch,
                });
                var heat = that.model.get('heatName');
                document.querySelector('#heat-picker-multi-select').setOptions(that.model.get('heatNames'));
                document.querySelector('#heat-picker-multi-select').setValue(heat);
                document.querySelector('#heat-picker-multi-select').addEventListener('change', function () {
                    $('.vscomp-search-clear').click();
                    if (this.value === that.model.get('heatName')) {
                        return 0;
                    }
                    else {
                        var newHeatName = this.value;
                        if (newHeatName && newHeatName != '') {
                            that.model.set({
                                heatName: newHeatName
                            });
                            that.UpdateURL();
                            that.refresh();
                        }
                    }
                });

            },

            onSampleSelectServerSearch: function (searchValue, virtualSelect) {
                var qp = new Core.Database.QueryParameters();
                qp.Add('@HeatName', 'VARCHAR(10)', searchValue);
                qp.Add('@SelectedHeatName', 'VARCHAR(10)', this.selectedValues[0]);
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.LAB.GetAutocompleteHeats',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                virtualSelect.setServerOptions(resp.Table);

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

            UpdateURL: function () {
                try {
                    var params = this.model.toJSON();
                    app.router.navigate('!/lab-real-time/' + (params.heatName ? params.heatName : ''), { trigger: false });
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            getElementClass: function (value, min, max, currentLimits) {
                var textMin = currentLimits.Min ? 'Min: ' + currentLimits.Min : 'Min: - ';
                var textAim = currentLimits.Aim ? 'Aim: ' + currentLimits.Aim : 'Aim: - ';  
                var textMax = currentLimits.Max ? 'Max: ' + currentLimits.Max : 'Max: - ';
                var textGrade = currentLimits.GradeName ? 'Grade: ' + currentLimits.GradeName : 'Grade: - '
                var text = '*' + textGrade + ' | ' + textMin + ' | ' + textAim + ' | ' + textMax +'*';
                if (min === '-') min = null;
                if (max === '-') max = null;
                if (value === '-')
                    return 'string-cell align-center-cell no-editable ' + text;
                if (value === null)
                    return 'string-cell align-center-cell ' + text;
                if (!min && !max)
                    return 'string-cell align-center-cell ok ' + text;
                if (value != null && min && value < min)
                    return 'string-cell align-center-cell warning ' + text;
                if (value != null && max && value > max)
                    return 'string-cell align-center-cell danger ' + text;;
                if (value != null && max && !min && value <= max)
                    return 'string-cell align-center-cell ok ' + text;
                if (value != null && min && !max && value >= min)
                    return 'string-cell align-center-cell ok ' + text;
                if (value != null && min && max && value >= min && value <= max)
                    return 'string-cell align-center-cell ok ' + text;


            },

            warningElementCodeValue: function (element, value) {
                var that = this,
                    min = null,
                    max = null;
                var limits = _.findWhere(that.model.limitsCompare, { Code: element });

                if (limits) {
                    min = limits.Min;
                    max = limits.Max;
                }
                if (value == '-') value = null;

                if (!value)
                    return 'string-cell align-center-cell';
                if (!min && !max)
                    return 'string-cell align-center-cell ok';
                if (value && min && value < min)
                    return 'string-cell align-center-cell warning';
                if (value && max && value > max)
                    return 'string-cell align-center-cell danger';
                if (value && max && !min && value <= max)
                    return 'string-cell align-center-cell ok';
                if (value && min && !max && value >= min)
                    return 'string-cell align-center-cell ok';
                if (value && min && max && value >= min && value <= max)
                    return 'string-cell align-center-cell ok';


            },

            refresh: function () {
                this.model.set({
                    hasData_process: false,
                    isLoading_process: true,
                })
                this.$el.find('.lab-real-time-grid-container').html('');
                this.model.fetch();

            },
            process_fetched: function () {
                try {
                    var that = this;
                    this.pauseTimer = false;
                    setTimeout(
                        function () {
                            that.model.set({
                                hasData_process: (that.model.labGridCollection.length > 0),
                                isLoading_process: false,
                            });

                        },
                        100
                    );

                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

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

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

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

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

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

                        this.autoRefresh.enabled = true;

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

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

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

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

                    this.options.onappend(this);
                }

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

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

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

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

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

                this.hideSubviews();

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

        });


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

