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

define([
  // Application variable, always include it to have access to app methods.
  'app',

  //templates-loader: this loads templates async.
  'js/templates-loader',
  'backgrid',
  'moment',

    'modules/modal2',
  'backgrid/infinator',
  'backgrid/moment-cell',
  'backgrid/grouped-columns',
  
    "js/jquery.floatThead/jquery.floatThead",
],
function (app, T, Backgrid, moment, Modal) {

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

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            start: new moment().subtract(2, 'days').format('YYYY-MM-DD'),
            end: new moment().format('YYYY-MM-DD'),
           
            hasData: false,
            isLoading: false,
            grid: [],
            appendGrid: true,

        },
        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, };
                },
            },
        },
        initialize: function () {
            this.gridCollection = new Screen.Collections.Items();
        },

    });

    Screen.Views.Main = Backbone.Epoxy.View.extend({
        template: 'process-data-export',
        id: 'process-data-export',
        title: 'Process Data Export',
        events: function () {
            return {
                'click #refreshBtn': this.refreshBtn_click,
                "click .btn-export-to-excel": this.exportToExcel,
            };
        },
        bindings: 'data-bind',
        bindingSources: null,
        subviews: null,
        viewParams: null,

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

            var that = this;

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


            this.bindingSources = {};

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

            this.bindEvents();
        },
        bindEvents: function () {
            //this.listenTo(this.model, 'buildGrid', this.buildGrid);
            this.listenTo(this.model.gridCollection, 'fetch', this.processes_ready);
                

        },
        buildGrid: function (tableData) {
            // the grid is not mandatory
            return;

            var columnsName = [];
            var that = this;

            if (!tableData || tableData.length === 0) return;

            this.model.set({
                appendGrid: false,
            });

            var keys = Object.keys(tableData[0]);

            _.each(keys, function (obj) {
                columnsName.push({
                    "name": obj,
                    "editable": false,
                    "label": app.translate([that, app], obj),
                    "cell": Backgrid.StringCell.extend({
                        className: 'string-cell align-center-cell',
                    }),
                });
            });


            that.grid = new Backgrid.Grid({
                className: 'backgrid table table-hover table-condensed production-table',
                columns: columnsName,
                row: Backgrid.Row.extend({
                    initialize: function (options) {
                        Backgrid.Row.prototype.initialize.apply(this, arguments);
                    },
                }),
                collection: that.model.gridCollection,
                footer: Backgrid.Extension.Infinator.extend({
                    scrollToTop: false,
                }),
            });
            that.model.set({ grid: that.grid });

            that.showBackgrid();
        
        },


        showBackgrid: function () {
            var container = this.$el.find(".processes-grid-container");
            container.empty();

            container.append(this.model.get('grid').render().el);

            var table = container.find(".production-table")
            table.floatThead({
                scrollingTop: function () {
                    try {
                        return $(".fixed-subnavbar").height() + ($("header").height() / 2);
                    } catch (error) { return 111; }
                },
                zIndex: 500,
                useAbsolutePositioning: false,
            });

        },

        _refresh: function (opt) {
            this.model.gridCollection.reset();

            this.model.set({
                hasData: false,
                isLoading: true,
            });

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

            this.refreshProcesses(opt);

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

                this.autoRefresh.toid = setTimeout(
                    function () { that._refresh(); },
                    this.autoRefresh.every
                );
            }
        },
        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');
            i

            this.model.set(fixedParams);

            this._refresh({
                reset: true,
                params: _.extend(
                    {},
                    fixedParams,
                    {}
                ),
            });
        },
        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/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) {
                            //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();

                            //start: the view was already loaded an is on a div element, but not appended to the main container
                            //here you can perform anything you want DOM related, by getting the dom element via that.$el.find('#id')
                            //or this.$('#id')

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


                            //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,
                                    {
                                    }
                                ),
                            });


                        },
                        true,
                        customPath
                    );
                },
                customPath
            );
        },
        processes_ready: function (coll,data) {
            try {
                var that = this;
                setTimeout(
                    function () {
                        that.model.set({
                            hasData: (that.model.gridCollection.length > 0),
                            isLoading: false,
                        });
                        that.buildGrid(data);
                    },
                    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);

            this.model.gridCollection.fetch({
                start: attrs.start,
                end: attrs.end,
                refresh: true,
            })



        },
        getExcelColumns: function () {
            return [
                'A'
                , 'B'
                , 'C'
                , 'D'
                , 'E'
                , 'F'
                , 'G'
                , 'H'
                , 'I'
                , 'J'
                , 'K'
                , 'L'
                , 'M'
                , 'N'
                , 'O'
                , 'P'
                , 'Q'
                , 'R'
                , 'S'
                , 'T'
                , 'U'
                , 'V'
                , 'W'
                , 'X'
                , 'Y'
                , 'Z'
                , 'AA'
                , 'AB'
                , 'AC'
                , 'AD'
                , 'AE'
                , 'AF'
                , 'AG'
                , 'AH'
                , 'AI'
                , 'AJ'
                , 'AK'
                , 'AL'
                , 'AM'
                , 'AN'
                , 'AO'
                , 'AP'
                , 'AQ'
                , 'AR'
                , 'AS'
                , 'AT'
                , 'AU'
                , 'AV'
                , 'AW'
                , 'AX'
                , 'AY'
                , 'AZ'
                , 'BA'
                , 'BB'
                , 'BC'
                , 'BD'
                , 'BE'
                , 'BF'
                , 'BG'
                , 'BH'
                , 'BI'
                , 'BJ'
                , 'BK'
                , 'BL'
                , 'BM'
                , 'BN'
                , 'BO'
                , 'BP'
                , 'BQ'
                , 'BR'
                , 'BS'
                , 'BT'
                , 'BU'
                , 'BV'
                , 'BW'
                , 'BX'
                , 'BY'
                , 'BZ'
                , 'CA'
                , 'CB'
                , 'CC'
                , 'CD'
                , 'CE'
                , 'CF'
            ];
        },
        setExportButtonExporting: function (val) {
            var btn_export = this.$el.find('.btn-export-to-excel');
            var export_state = btn_export.find('.excel-export-state');
            var loading_state = btn_export.find('.loading-state');

            if (val) {
                export_state.css('display', 'none', 'important');
                loading_state.removeClass('hide');

                btn_export.attr('disabled', true);
            } else {
                loading_state.addClass('hide');
                export_state.css('display', 'inline-block', 'important');

                btn_export.attr('disabled', false);
            }
        },
        exportToExcel: function () {
            var that = this,
                params = this.model.toJSON();

            var models = this.model.gridCollection.toJSON();
            if (!models || !models[0]) return;

            this.setExportButtonExporting(true);

            var CellsData = [];
            var SQLCellsData = [];
            var excelColumns = this.getExcelColumns();


            if (models && models.length > 0) {
                var keys = Object.keys(models[0]);
                _.forEach(keys, function (key,i) {
                    CellsData.push({
                        Column: excelColumns[i], Value: key
                    });
                    SQLCellsData.push({
                        ExcelColumnName: excelColumns[i], SQLDataColumnName: key, DataType: 'String'
                    })
                });
                console.log("CellsData", CellsData);
                console.log("SQLCellsData", SQLCellsData);
            }
            var params = [
                { Name: '@start', Type: 'DATETIME', Value: params.start, },
                { Name: '@end', Type: 'DATETIME', Value: params.end, },
            ];
            var QP = new QueryParameters();

            _.each(params, function (qpParams) {
                QP.Add(qpParams.Name, qpParams.Type, qpParams.Value);
            });


            var data = {
                Data: [],
                ConnectionStringName: 'APP',
                ExportMethod: 3,
                FileName: 'MES-Process-Data',
                TemplateFileFullPath: 'generic.xls',
                SQLDataSources: [
                    {
                        Name: 'data',
                        DatabaseParameters: {
                            DBEngine: 'SQLSERVER',
                            Procedure: app.DatabaseNames.MES + '.MES.GetProcessDataExport',
                            QueryParameters: QP,
                        },
                    },
                ]
            };

            data.Data.push({
                SheetName: 'Data',
                RowsData: [{
                    CellsData: CellsData,
                }],
                StartRowIndex: 1,
            });

            data.Data.push({
                SheetName: 'Data',
                RowsData: [],
                StartRowIndex: 2,
                DataSourceName: 'data',
                DataSourceTableIndex: 0,
                SQLCellsData: SQLCellsData
            });
                       
            Core.Export.Excel(
                data,
                function (resp) {
                    try {
                        if ((resp) && (resp.Success == true) && (resp.Data)) {
                            location.href = app.foldersRoot + '/excel/' + resp.Data;

                            that.setExportButtonExporting(false);
                        }
                        else {
                            if ((resp) && (resp.Message))
                                console.error(resp.Message);
                            else
                                console.error('Server response not valid.');

                            that.setExportButtonExporting(false);
                        }
                    }
                    catch (Error) { console.error(Error); }
                    that.setExportButtonExporting(false);
                },
                function (resp) {
                    that.model.refreshProcesses();
                    that.setExportButtonExporting(false);
                    console.error(resp);
                }
            );
        },
        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'),
                                casterCode: (params.casterCode == null || params.casterCode == "") ? '-' : params.casterCode,
                                crewId: (params.crewId == null || params.crewId == "") ? '-' : params.crewId,
                                shiftId: (params.shiftId == null || params.shiftId == "") ? '-' : params.shiftId,
                                strandId: (params.strandId == null || params.strandId == "") ? '-' : params.strandId,
                            }
                        ),
                        false
                    ),
                    { trigger: false, }
                );

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

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

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

            if (this.options.state == app.view_states.loading
                || this.options.state == app.view_states.shown) {
                //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.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        },
        closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.close();
            });
        },
        show: function () {
            this.options.state = app.view_states.shown;

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

            this.hideSubviews();

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

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

        fixedParameters: [],

        fetch: function (params) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                options = params ? _.clone(params) : {};
            if (options.refresh) {
                this.resetPagination(true);
                this.fixedParameters = [
                        { Name: '@Start', Type: 'DATETIME', Value: params.start, },
                        { Name: '@End', Type: 'DATETIME', Value: params.end, },
                ];
            }
            this.isFetching = true;

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

            if (!options.refresh) {
                qp.Add('@fromRow', 'INT', (this.currentPage - 1) * this.pageSize + 1);
                qp.Add('@rowsToFetch', 'INT', this.pageSize - 1);
            } else {
                qp.Add('@fromRow', 'INT', 0);
                qp.Add('@toRow', 'INT', this.currentPage * this.pageSize);
                qp.Add('@rowsToFetch', 'INT', this.pageSize);
            }


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

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

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

                                that.isFetching = false;


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

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