//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',
    'modules/modal',
    "xlsx",
    'js/jquery.clearsearch/jquery.clearsearch',
],

    function (app, T, Backgrid, Modal, XLSX) {

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

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


        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                hasData: false,
                isLoading: false,
                excelRows: [],
                showRedirectButton: false,
            },

            initialize: function () {
                this.attributes.items = new Screen.Collections.Items();
            },


        });

        //the generate id method is called everytime a view is going to be shown by the router and returns and id that
        //is used by the router to store in cache (if it is cacheable) and to know the current shown view.
        //this is useful in case your view is reusable, and displays different data depending on url parameters 
        //(such as a catalog view, or a report that doesnt change in terms of UI but it does change in terms of data)
        //so you can always use the same view on the router but the cache can tell which view is which by using differents ids.
        Screen.generateID = function (viewParams) {
            try {
                //if the viewparams change the view id, then evaluate the viewparams here
                //and return the appropiate id.
                return 'forecast-run-schedule-configuration';
            } catch (Error) { }
        }

        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'forecast-run-schedule-configuration',
            id: 'forecast-run-schedule-configuration',
            title: 'Run Schedule Configuration',
            //default not cacheable, change this if you want the view to be cacheable
            // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
            isCacheable: false,
            events: function () {
                return {
                };
            },
            autoRefresh: 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;

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

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


                this.subviews = {
                    subnavbarControls: new Screen.Views.SubnavBarControls({
                        model: this.model,
                        bindingSources: this.bindingSources,
                        parent: this,
                        container: app.views.subnavbar.getSectionContainer(1, 12),
                        events: function () {
                            return {
                                'click #saveBtn': _.bind(that.saveBtn_click, that),
                                'click #cancelBtn': _.bind(that.cancelBtn_click, that),
                                'change #fileInput': _.bind(that.handleFile, that),
                                'click #redirectBtn': _.bind(that.redirectBtn_click, that),

                            };
                        },
                    }),
                };

            },
            redirectBtn_click: function () {
                Backbone.history.navigate('!/forecast-run-schedule/', { trigger: true });
            },
            clearFileInput: function () {
                $("#fileInput").val(null);
                this.model.get('items').reset();
                this.model.set({
                    hasData: false,
                    isLoading: false,
                    showRedirectButton: false,
                });
            },
            saveBtn_click: function () {
                this.model.set({
                    isLoading: true,
                    hasData: false,
                });
                $("#fileInput").val(null);
                this.model.get('items').reset();
                this.upload(true);
            },
            cancelBtn_click: function () {
                this.clearFileInput();
            },

            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.subviews.subnavbarControls.render();

                                var grid = that.options.itemsGrid = new Backgrid.Grid({
                                    className: 'backgrid table table-hover',
                                    columns: [

                                        {
                                            name: 'DATE',
                                            label: 'DATE',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'SHIFT',
                                            label: 'SHIFT',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'CREW',
                                            label: 'CREW',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'HEATS',
                                            label: 'HEATS',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C1MOLD',
                                            label: 'C1MOLD',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C1MILL',
                                            label: 'C1MILL',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C1SIZE',
                                            label: 'C1SIZE',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C1HEATS',
                                            label: 'C1HEATS',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C2MOLD',
                                            label: 'C2MOLD',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C2MILL',
                                            label: 'C2MILL',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C2SIZE',
                                            label: 'C2SIZE',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                        {
                                            name: 'C2HEATS',
                                            label: 'C2HEATS',
                                            editable: false,
                                            sortable: false,
                                            cell: Backgrid.StringCell.extend({
                                                orderSeparator: '',
                                                className: 'string-cell align-center-cell',
                                            }),
                                        },
                                    ],
                                    collection: that.model.get('items'),
                                });
                                that.$el.find('.items-grid-container').append(grid.render().el);

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


                                //Call first refresh.
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            handleFile: function (e) {
                var that = this;


                var file = e.target.files[0];
                var reader = new FileReader();

                this.clearFileInput();

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

                reader.onload = function (e) {

                    var data = e.target.result;

                    var workbook = XLSX.read(data, { type: 'string' });
                    var allData = [];
                    var jsonData = [];
                    var dateTable = [];
                    var excelRows = [];
                    workbook.SheetNames.forEach(sheet => {
                        if (sheet === "Caster Master") {
                            let rowObject = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
                            jsonData = rowObject;
                            allData = workbook.Sheets[sheet];
                        }
                    });

                    _.forEach(allData, function (row) {
                        dateTable.push({ v: row.v, w: row.w })
                    });
                    var key_DATE;
                    var key_SHIFT;
                    var key_CREW;
                    var key_HEATS;
                    var key_C1MOLD;
                    var key_C1MILL;
                    var key_C1SIZE;
                    var key_C1HEATS;
                    var key_C2MOLD;
                    var key_C2MILL;
                    var key_C2SIZE;
                    var key_C2HEATS;
                    _.forEach(jsonData, function (row, i) {
                        if (i === 0) {
                            function getKeyByValueObject(object, value, position) {
                                if (position === 1 || !position)
                                    return Object.keys(object).filter(key => object[key] === value) && Object.keys(object).filter(key => object[key] === value)[0]
                                        ? Object.keys(object).filter(key => object[key] === value)[0]
                                        : Object.keys(object).filter(key => object[key] === value);
                                else if (position === 2)
                                    return Object.keys(object).filter(key => object[key] === value) && Object.keys(object).filter(key => object[key] === value)[1]
                                        ? Object.keys(object).filter(key => object[key] === value)[1]
                                        : null;
                            };
                            key_DATE = getKeyByValueObject(row, "DATE");
                            key_SHIFT = getKeyByValueObject(row, "DAY");
                            key_CREW = getKeyByValueObject(row, "CREW");
                            key_HEATS = getKeyByValueObject(row, "HEATS");
                            key_C1MOLD = getKeyByValueObject(row, "MOLD");
                            key_C1MILL = getKeyByValueObject(row, "MILL");
                            key_C1SIZE = getKeyByValueObject(row, "SIZE");
                            key_C1HEATS = getKeyByValueObject(row, "C1 HEATS");
                            key_C2MOLD = getKeyByValueObject(row, "MOLD", 2);
                            key_C2MILL = getKeyByValueObject(row, "MILL", 2);
                            key_C2SIZE = getKeyByValueObject(row, "SIZE", 2);
                            key_C2HEATS = getKeyByValueObject(row, "C2 HEATS");


                        }
                        if (i > 0) {
                            excelRows.push({
                                DATE: _.where(dateTable, { v: row[key_DATE] })[0].w
                                , SHIFT: row[key_SHIFT] ? 'D' : 'N'
                                , CREW: row[key_CREW]
                                , HEATS: row[key_HEATS]
                                , C1MOLD: row[key_C1MOLD]
                                , C1MILL: row[key_C1MILL]
                                , C1SIZE: row[key_C1SIZE]
                                , C1HEATS: row[key_C1HEATS]
                                , C2MOLD: row[key_C2MOLD]
                                , C2MILL: row[key_C2MILL]
                                , C2SIZE: row[key_C2SIZE]
                                , C2HEATS: row[key_C2HEATS]
                                , Sizes: row[key_C1SIZE] && row[key_C2SIZE]
                                    ? (row[key_C1SIZE].replace('/', ',') + ',' + row[key_C2SIZE].replace('/', ','))
                                    : (row[key_C1SIZE] && !row[key_C2SIZE] ? row[key_C1SIZE].replace('/', ',')
                                        : (!row[key_C1SIZE] && row[key_C2SIZE] ? row[key_C2SIZE].replace('/', ',') : null))
                            });
                        }
                    });
                    that.model.set({ excelRows: excelRows });
                    that.upload(false);

                };
                reader.readAsArrayBuffer(file);
            },

            upload: function (save) {
                var that = this;
                var excelRows = this.model.get('excelRows');
                try {
                    var qp = new QueryParameters();
                    qp.Add(
                        'Layout',
                        'XML',
                        app.jsonArrayToXml(
                            excelRows,
                            [

                                'DATE'
                                , 'SHIFT'
                                , 'CREW'
                                , 'HEATS'
                                , 'C1MOLD'
                                , 'C1MILL'
                                , 'C1SIZE'
                                , 'C1HEATS'
                                , 'C2MOLD'
                                , 'C2MILL'
                                , 'C2SIZE'
                                , 'C2HEATS'
                                , 'Sizes'
                            ]
                        )
                    );
                    qp.Add('Save', 'BIT', save)

                    that.model.set({ isLoading: true });

                    Core.Json.CallProcedure(
                        app.DatabaseNames.MES + '.MES.UploadRunSchedule',
                        qp,
                        {
                            onSuccess: function (resp) {
                                try {
                                    if ((resp) && (resp.Table)) {
                                        if (save) {
                                            app.views.topMessages.showMessage('The file has been successfully uploaded.', { stay: 5000, });
                                            that.model.set({ showRedirectButton: true, isLoading: false, hasData: false });
                                        } else {
                                            that.model.get('items').setDataColl(resp.Table);
                                            that.model.set({ isLoading: false, hasData: true });
                                        }

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

                                    }
                                    else {
                                        if ((resp) && (resp.Message)) {
                                            app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                            console.error(resp.Message);
                                        }
                                        else {
                                            app.views.topMessages.showMessage("Server response not valid.", { stay: 5000, });
                                            console.error("Server response not valid.");
                                        }
                                        that.model.set({ isLoading: false, hasData: false });
                                    }
                                    // that.trigger('entry-upserted');
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            onFailure: function (resp) {
                                console.error(resp);
                                that.model.set({ isLoading: false, hasData: false });
                            },
                            Secured: true,
                            Async: true,
                        },
                        app.ConnectionStrings.app
                    );
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).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 () {
            },
            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.setAll(false);
                app.models.subnavbar.set('sections', '12');
                app.models.subnavbar.set('subnavbar', true);
            },
            reRender: function () {
            },





        });

        //subview for the subnavbar controls
        Screen.Views.SubnavBarControls = Backbone.Epoxy.View.extend({
            id: 'forecast-run-schedule-configuration-subnavbar-controls',
            title: '',
            template: 'forecast-run-schedule-configuration',

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

                this.bindEvents();
            },
            render: function (container, onComplete) {
                var that = this;
                var thatContainer = (container) ? container : (this.options.container) ? this.options.container : null;
                var onViewComplete = (onComplete) ? onComplete : function () { };

                //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/forecast-run-schedule-configuration/';

                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;

                        var ctx = {
                            editable: (($.inArray('AdminUserRole', app.models.user.get('roles')) != -1
                                || $.inArray('SupervisorUserRole', app.models.user.get('roles')) != -1) ? true : false),
                        };

                        ctx = true;
                        //loading the view and appeding it to the views's $el.
                        that.$el.html(tmp(
                            _.extend({}, ctx, (that.model) ? that.model.toJSON() : {})
                        ));


                        that.applyBindings();

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

                    }, true, customPath);
                }, customPath, 'subnavbar_controls');

            },
            bindEvents: function () {
                //this function should be in every view that uses listenTo anywhere
                //all the model bindings or view-model binding should be here, to manage
                //the show/hide view easily
            },

            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;
                }
            },
            close: function () {
                this.options.state = app.view_states.closed;

                this.remove();
                this.unbind();
            },
            show: function () {
                this.options.state = app.view_states.shown;

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

                this.$el.hide();
                this.unbind();
                this.stopListening();
            },
        });

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

    });
