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

define([
    'app',
    'js/templates-loader',
    'backbone',
    'moment',
    'components/ag-grid/ag-grid-module',
    'modules/navigation-buttons/navigation-buttons',
    'js/multiselect/virtual-select.min',
],
    function (app, T, Backbone, moment, AgGridModule, NavigationButton) {

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

        var ASSET = 'EAF';

        // ---------------------------------------------------------------
        // Model
        // Keeps compatibility with the legacy `heatName` URL param and
        // the 3-result-set shape of MES.GetThermalProfile:
        //   Table  = readings time series
        //   Table1 = single-row heat summary
        //   Table2 = nearby-heats nav badges
        // ---------------------------------------------------------------
        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                hasData: false,
                isLoading: false,

                // Heat picker state
                heatName: null,
                heatNames: [],

                // Headline + KPI strings (all display-formatted)
                ladleText:       '-',
                heatNameText:    '-',
                liquidusText:    '-',
                ladleCloseText:  '-',
                startTapText:    '-',
                heatsText:       '-',
                contactText:     '-',
                mwhText:         '-',
                readingsCountText: '0',
            },
            initialize: function () {
                this.readingsColl = new Screen.Collections.ItemsColl();
                this.summaryColl  = new Screen.Collections.ItemsColl();
            },
            fetchNavigateHeat: function (direction) {
                var that = this;
                var qp = new Core.Database.QueryParameters();
                qp.Add('@heatName',  'VARCHAR(10)', that.get('heatName'));
                qp.Add('@direction', 'SMALLINT',    direction);
                qp.Add('@Asset',     'CHAR(3)',     ASSET);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.MES.GetNavigatedHeat',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table && resp.Table[0] && resp.Table[0].HeatName) {
                                    that.set({
                                        heatName:  resp.Table[0].HeatName,
                                        heatNames: [{ value: resp.Table[0].HeatName, label: resp.Table[0].HeatName }],
                                    });
                                    that.trigger('heat-name-changed');
                                } else {
                                    var msg = (resp && resp.Message) ? resp.Message : 'Server response not valid.';
                                    app.views.topMessages.showMessage(msg, { stay: 5000 });
                                    console.error(msg);
                                }
                            } catch (e) {
                                console.error((e.stack) ? e.stack : new Error(e).stack);
                            }
                        },
                        Secured: true,
                        Async:   false,
                    },
                    app.ConnectionStrings.app
                );
            },
            fetchCatalogs: function () {
                var that = this;
                var qp = new Core.Database.QueryParameters();
                qp.Add('@HeatName', 'VARCHAR(10)', that.get('heatName'));
                qp.Add('@Asset',    'CHAR(3)',    ASSET);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.MES.GetAutocompleteHeats',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.set({
                                        heatNames: resp.Table,
                                        heatName:  (resp.Table[0] && resp.Table[0].value) ? resp.Table[0].value : '',
                                    });
                                    that.trigger('catalogs-fetched');
                                } else {
                                    var msg = (resp && resp.Message) ? resp.Message : 'Server response not valid.';
                                    app.views.topMessages.showMessage(msg, { stay: 5000 });
                                    console.error(msg);
                                    that.set({ hasData: false, isLoading: false });
                                }
                            } catch (e) {
                                console.error((e.stack) ? e.stack : new Error(e).stack);
                            }
                        },
                        Secured: true,
                        Async:   false,
                    },
                    app.ConnectionStrings.app
                );
            },
            fetch: function () {
                var that = this;
                var qp = new Core.Database.QueryParameters();
                qp.Add('@heatName',     'VARCHAR',  that.get('heatName'));
                qp.Add('@timeZoneCode', 'CHAR(10)', app.models.user.get('timezoneCode'));

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.MES.GetThermalProfile',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.readingsColl.setDataColl(resp.Table);
                                    that.summaryColl.setDataColl(resp.Table1 || []);
                                    if (resp.Table2) that.trigger('fetch-nav-buttons', resp.Table2);
                                } else {
                                    var msg = (resp && resp.Message) ? resp.Message : 'Server response not valid.';
                                    app.views.topMessages.showMessage(msg, { stay: 5000 });
                                    console.error(msg);
                                    that.set({ hasData: false, isLoading: false });
                                }
                            } catch (e) {
                                console.error((e.stack) ? e.stack : new Error(e).stack);
                            }
                        },
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });

        // Stable screen id — URL param `heatName` shouldn't force a new view instance
        Screen.generateID = function () {
            return 'thermal-profile';
        };

        // ---------------------------------------------------------------
        // AG Grid column definitions for the readings time series
        // ---------------------------------------------------------------
        function buildReadingsColumnDefs(i18n) {
            var t = function (key, fallback) {
                try {
                    var v = i18n && i18n[key] && i18n[key][0];
                    return v || fallback;
                } catch (e) { return fallback; }
            };

            return [
                _.extend({
                    field: 'Timestamp', headerName: t('time_col', 'Time'),
                    fieldType: 'Datetime', format: 'HH:mm',
                    cellClass: 'text-center', headerClass: 'ag-header-cell-center',
                }, { flex: 0.9, minWidth: 90 }),
                _.extend({
                    field: 'Area', headerName: t('area_col', 'Area'),
                    cellClass: 'text-center', headerClass: 'ag-header-cell-center',
                }, { flex: 1.1, minWidth: 110 }),
                _.extend({
                    field: 'Temperature', headerName: t('temp_col', 'Temp'),
                    cellClass: 'text-right', headerClass: 'ag-header-cell-center',
                    cellStyle: { fontWeight: '600' },
                }, { flex: 0.9, minWidth: 80 }),
                _.extend({
                    field: 'TempDiff', headerName: t('temp_diff_col', 'Temp Diff'),
                    cellClass: 'text-right', headerClass: 'ag-header-cell-center',
                }, { flex: 0.9, minWidth: 80 }),
                _.extend({
                    field: 'TimeDiff', headerName: t('time_diff_col', 'Time Diff (min)'),
                    cellClass: 'text-right', headerClass: 'ag-header-cell-center',
                }, { flex: 1, minWidth: 100 }),
                _.extend({
                    field: 'Slope', headerName: t('slope_col', 'Slope (deg/min)'),
                    cellClass: 'text-right', headerClass: 'ag-header-cell-center',
                }, { flex: 1, minWidth: 110 }),
            ];
        }

        // ---------------------------------------------------------------
        // View
        // ---------------------------------------------------------------
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template:    'thermal-profile',
            id:          'thermal-profile',
            title:       'Thermal Profile',
            isCacheable: false,
            events: function () {
                return {
                    'click #refreshBtn':          this.refreshBtn_click,
                    'click .btn-export-to-excel': this.exportToExcel,
                    'click #backNavBtn':          this.heatNavigationBtn_click,
                    'click #forwardNavBtn':       this.heatNavigationBtn_click,
                };
            },
            bindings: 'data-bind',
            subviews: null,
            viewParams: null,

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

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

                this.subviews = {};
                this.NavigationButtonView = new NavigationButton.Views.Main();

                // Build AG Grid now; it will be mounted in render()
                this.agGridModule = new AgGridModule({
                    columnDefs:  [],
                    rowData:     [],
                    fileName:    'thermal-profile',
                    screenTitle: this.title,
                    pagination:  'hidden',
                    allowMultipleSelection: false,
                    suppressRowClickSelection: true,
                    gridOptions: {
                        wrapHeaderText:   true,
                        autoHeaderHeight: true,
                    },
                });

                this.bindEvents();
            },
            bindEvents: function () {
                this.listenTo(this.model.summaryColl,  'fetch', this.onSummaryReady)
                    .listenTo(this.model.readingsColl, 'fetch', this.onReadingsReady)
                    .listenTo(this.model, 'fetch-nav-buttons', this.onNavButtons)
                    .listenTo(this.model, 'heat-name-changed', this.onHeatNameChanged)
                    .listenTo(this.model, 'catalogs-fetched',  this.updateURL);
            },

            // -------------------------------------------------------------
            // Render
            // -------------------------------------------------------------
            render: function (container, urlParams) {
                var that = this;

                this.viewParams = urlParams;

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

                var customPath = '/app/pages/mes/' + this.template + '/';

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

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

                                // Mount AG Grid (with i18n-aware column defs)
                                var i18n = (i18nJED && i18nJED.options && i18nJED.options.locale_data && i18nJED.options.locale_data.messages) || {};
                                that.agGridModule.columnDefs = buildReadingsColumnDefs(i18n);
                                that.agGridModule.gridOptions.columnDefs = that.agGridModule.columnDefs;
                                that.agGridModule.render();
                                that.$el.find('#thermal-grid').append(that.agGridModule.$el);

                                // Nearby heats navigation badges
                                that.NavigationButtonView.render(that.$el.find('.navigation-buttons'), null);

                                // Append view
                                that.append(thatContainer, that.$el);

                                // URL params → model, then fetch catalogs + data
                                var fixedParams = _.extend({}, urlParams);
                                if (fixedParams && fixedParams.heatName && fixedParams.heatName.length === 7) {
                                    that.model.set(fixedParams);
                                } else {
                                    that.updateURL();
                                }
                                that.model.fetchCatalogs();

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

            // -------------------------------------------------------------
            // Heat picker (VirtualSelect with server-side autocomplete)
            // -------------------------------------------------------------
            renderHeatPicker: function () {
                var that = this;

                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.onHeatPickerServerSearch,
                });

                var picker = document.querySelector('#heat-picker-multi-select');
                picker.setOptions(that.model.get('heatNames'));
                picker.setValue(that.model.get('heatName'));

                picker.addEventListener('change', function () {
                    $('.vscomp-search-clear').click();
                    var newHeatName = this.value;
                    if (!newHeatName || newHeatName === that.model.get('heatName')) return;

                    that.model.set({ heatName: newHeatName });
                    that.refresh();
                    that.updateURL();
                });
            },
            onHeatPickerServerSearch: function (searchValue, virtualSelect) {
                // `this` is the VirtualSelect instance, not the Backbone view
                var qp = new Core.Database.QueryParameters();
                qp.Add('@HeatName',         'VARCHAR(10)', searchValue);
                qp.Add('@SelectedHeatName', 'VARCHAR(10)', this.selectedValues[0]);
                qp.Add('@Asset',            'CHAR(3)',     ASSET);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.MES.GetAutocompleteHeats',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try { virtualSelect.setServerOptions(resp.Table); }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        Secured: true,
                        Async:   false,
                    },
                    app.ConnectionStrings.app
                );
            },

            // -------------------------------------------------------------
            // Event handlers
            // -------------------------------------------------------------
            onHeatNameChanged: function () {
                var value   = this.model.get('heatName');
                var options = this.model.get('heatNames');
                var picker  = document.querySelector('#heat-picker-multi-select');
                if (picker) {
                    picker.setOptions(options);
                    picker.setValue(value);
                }
                this.updateURL();
                this.refresh();
            },
            onNavButtons: function (resp) {
                this.NavigationButtonView.setDataColl(resp);
            },
            heatNavigationBtn_click: function (e) {
                // The <i> icon can be the click target, so walk up to the button
                var target    = $(e.target).closest('button').get(0) || e.target;
                var direction = (target.id === 'backNavBtn') ? -1 : 1;
                this.model.fetchNavigateHeat(direction);
            },

            onSummaryReady: function (coll) {
                var that = this;
                setTimeout(function () {
                    try {
                        var row = coll.toJSON()[0] || {};
                        that.model.set({
                            ladleText:      row.LadleId != null ? String(row.LadleId) : '-',
                            heatNameText:   row.HeatName     || that.model.get('heatName') || '-',
                            liquidusText:   row.Liquidus != null ? String(row.Liquidus) : '-',
                            ladleCloseText: row.LadleClose ? moment(row.LadleClose).format('HH:mm') : '-',
                            startTapText:   row.StartTap   ? moment(row.StartTap).format('HH:mm')   : '-',
                            heatsText:      row.Heats   != null ? String(row.Heats)   : '-',
                            contactText:    row.Contact != null ? String(row.Contact) : '-',
                            mwhText:        row.MWH     != null ? String(row.MWH)     : '-',
                            hasData:        true,
                            isLoading:      false,
                        });
                    } catch (e) {
                        console.error((e.stack) ? e.stack : new Error(e).stack);
                    }
                }, 100);
            },
            onReadingsReady: function (coll) {
                var rows = coll.toJSON();
                if (this.agGridModule) {
                    this.agGridModule.gridReadyPromise.then(function () {
                        this.agGridModule.setRowData(rows);
                        this.agGridModule.hideOverlay();
                    }.bind(this)).catch(function () {});
                }
                this.model.set({ readingsCountText: rows.length + (rows.length === 1 ? ' reading' : ' readings') });
            },

            refresh: function () {
                this.model.set({ isLoading: true, hasData: false });
                if (this.agGridModule && this.agGridModule.showLoadingOverlay) {
                    this.agGridModule.gridReadyPromise.then(function () {
                        this.agGridModule.showLoadingOverlay();
                    }.bind(this)).catch(function () {});
                }
                this.model.fetch();
            },
            refreshBtn_click: function () {
                this.refresh();
                this.updateURL();
            },
            updateURL: function () {
                try {
                    var params = this.model.toJSON();
                    app.router.navigate(
                        app.router.resolveURL(
                            app.router.currentModule,
                            { heatName: params.heatName },
                            false
                        ),
                        { trigger: false }
                    );
                } catch (e) {
                    console.error((e.stack) ? e.stack : new Error(e).stack);
                }
            },

            // -------------------------------------------------------------
            // Excel export — 2 sheets: Summary (Table1) + Readings (Table)
            // Calls the same SP (MES.GetThermalProfile) with the same params
            // -------------------------------------------------------------
            exportToExcel: function () {
                var that  = this;
                var attrs = this.model.toJSON();

                if (!attrs.heatName) return;

                that.setExportButtonExporting(true);

                var params = [
                    { Name: '@heatName',     Type: 'VARCHAR',  Value: attrs.heatName },
                    { Name: '@timeZoneCode', Type: 'CHAR(10)', Value: app.models.user.get('timezoneCode') },
                ];
                var QP = new QueryParameters();
                _.each(params, function (p) { QP.Add(p.Name, p.Type, p.Value); });

                var readingsHeader = [
                    { Column: 'A', Value: 'Timestamp'   },
                    { Column: 'B', Value: 'Area'        },
                    { Column: 'C', Value: 'Temperature' },
                    { Column: 'D', Value: 'TempDiff'    },
                    { Column: 'E', Value: 'TimeDiff'    },
                    { Column: 'F', Value: 'Slope'       },
                ];
                var readingsCells = [
                    { ExcelColumnName: 'A', SQLDataColumnName: 'Timestamp',   DataType: 'String' },
                    { ExcelColumnName: 'B', SQLDataColumnName: 'Area',        DataType: 'String' },
                    { ExcelColumnName: 'C', SQLDataColumnName: 'Temperature', DataType: 'String' },
                    { ExcelColumnName: 'D', SQLDataColumnName: 'TempDiff',    DataType: 'String' },
                    { ExcelColumnName: 'E', SQLDataColumnName: 'TimeDiff',    DataType: 'String' },
                    { ExcelColumnName: 'F', SQLDataColumnName: 'Slope',       DataType: 'String' },
                ];

                var summaryHeader = [
                    { Column: 'A', Value: 'HeatName'   },
                    { Column: 'B', Value: 'LadleId'    },
                    { Column: 'C', Value: 'Liquidus'   },
                    { Column: 'D', Value: 'LadleClose' },
                    { Column: 'E', Value: 'StartTap'   },
                    { Column: 'F', Value: 'Heats'      },
                    { Column: 'G', Value: 'Contact'    },
                    { Column: 'H', Value: 'MWH'        },
                ];
                var summaryCells = [
                    { ExcelColumnName: 'A', SQLDataColumnName: 'HeatName',   DataType: 'String' },
                    { ExcelColumnName: 'B', SQLDataColumnName: 'LadleId',    DataType: 'String' },
                    { ExcelColumnName: 'C', SQLDataColumnName: 'Liquidus',   DataType: 'String' },
                    { ExcelColumnName: 'D', SQLDataColumnName: 'LadleClose', DataType: 'String' },
                    { ExcelColumnName: 'E', SQLDataColumnName: 'StartTap',   DataType: 'String' },
                    { ExcelColumnName: 'F', SQLDataColumnName: 'Heats',      DataType: 'String' },
                    { ExcelColumnName: 'G', SQLDataColumnName: 'Contact',    DataType: 'String' },
                    { ExcelColumnName: 'H', SQLDataColumnName: 'MWH',        DataType: 'String' },
                ];

                var data = {
                    Data: [
                        { SheetName: 'Summary',  RowsData: [{ CellsData: summaryHeader }],  StartRowIndex: 1 },
                        { SheetName: 'Summary',  RowsData: [], StartRowIndex: 2, DataSourceName: 'data', DataSourceTableIndex: 1, SQLCellsData: summaryCells },
                        { SheetName: 'Readings', RowsData: [{ CellsData: readingsHeader }], StartRowIndex: 1 },
                        { SheetName: 'Readings', RowsData: [], StartRowIndex: 2, DataSourceName: 'data', DataSourceTableIndex: 0, SQLCellsData: readingsCells },
                    ],
                    ConnectionStringName: 'APP',
                    ExportMethod: 3,
                    FileName: 'Thermal-Profile-' + attrs.heatName,
                    TemplateFileFullPath: 'generic.xls',
                    SQLDataSources: [
                        {
                            Name: 'data',
                            DatabaseParameters: {
                                DBEngine: 'SQLSERVER',
                                Procedure: app.DatabaseNames.MES + '.MES.GetThermalProfile',
                                QueryParameters: QP,
                            },
                        },
                    ],
                };

                Core.Export.Excel(
                    data,
                    function (resp) {
                        try {
                            if (resp && resp.Success === true && resp.Data) {
                                location.href = app.foldersRoot + '/excel/' + resp.Data;
                            } else if (resp && resp.Message) {
                                console.error(resp.Message);
                            } else {
                                console.error('Server response not valid.');
                            }
                        } catch (Error) { console.error(Error); }
                        that.setExportButtonExporting(false);
                    },
                    function (resp) {
                        console.error(resp);
                        that.setExportButtonExporting(false);
                    }
                );
            },
            setExportButtonExporting: function (val) {
                var btn           = this.$el.find('.btn-export-to-excel');
                var exportState   = btn.find('.excel-export-state');
                var loadingState  = btn.find('.loading-state');

                if (val) {
                    exportState.css('display', 'none');
                    loadingState.removeClass('hide');
                    btn.attr('disabled', true);
                } else {
                    loadingState.addClass('hide');
                    exportState.css('display', 'inline-block');
                    btn.attr('disabled', false);
                }
            },

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

                if (this.options.state == app.view_states.loading
                    || this.options.state == app.view_states.shown) {
                    this.options.state = app.view_states.shown;
                    container.append(el);
                    this.options.onappend(this);
                }
                if (this.options.state == app.view_states.hidden) container.append(el);
                if (this.options.state == app.view_states.closed) return;
            },
            bindViewScopedEvents:   function () { },
            unbindViewScopedEvents: function () { },
            close: function () {
                this.options.state = app.view_states.closed;
                if (this.agGridModule && this.agGridModule.destroy) this.agGridModule.destroy();
                this.closeSubviews();
                this.remove();
                this.unbindViewScopedEvents();
                this.unbind();
            },
            closeSubviews: function () { _.each(this.subviews, function (s) { s.close(); }); },
            show: function () {
                this.options.state = app.view_states.shown;
                this.showSubviews();
                this.bindEvents();
                this.$el.show();
            },
            showSubviews: function () { _.each(this.subviews, function (s) { s.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 (s) { s.hide(); }); },
            preRender: function () { app.models.subnavbar.set('subnavbar', false); },
            reRender: function () {
                try { this.refresh(); } catch (Error) { }
            },
        });

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

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