//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/user-property/user-property',
  'modules/furnace/furnace',

  'backgrid/select-integer-cell',
],
function (app, T, Backgrid, UserProperty, Furnace) {

    var PROPERTY_ALL_VALUE = -1,
        PROPERTY_NO_VALUE = 0;

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

    Screen.Models.Item = Backbone.Epoxy.Model.extend({
        defaults: {
            name: null,
            userId: null,
            userName: null,
            eafFurnaceCode: PROPERTY_NO_VALUE,
        },
        idAttribute: 'userId',
    });

    Screen.Collections.Items = UserProperty.Collections.UserProperties.extend({
        model: Screen.Models.Item,
    });

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            items: null,

            eafFurnaces: [],

            hasData: false,
            isLoading: true,
        },
        computeds: {
            hasEafFurnaces: {
                deps: ['eafFurnaces'],
                get: function (value) {
                    return ((value) && (value.length != 0));
                },
            },
        },

        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 'eaf-furnace-assign';
        } catch (Error) { }
    }

    Screen.Views.Main = Backbone.Epoxy.View.extend({
        template: 'eaf-furnace-assign',
        id: 'eaf-furnace-assign',
        title: 'Eaf Furnace Assign',
        //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,

        userPropertiesColl: 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
            };

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

            if (!this.userPropertiesColl)
                this.userPropertiesColl = new UserProperty.Collections.UserProperties();

            this.bindingSources = {
                items: this.model.get('items'),
            };


            Furnace.Collections.Furnaces.fetch({
                async: false,
                success: function (records) {
                    try {
                        that.model.set(
                            'eafFurnaces',
                            _.map(records, function (obj) { return { value: obj.code, label: obj.name, }; })
                        );
                    }
                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                },
            });


            this.subviews = {};


            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.userPropertiesColl, 'fetch', this.userPropertiesColl_fetch)
                .listenTo(this.model.get('items'), 'change:eafFurnaceCode', this.collection_change_eafFurnaceCode);
        },
        _refresh: function (opt) {
            //console.log('autorefresh: ' + new Date().toString()); 
            if (this.autoRefresh.toid != null) {
                clearTimeout(this.autoRefresh.toid);
                this.autoRefresh.toid = null;
            }

            this.refreshItemsColl(opt);

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

                this.autoRefresh.toid = setTimeout(
                    function () { that._refresh(); },
                    this.autoRefresh.every
                );
            }
        },
        refresh: function (viewParams) {
            //if (viewParams.sectionParam1)
            //    viewParams.sectionParam1 = parseInt(viewParams.sectionParam1, 10);
            //else
            //    viewParams.sectionParam1 = Screen.Models.Main.prototype.defaults.recipeId;

            //this.model.set({
            //    recipeId: viewParams.sectionParam1,
            //});
        },
        refreshItemsColl: function (options) {
            var that = this,
                opt = _.extend({}, options, { params: {}, refresh: true, });

            if (opt.reset == true)
                this.model.set('isLoading', true);

            var that = this,
                modelAttrs = this.model.toJSON();

            this.userPropertiesColl.fetch(_.extend(
                opt,
                {
                    refresh: opt.refresh,
                    reset: opt.reset,

                    params: _.extend(
                        modelAttrs,
                        opt.params
                    ),
                }
            ));
        },
        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')

                            var grid = that.options.itemsGrid = new Backgrid.Grid({
                                className: 'backgrid table table-hover',
                                columns: [
                                    {
                                        name: 'name',
                                        label: app.translate(that, 'name_col'),
                                        editable: false,
                                        sortable: false,
                                        cell: Backgrid.StringCell.extend({
                                            orderSeparator: '',
                                            className: 'string-cell align-center-cell name',
                                        }),
                                    },
                                    {
                                        name: 'userName',
                                        label: app.translate(that, 'user_name_col'),
                                        editable: false,
                                        sortable: false,
                                        cell: Backgrid.StringCell.extend({
                                            orderSeparator: '',
                                            className: 'string-cell align-center-cell userName',
                                        })
                                    },
                                    {
                                        name: 'eafFurnaceCode',
                                        sortable: false,
                                        label: app.translate([that, app], 'eaf_furnace_col'),
                                        cell: Backgrid.Extension.SelectIntegerCell.extend({
                                            className: 'select-cell align-center-cell eafFurnaceCode',
                                            optionValues: [].concat(
                                                [[app.translate([that, app], 'user_property_combo_all_opt'), -1]],
                                                _.map(that.model.get('eafFurnaces'), function (obj) { return [obj.label, obj.value, ]; }),
                                                [[app.translate([that, app], 'user_property_combo_none_opt'), 0]]
                                            ),
                                        }),
                                    },
                                ],
                                collection: that.model.get('items'),
                            });
                            that.$el.find('.items-grid-container').append(grid.render().el);

                            //end

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

                            //Call first refresh.
                            that.startAutoRefresh();
                        },
                        true,
                        customPath
                    );
                },
                customPath
            );
        },

        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;
            }
        },
        startAutoRefresh: function () {
            try {
                if (this.autoRefresh.enabled !== true) {
                    var that = this;

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

                    this.autoRefresh.enabled = true;

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

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

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

            this.hideSubviews();
            this.stopAutoRefresh();

            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 () {
            this.startAutoRefresh();
        },

        actionOnRow: function (model, action) {
            try {
                switch (action.toUpperCase()) {
                    case 'EDIT_DETAILS':
                        this.model.set('itemId', model.get('userId'));
                        break;
                }
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        userPropertiesColl_fetch: function (coll, resp) {
            try {
                var itemsColl = this.model.get('items'),
                    users = _(this.userPropertiesColl.toJSON())
                                .where({ code: 'EAF_FURNACE', })
                                .map(function (obj) {
                                    return {
                                        userId: obj.userId,
                                        userName: obj.userName,
                                        name: obj.name,
                                        eafFurnaceCode: obj.value,
                                    };
                                });

                //Add users which do not have eaf furnace property.
                this.userPropertiesColl.each(function (model) {
                    var attrs = model.toJSON();

                    if (!_.findWhere(users, { userId: attrs.userId, })) {
                        users.push({
                            userId: attrs.userId,
                            userName: attrs.userName,
                            name: attrs.name,
                            eafFurnaceCode: PROPERTY_NO_VALUE,
                        });
                    }
                });

                itemsColl.set(users, { from: 'fetch', });

                this.model.set({
                    hasData: (itemsColl.length > 0),
                    isLoading: false,
                });
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        collection_change_eafFurnaceCode: function (model, value, opt) {
            try {
                if (!opt) opt = {};

                if (opt.from != 'fetch') {
                    var that = this,
                        prop,
                        eafFurnaceCode = model.get('eafFurnaceCode'),
                        userId = model.get('userId')
                    var userPropertiesCollTemp = new UserProperty.Collections.UserProperties(
                            _.filter(
                                this.userPropertiesColl.toJSON(), 
                                function (obj) { return ((obj.userId == userId) && (obj.code != null)); }
                            )
                        );


                    prop = userPropertiesCollTemp.findWhere({ code: 'EAF_FURNACE', });

                    if (prop) {
                        if (eafFurnaceCode != PROPERTY_NO_VALUE)
                            prop.set('value', eafFurnaceCode);
                        else
                            userPropertiesCollTemp.remove(prop);
                    }
                    else if (eafFurnaceCode != PROPERTY_NO_VALUE) {
                        userPropertiesCollTemp.add({
                            code: 'EAF_FURNACE',
                            value: eafFurnaceCode,
                        });
                    }


                    userPropertiesCollTemp.update(
                        {
                            params: {
                                userId: userId,
                            },
                            success: function (resp) {
                                try {
                                    app.views.topMessages.showMessage(app.translate([that, app], 'SAVED_CHANGES_SUCCESSFUL'), { stay: 5 * 1000, });

                                    that.refreshItemsColl({ refresh: true, });
                                }
                                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                            },
                            error: function (errorMsg) {
                                try {
                                    app.views.topMessages.showMessage(app.translate([that, app], errorMsg), { stay: 5 * 1000, });
                                }
                                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                            }
                        }
                    );
                }
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
    });

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

});
