/// <reference path="http://localhost:65492/IndustrialDashboard/Scripts/IndustrialDashboard-debug.js" />
//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",
],

function (app, T, Backgrid, moment) {

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

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            start: new moment().format('YYYY-MM-DD'),
            end: new moment().format('YYYY-MM-DD'),
            lineId: 0,
            lines: [],

            items: null, 
        },
        //computeds: {
        //    hasPassChangeReasons: {
        //        deps: ['passChangeReasons'],
        //        get: function (passChangeReasons) {
        //            return passChangeReasons.length != 0;
        //        },
        //    },
        //},

        fetchLines: function () {
            var that = this;

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetProductionItems", null, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var items = data.Table;

                        that.set({
                            lines: _.map(_.filter(items, function (m) { return m.ProductionItemType.toUpperCase() == "LINE"; }), function (m) {
                                return { value: m.Id, label: m.Name, };
                            }),
                        });
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
    });

    //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 "oee-prod-import-report";
        } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
    }

    Screen.Views.Main = Backbone.Epoxy.View.extend({
        template: "oee-prod-import-report"
        , id: "oee-prod-import-report"
        , title: "OEE Production Import Report"
        //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 {
                //'click #excelBtn': this.excelBtn_click,
                //'click #refreshBtn': this.refreshBtn_click,
            };
        },

        itemsGrid: null,

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

            this.model = new Screen.Models.Main({
                items: new Screen.Collections.Items(), 
            });

            this.options.subviews = {};
            this.options.autoRefresh = {
                enabled: true,
                toid: null,
            };

            this.model.fetchLines();

            this.bindEvents();
        },

        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
            this.listenTo(this.model, 'change', this.model_changed);
        },
        drawGrid: function (coll) {
            if (coll.length > 0) {
                var columns = [],
                    attrs = coll.models[0].toJSON(),
                    idAttribute = coll.model.prototype.idAttribute.toUpperCase(),
                    colsIgnored = ['EXPORTED'],
                    i = 0;

                for (var attrName in attrs) {
                    if ((attrName.toUpperCase() != idAttribute) && (colsIgnored.indexOf(attrName.toUpperCase()) == -1)) {
                        var colName = (attrName.match(/^\FixedCol\$_.+$/))
                                            ? attrName + '_col_label'
                                            : attrName;

                        columns.push({
                            id: attrName,
                            name: attrName,
                            label: app.translate([this, app], colName),
                            editable: false,
                            sortable: false,
                            //Use order property to sort columns always in the right order because when columns change,
                            //the new custom columns are displayed at the end of the table due to they are sorted by the columns
                            //collection at the end due to the other columns did not change.
                            order: i,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell " 
                                            //Replace char '$' to make it a valid CSS class name.
                                            + attrName.replace(/\$/gi, ''),
                            })
                        });
                    }

                    i++;
                }

                if (!this.itemsGrid) {
                    var grid = this.itemsGrid = new Backgrid.Grid({
                        className: "backgrid table table-hover",
                        //Override columns collection to sort the columns by order property.
                        columns: new (Backgrid.Columns.extend({
                            comparator: 'order',
                        }))(columns),
                        collection: coll,
                    });

                    this.$el.find(".items-grid-container").append(grid.render().el);
                }
                else {
                    this.itemsGrid.columns.set(columns);
                }
            }
        },
        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.oeeModule.screensPath + 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;
                            that.$el.html(tmp());
                            that.applyBindings();

                            that.$el.find('.input-date').datepicker({
                                dateFormat: 'yy-mm-dd',
                            });

                            that.append(thatContainer, that.$el);
                        },
                        true,
                        customPath
                    );
                },
                customPath
            );
        }
        , _startAutoRefresh: function (opt) {
            try {
                if (this.options.autoRefresh.toid != null) {
                    clearTimeout(this.options.autoRefresh.toid);
                    this.options.autoRefresh.toid = null;
                }

                this.options.autoRefresh.enabled = true;

                this._autoRefresh(opt);
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        }
        , _autoRefresh: function (opt) {
            var that = this; 
            if (this.options.autoRefresh.toid != null) {
                clearTimeout(this.options.autoRefresh.toid);
                this.options.autoRefresh.toid = null;
            }

            this.refresh(_.extend({}, opt, {
                callback: function () {
                    if (that.options.autoRefresh.enabled == true) {
                        that.options.autoRefresh.toid = setTimeout(_.bind(that._autoRefresh, that), 5000);
                    }
                }, 
            }));
        }
        , _stopAutoRefresh: function () {
            if (this.options.autoRefresh.toid != null) {
                clearTimeout(this.options.autoRefresh.toid);
                this.options.autoRefresh.toid = null;
            }
            this.options.autoRefresh.enabled = false;
        }
        , refresh: function (opt) {
            try {
                var that = this,
                    attrs = this.model.toJSON(),
                    fetched = false; 

                if (opt && opt.showLoading) {
                    setTimeout(function () {
                        if (!fetched) that.showLoading(true);
                    }, 500);
                }

                this.model.get("items").fetch(_.extend(
                    {},
                    opt,
                    {
                        params: {
                            start: attrs.start,
                            end: attrs.end,
                            lineId: attrs.lineId,
                        },
                        success: function () {
                            try {
                                fetched = true; 
                                that.showLoading(false);

                                that.drawGrid(that.model.get('items'));

                                if (opt && opt.callback && _.isFunction(opt.callback))
                                    opt.callback.call(that, that); 
                            }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        error: function () {
                            try {
                                fetched = true;
                                that.showLoading(false);

                                if (opt && opt.callback && _.isFunction(opt.callback))
                                    opt.callback.call(that, that);
                            }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                    }
                ));
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        }
        , showLoading: function (val) {
            var loadingPoster = this.$el.find(".loading-poster"); 
            var gridContainer = this.$el.find(".items-grid-container"); 
            
            if (val) {
                gridContainer.addClass("hide");
                loadingPoster.removeClass("hide");
            } else {
                loadingPoster.addClass("hide");
                gridContainer.removeClass("hide"); 
            }
        }

        , 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.remove();
            this.unbindViewScopedEvents();
            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();
        },
        preRender: function () {
            app.models.subnavbar.set('subnavbar', false);
        },
        reRender: function (viewParams) {
            try {
                this._refresh(viewParams);
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },

        model_changed: function (model, value, opt) {
            try {
                this.refresh({
                    showLoading: true,
                    refresh: true,
                });
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
    });

    Screen.Models.Item = Backbone.Epoxy.Model.extend({
        defaults: {
            BatchId: null,
        },

        idAttribute: 'BatchId',

        parse: function (obj) {
            return obj;
        },
    });

    Screen.Collections.Items = Backbone.Collection.extend({
        model: Screen.Models.Item,

        fixedParameters: [],
        isFetching: false,
        currentPage: 1,
        pageSize: 100,
        transaction_timestamp: null,

        fetch: function (opt) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                ttimestamp = this.transaction_timestamp = new Date().getTime(),
                options = _.extend({
                    method: 'set',
                    async: true,
                    params: {},
                    refresh: false,
                }, opt);

            this.isFetching = true;

            if (options.refresh) {
                this.resetPagination(true);

                this.fixedParameters = [
                    { Name: '@start', Type: 'DATE', Value: options.params.start, },
                    { Name: '@end', Type: 'DATE', Value: options.params.end, },
                    { Name: '@lineId', Type: 'INT', Value: options.params.lineId, },
                    { Name: '@timeZoneCode', Type: 'CHAR', Value: app.models.user.get('timezoneCode'), },
                ];
            }

            _.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);
                qp.Add('@rowsToFetch', 'INT', this.pageSize);
            } 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.OEE + '.WebApp.GetProductionImportData',
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            //checking transaction timestamp
                            if (ttimestamp != that.transaction_timestamp)
                                return;

                            if ((resp) && (resp.Table)) {
                                var newColl;

                                newColl = _.map(resp.Table, that.model.prototype.parse);

                                var method = (options.refresh) ? 'set' : 'add';

                                //checking transaction timestamp
                                if (ttimestamp != that.transaction_timestamp)
                                    return;

                                if (options.refresh)
                                    that.reset();

                                that[method](newColl)
                                    .trigger('fetch', that, resp);

                                //decreasing page since we couldn't get any data on this page.
                                if (newColl.length == 0 && method == 'add')
                                    that.currentPage--;

                                that.isFetching = false;

                                if (options.success != null && _.isFunction(options.success))
                                    options.success(resp);
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(new Error(resp.Message).stack);
                                else
                                    console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);

                                if (options.error != null && _.isFunction(options.error))
                                    options.error(resp);
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);

                        if (options.error != null && _.isFunction(options.error))
                            options.error(resp);
                    },
                    Secured: true,
                },
                app.ConnectionStrings.app
            );
        },
        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;

});

