//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",

  "modules/modal",

  "js/jstree/jstree", 

],

function (app, T, Modal) {

    var TREE_NODE_ROOT_ID = -2;

    //replace all "LineProducts" with your view's name.
    var LineProducts = { Models: {}, Views: {}, Collections: {} }

    LineProducts.Models.TreeItem = Backbone.Model.extend({
        initialize: function () {
        }
        , defaults: {
            id: null,
            parent: null,
            type: null,
            text: null,
        }
    });

    LineProducts.Models.TreeItems = Backbone.Collection.extend({
        model: LineProducts.Models.TreeItem,
        initialize: function () {
            _.bindAll(this);

            this.bindEvents();
        },
        fetch: function (opt) {
            var options = {
                method: "set",
                async: true,
                callback: null,
                codesText: '',
            };

            options = _.extend(options, (opt) ? opt : {});

            var that = this,
                QP = new Core.Database.QueryParameters();

            var items = [];
            items.push({
                id: TREE_NODE_ROOT_ID,
                parent: '#',
                type: "root",
                text: options.codesText,
                state: {
                    opened: true,
                },
            });

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetLineProductsTree", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var data = data.Table;

                        for (var i = 0; i < data.length; i++) {
                            var itemData = data[i];
                            var prodItem = {
                                id: itemData.Id,
                                parent: ((itemData.ParentId != null) && (itemData.ParentId != -1))
                                            ? itemData.ParentId
                                            : TREE_NODE_ROOT_ID,
                                type: itemData.Type.toLowerCase(),
                                text: itemData.Name,
                            };

                            items.push(prodItem);
                        }
                    }

                    that[options.method](items, { from: "fetch" });

                    if (options.callback != null && _.isFunction(options.callback))
                        options.callback.call(this, that);
                },
                Async: options.async,
                Secured: true,
            }, app.ConnectionStrings.app);

            return this;
        },
        bindEvents: function () {
        },
        addItem: function (productionItemId, productId, success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("@LineProductionItemId", "INT", productionItemId);
            QP.Add("@ProductId", "INT", productId);

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.AddProductToLine", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = _.map(data, function (m) { return m.LineProductionItemId + '+' + m.ProductId }); 

                        if (success != null && _.isFunction(success))
                            success.call(this, that, ids);
                    } else {
                        error.call(this, that);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        }, 
        deleteItem: function (productionItemId, productId, success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("@LineProductionItemId", "INT", productionItemId);
            QP.Add("@ProductId", "INT", productId);

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.RemoveProductFromLine", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = _.pluck(data, 'Id');

                        if (success != null && _.isFunction(success))
                            success.call(this, that, ids);
                    } else {
                        error.call(this, that);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
        addNode: function (productionItemId, productId, text, parent, type, success, error) {
            var that = this; 
            this.addItem(productionItemId, productId, function (ref, ids) {
                that.add({
                    id: ids[0],
                    parent: (parent == "#") ? null : parseInt(parent), 
                    text: text,
                    type: type,
                });

                if (success && _.isFunction(success))
                    success.call(this, that, ids); 
            }, 
            function (ref) {
                if (error && _.isFunction(error))
                    error.call(this, that); 
            });
        },        
        deleteNode: function (productionItemId, productId, success, error) {
            var that = this;
            var model = this.get(productionItemId + '+' + productId);
            if (model) {
                this.deleteItem(
                    productionItemId, productId
                    , function (ref, ids) {
                        //removing from collection; 
                        that.remove(model);

                        if (success && _.isFunction(success))
                            success.call(this, that, ids);
                    },
                    function (ref) {
                        if (error && _.isFunction(error))
                            error.call(this, that);
                    }
                );
            }
        },
    });

    LineProducts.Models.Main = Backbone.Model.extend({
        defaults: {
            linesTreeItems: null,

            //
            productId: null,
            products: [], 
        },
        initialize: function () {
            this.set("linesTreeItems", new LineProducts.Models.TreeItems());

            this.fetchCatalogs(); 
        },
        fetchCatalogs: function () {
            this.fetchProducts(); 
        },
        fetchProducts: function () {
            var that = this; 
            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetProducts", null, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var products = data.Table; 
                        that.set({
                            products: _.map(products, 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.
    LineProducts.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "line-products"; 
        } catch (Error) { }
    }

    LineProducts.Views.Main = Backbone.Epoxy.View.extend({
        template: "line-products"
        , id: "line-products"
        , title: "Line Products"
        //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: true
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

            this.options.linesTree = null; 

            var model = new LineProducts.Models.Main({
                procedure: "dbo.procedureName"
            });

            this.model = model;

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

            this.options.MYREFERENCES.subviews = {
                productConfiguration: { view: null, model: null }, 
            };

            this.bindEvents();

            this._autoRefresh = _.bind(this._autoRefresh, this); 
        },

        events: {
            "click .btn-add-product-to-line": "addProductToLine",
        }, 

        render: function (container) {
            var that = this;
            var thatContainer = (container != null && container != undefined) ? container : this.options.container;

            //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 + "OEEConfiguration/line-products/";

            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;
                    //start: before the view is visible, but the template was already loaded (not instanced nor appended)

                    //end:

                    //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")
                    //end

                    $.jstree.defaults.core.themes.variant = "large";
                    var times = 0; 
                    that.$el.find(".tree").jstree({
                        core: {
                            check_callback: true, 
                            data: function (obj, cb) {
                                var data = that.model.get("linesTreeItems").toJSON();

                                _.each(data, function (t) {
                                    //This should be temporaly until find the cause of the issue with state prop on jstree.
                                    if (!t.state) t.state = {};
                                });

                                cb.call(this, data);
                            },
                        },
                        types: {
                            "#": {
                                valid_children: ['root', 'area', 'line'],
                                //max_children: 1,
                            },
                            "root": {
                                icon: "fa fa-building",
                                valid_children: ['area', 'line'],
                            },
                            "area": {
                                icon: "fa fa-th-large",
                                valid_children: ['line']
                            },
                            //"#": {
                            //    valid_children: ['line']
                            //},
                            "line": {
                                "icon": "fa fa-sitemap",
                                valid_children: ['product'], 
                            },
                            "product": {
                                "icon": "fa fa-cube",
                                max_children: 0
                            }
                        },
                        contextmenu: {
                            items: _.bind(that.customLinesTreeCtxMenu, that),
                        },
                        plugins: [
                            "contextmenu",
                            "wholerow",
                            "types",
                        ], 
                    });

                    that.options.linesTree = that.$el.find(".tree").jstree(true);

                    that.$el.find(".tree").bind({
                        "create_node.jstree": _.bind(that.onCreateNode, that),
                        "delete_node.jstree": _.bind(that.onDeleteNode, that),
                        "select_node.jstree": _.bind(that.onSelectNode, that),
                        "deselect_node.jstree": _.bind(that.onDeselectNode, that),
                        "deselect_all.jstree": _.bind(that.onDeselectNode, that),
                    });

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

                    that._startAutoRefresh(); 
                }, true, customPath); 
            }, customPath, "main_template");
        }

        , customLinesTreeCtxMenu: function (node) {
            var that = this;
            // The default set of all items
            var items = {
                deleteItem: {
                    label: "Delete",
                    action: function (obj) {
                        that.deleteNode(node);
                    },
                }
            };

            if (node.type != "product") {
                delete items["deleteItem"];
            }

            return items;
        }

        , addProductToLine: function () {
            var productId = this.model.get("productId"); 
            if (productId != -1) {
                var tree = this.options.linesTree;
                var selected = tree.get_selected();

                if (!selected.length) { return false; }
                var sel = selected[0];
                var selected_node = tree.get_node(sel);

                if (_.indexOf(_.map(selected_node.children, function (m) { return parseInt(m.split("+")[1], 10); }), productId) == -1) {
                    if (selected_node.type == "line") {
                        var text = _.findWhere(this.model.get("products"), { value: productId });
                        text = (text) ? text.label : "";
                        var _id = selected_node.id + '+' + productId; 

                        sel = tree.create_node(sel, { id: _id, "type": "product", "text": text }, "last", function (a, b, c) {
                        });
                    }
                }
            }
        }

        , onCreateNode: function (e, obj) {
            var node = obj.node;
            var instance = obj.instance; 
            var collection = this.model.get("linesTreeItems");

            collection.addNode(node.parent, node.id.split('+')[1], node.text, node.parent, node.type, function (ref, ids) {
                instance.set_id(node, ids[0]);
                instance.deselect_all(); 
                instance.select_node(node); 
            }, function () {
                instance.refresh(); 
            }); 
        }

        , onDeleteNode: function (e, obj) {
            if (this.options.MYREFERENCES.subviews.productConfiguration.view)
                this.options.MYREFERENCES.subviews.productConfiguration.view.close();

            var node = obj.node;
            var instance = obj.instance;
            var collection = this.model.get("linesTreeItems");

            var productionItemId = node.parent;
            var productId = node.id.split('+')[1]; 

            collection.deleteNode(productionItemId, productId, function (ref, ids) {
            }, function () {
                instance.refresh();
            });
        }

        , onSelectNode: function (e, obj) {
            this.checkAddProductButton(e, obj);

            var that = this;
            var node = obj.node;
            var instance = obj.instance;
            var collection = this.model.get("linesTreeItems");

            if (this.options.MYREFERENCES.subviews.productConfiguration.view)
                this.options.MYREFERENCES.subviews.productConfiguration.view.close(); 

            if (obj.selected.length < 2) {
                if (node.type == "product") {
                    var productConfigurationContainer = this.$el.find(".product-configuration-container");

                    var model = new LineProducts.Models.ProductConfiguration();
                    this.options.MYREFERENCES.subviews.productConfiguration.view = new LineProducts.Views.ProductConfiguration({
                        container: productConfigurationContainer,
                        model: model,
                    });

                    model.fetch({
                        data: {
                            id: node.id.split('+')[1],
                            lineProductionItemId: node.parent
                        }
                    });

                    this.options.MYREFERENCES.subviews.productConfiguration.view.render();
                }
            }
        }

        , onDeselectNode: function (e, obj) {
            var that = this;
            var node = obj.node;
            var instance = obj.instance;

            if (this.options.MYREFERENCES.subviews.productConfiguration.view)
                this.options.MYREFERENCES.subviews.productConfiguration.view.close();
        }

        , deleteNode: function (data) {
            var tree = this.options.linesTree;
            var selected = tree.get_selected();

            if (selected.length > 0)
                data = selected; 

            tree.delete_node(data); 
        }

        , checkAddProductButton: function (e, data) {
            var btnAddProductToLine = this.$el.find(".btn-add-product-to-line");
            if (data.node.type == "line") {
                btnAddProductToLine.prop("disabled", false);
            } else {
                btnAddProductToLine.prop("disabled", true);
            }
        }

        , 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.options.MYREFERENCES.autoRefresh.toid != null) {
                    clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                    this.options.MYREFERENCES.autoRefresh.toid = null;
                }

                this.options.MYREFERENCES.autoRefresh.enabled = true;

                this._autoRefresh();
            } catch (Error) { }
        }

        , _autoRefresh: function () {
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }

            this.refresh();

            if (this.options.MYREFERENCES.autoRefresh.enabled == true) {
                this.options.MYREFERENCES.autoRefresh.toid = setTimeout(this._autoRefresh, 5000);
            }
        }

        , _stopAutoRefresh: function () {
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }
            this.options.MYREFERENCES.autoRefresh.enabled = false;
        }

        , refresh: function () {
            try {
                var that = this; 
                this.model.get("linesTreeItems").fetch({
                    codesText: app.translate(that, "root_tree_text"),
                });
            } catch (Error) { }
        }

        , linesTreeItemsChanged: function (a, b, c) {
            var fromFetch = (
                            (c && c.from && c.from == "fetch") ||
                            (!c && b && b.from == "fetch")
                            ) ? true : false;

            if (fromFetch) {
                this.debounced_refreshLinesTree(); 
            }
        }        

        , debounced_refreshLinesTree: _.debounce(function(){
            this.options.linesTree.refresh(); 
        }, 500)  

        , 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.get("linesTreeItems"), "add", this.linesTreeItemsChanged);
            this.listenTo(this.model.get("linesTreeItems"), "remove", this.linesTreeItemsChanged);
            this.listenTo(this.model.get("linesTreeItems"), "change", this.linesTreeItemsChanged);

            
        }

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

        , preRender: function () {
            app.models.subnavbar.set("dateControl", false);
            app.models.subnavbar.set("subnavbar", false);
        }

        , reRender: function () {
        }
    });

    LineProducts.Models.ProductMachineConfiguration = Backbone.Model.extend({
        defaults: {
            id: null,
            enabled: null, 
            name: null,
            productionUnitQuantity: null,
            idealCycleValue: null,
            idealCycleTime: null,
            setpointOEE: null,
        }, 
    });

    LineProducts.Collections.ProductMachineConfigurations = Backbone.Collection.extend({
        model: LineProducts.Models.ProductMachineConfiguration,
        updateItem: function (productId, productionItemId, props, success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("ProductId", "INT", productId);
            QP.Add("ProductionItemId", "INT", productionItemId);

            for (var q in props) {
                QP.Add(props[q].name, props[q].type, props[q].value);
            }

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.UpdateMachineProductConfiguration", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = _.pluck(data, 'Id');

                        if (success != null && _.isFunction(success))
                            success.call(this, that, ids);
                    } else {
                        if (error != null && _.isFunction(error))
                            error.call(this, that);
                    }
                },
                onError: function (data) {
                    if (error != null && _.isFunction(error))
                        error.call(this, that); 
                }, 
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        }, 
    }); 

    LineProducts.Models.ProductConfiguration = Backbone.Model.extend({
        defaults: {
            id: null,
            name: null,
            lineProductionItemId: null, 
            setpointOEE: null, 
            hasBatchOpened: null,

            productMachineConfigurations: null, 
        }, 
        initialize: function () {
            var opts = { loaded: false, prevfetchopts: {} }; 
            this.options = _.extend(this.options ? this.options : {}, opts);

            this.attributes.productMachineConfigurations = new LineProducts.Collections.ProductMachineConfigurations();
        }
        , fetch: function (options) {
            var that = this; 

            var QP = new QueryParameters();
            if (options.data) {
                this.options.prevfetchopts = options.data;

                if (options.data.id) QP.Add("Id", "INT", options.data.id);
                if (options.data.lineProductionItemId) QP.Add("LineProductionItemId", "INT", options.data.lineProductionItemId);
            }

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetProductConfiguration", QP, {
                onSuccess: function (data) {
                    if (data && data.Table && data.Table[0] && data.Table1) {
                        var productInfo = data.Table[0];
                        var machinesInfo = data.Table1; 

                        var productConfiguration = _.extend({}, _.omit(that.attributes, 'productMachineConfigurations'), {
                            id: productInfo.Id,
                            lineProductionItemId: productInfo.LineProductionItemId, 
                            name: productInfo.Name,
                            setpointOEE: productInfo.SetpointOEE,
                            hasBatchOpened: productInfo.HasBatchOpened,
                        });

                        var productMachineConfigurations = _.map(machinesInfo, function (m) {
                            return {
                                id: m.ProductionItemId,
                                enabled: m.Enabled, 
                                name: m.Name,
                                productionUnitQuantity: m.ProductionUnitQuantity,
                                idealCycleValue: m.IdealCycleValue,
                                idealCycleTime: m.IdealCycleTime,
                                setpointOEE: m.SetpointOEE,
                            };
                        });

                        that.options.loaded = true;
                        that.set(productConfiguration, { from: "fetch" });
                        that.get("productMachineConfigurations").set(productMachineConfigurations, { from: "fetch" }); 
                    }
                },
                Async: true,
                Secured: true
            }, app.ConnectionStrings.app);
        },
        saveProductConfiguration: function (success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("Id", "INT", this.get("id"));
            QP.Add("LineProductionItemId", "INT", this.get("lineProductionItemId"));

            QP.Add("SetpointOEE", "INT", parseInt(this.get("setpointOEE"), 10)); 

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.UpdateLineProductConfiguration", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = _.map(data, function (m) {
                            return { lineProductionItemId: m["LineProductionItemId"], productId: m["ProductId"], }; 
                        }); 

                        if (success != null && _.isFunction(success))
                            success.call(this, that, ids);
                    } else {
                        if (error != null && _.isFunction(error))
                            error.call(this, that);
                    }
                },
                onError: function (data) {
                    if (error != null && _.isFunction(error))
                        error.call(this, that);
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        }, 
    });

    LineProducts.Views.ProductConfiguration = Backbone.Epoxy.View.extend({
        template: "line-products"
        , id: "line-products"
        , title: "Line Products"
        //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
        , bindings: "data-bind"
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

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

            this.options.MYREFERENCES.subviews = {};

            this.options.grids = {
                productMachineConfigurations: null, 
            }; 

            this.bindEvents();
        },

        events: {
        },

        render: function (container, viewParams) {
            var that = this;
            var thatContainer = this.options.container;

            //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 + "OEEConfiguration/line-products/";

            if (this.model.options.loaded) {
                T.render.call(this, this.template, function (tmp) {
                    //getInternationalizationData
                    if (!that.options.i18n) that.options.i18n = {};
                    app.getI18NJed(that, that.template, function (i18nJED) {
                        //storing internationalization data
                        if (!that.options.i18n[that.template])
                            that.options.i18n[that.template] = i18nJED;

                        //loading the view and appeding it to the views's $el.
                        that.$el.html(tmp(that.model.toJSON()));

                        that.applyBindings(); 

                        var columns = [
                            {
                                name: "enabled",
                                label: app.translate(that, "enabled_label"),
                                editable: false,
                                sortable: false,
                                cell: Backgrid.Cell.extend({
                                    template: _.template("<input class='enable-checkbox' tabindex='-1' type='checkbox' />"),
                                    initialize: function () {
                                        Backgrid.Cell.prototype.initialize.apply(this, arguments);
                                    },
                                    events: {
                                        "change .enable-checkbox": "chkboxChanged",
                                    },
                                    chkboxChanged: function (e) {
                                        this.model.set("enabled", $(e.target).is(":checked"));
                                    }, 
                                    render: function () {
                                        this.$el.html(this.template());

                                        if (this.model.get("enabled"))
                                            this.$el.find(".enable-checkbox").attr("checked", "checked");

                                        this.delegateEvents();
                                        return this;
                                    },
                                    className: "align-center-cell enabled",
                                }), 
                            }, 
                            {
                                name: "name",
                                editable: false,
                                sortable: false, 
                                label: app.translate(that, "name_label"),
                                cell: Backgrid.StringCell.extend({
                                    className: "string-cell align-center-cell"
                                })
                            }, 
                            {
                                name: "productionUnitQuantity",
                                editable: true,
                                sortable: false, 
                                label: app.translate(that, "productionUnitQuantity_label"),
                                cell: Backgrid.NumberCell.extend({
                                    className: "number-cell align-center-cell",
                                    render: function () {
                                        Backgrid.NumberCell.prototype.render.apply(this, arguments);
                                        if (!_.isNumber(this.model.get(this.column.get("name")))) {
                                            this.$el.css("background-color", "#D0FCFE");
                                        } else {
                                            this.$el.css("background-color", "");
                                        }
                                        return this;
                                    },
                                }),
                                headerCell: Backgrid.HeaderCell.extend({
                                    render: function () {
                                        Backgrid.HeaderCell.prototype.render.apply(this, arguments);

                                        var help_icon = $('<div style="display:inline-block;margin-left:2px;height:20px;width:20px;cursor:pointer;"><i class="fa fa-info-circle"></i></div>');
                                        help_icon.tooltip({
                                            title: app.translate(that, "productionUnitQuantity_tooltip_help_text"),
                                            placement: "right", 
                                        }); 
                                        this.$el.append(help_icon); 
                                        return this;
                                    },
                                }),
                            },
                            {
                                name: "idealCycleValue",
                                editable: true,
                                sortable: false, 
                                label: app.translate(that, "idealCycleValue_label"),
                                cell: Backgrid.NumberCell.extend({
                                    className: "number-cell align-right-cell",
                                    render: function () {
                                        Backgrid.NumberCell.prototype.render.apply(this, arguments);
                                        if (!_.isNumber(this.model.get(this.column.get("name")))) {
                                            this.$el.css("background-color", "#D0FCFE");
                                        } else {
                                            this.$el.css("background-color", "");
                                        }
                                        return this;
                                    }, 
                                }),
                                headerCell: Backgrid.HeaderCell.extend({
                                    render: function () {
                                        Backgrid.HeaderCell.prototype.render.apply(this, arguments);
                                        this.$el.attr("colspan", 2);
                                        var help_icon = $('<div style="display:inline-block;margin-left:2px;height:20px;width:20px;cursor:pointer;"><i class="fa fa-info-circle"></i></div>');
                                        help_icon.tooltip({
                                            title: app.translate(that, "productionRate_tooltip_help_text"),
                                            placement: "right",
                                        });
                                        this.$el.append(help_icon);

                                        return this;
                                    }, 
                                }),
                            },
                            {
                                name: "idealCycleTime",
                                label: app.translate(that, "idealCycleTime_label"),
                                editable: true,
                                sortable: false,
                                headerCell: Backgrid.HeaderCell.extend({
                                    render: function () {
                                        Backgrid.HeaderCell.prototype.render.apply(this, arguments);
                                        this.$el.attr("colspan", 0);
                                        this.$el.css("display", "none"); 
                                        return this;
                                    },
                                }),
                                cell: Backgrid.SelectCell.extend({
                                    optionValues: [
                                        [app.translate(that, "select_option_label"), "-1"],
                                        [app.translate(that, "second_label"), "SECOND"],
                                        [app.translate(that, "minute_label"), "MINUTE"], 
                                        [app.translate(that, "hour_label"), "HOUR"], 
                                    ],
                                    formatter: _.extend({}, Backgrid.SelectFormatter.prototype, {
                                        fromRaw: function (rawValue, model) {
                                            return _.isArray(rawValue) ? rawValue : rawValue != null ? [rawValue.toString()] : ['-1'];
                                        },
                                        toRaw: function (formattedValue, model) {
                                            try {
                                                if (formattedValue != '-1') return formattedValue;
                                                else return model.get("idealCycleTime");
                                            } catch (error) {
                                                return undefined;
                                            }
                                        },
                                    }),
                                    render: function () {
                                        Backgrid.SelectCell.prototype.render.apply(this, arguments);
                                        this.$el.css("text-align", "left");
                                        this.$el.text("/ " + this.$el.text());

                                        if (!this.model.get(this.column.get("name"))) {
                                            this.$el.css("background-color", "#D0FCFE");
                                        } else {
                                            this.$el.css("background-color", "");
                                        }

                                        return this; 
                                    }, 
                                    className: "select-cell align-left-cell", 
                                }),
                            },
                            {
                                name: "setpointOEE",
                                editable: true,
                                sortable: false,
                                label: app.translate(that, "setpoint_oee_label"),
                                cell: Backgrid.IntegerCell.extend({
                                    className: "number-cell align-center-cell",
                                    formatter: _.extend({}, Backgrid.SelectFormatter.prototype, {
                                        fromRaw: function (rawValue, model) {
                                            return (_.isNumber(parseInt(rawValue, 10)) && !isNaN(parseInt(rawValue, 10))) ? rawValue + " %" : '';
                                        },
                                        toRaw: function (formattedValue, model) {
                                            try {
                                                return parseInt(formattedValue, 10); 
                                            } catch (error) {
                                                return undefined;
                                            }
                                        },
                                    }),
                                })
                            },
                        ];

                        var grid = that.options.grids.productMachineConfigurations = new Backgrid.Grid({
                            className: "backgrid table",
                            columns: columns,
                            collection: that.model.get("productMachineConfigurations"),
                        });

                        that.$el.find(".product-machine-configurations-grid").append(grid.render().el);

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

                        //end:

                    }, true, customPath);
                }, customPath, "machine_configuration");
            } else {
                setTimeout(function () {
                    if (!that.model.options.loaded) {
                        that.$el.html('<div style="text-align:center;margin-top:10px;"><i class="fa fa-5x fa-cog fa-spin"></i><br /></div>');
                        that.append(thatContainer, that.$el);
                    }
                }, 300); 
            }
        }

        , 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;
            }
        }

        , reRender: function (viewParams) {
            try {
            } catch (Error) { }
        }

        , refresh: function (viewParams) {
            this.model.fetch({
                data: this.options.prevfetchopts,
            }); 
        }

        , checkRender: function (a, b, c) {
            var fromFetch = (b && b.from == "fetch") ? true : false;
            if (fromFetch) {
                this.render();
            }
        }

        , productMachineConfigurationChanged: function (m, b, c) {
            var that = this; 
            var fromFetch = (b && b.from == "fetch") ? true : false;
            if (!fromFetch) {
                m.collection.updateItem(this.model.get("id"), m.get("id"),
                    [
                        { name: "Enabled", type: "BIT", value: m.get("enabled") },
                        { name: "ProductionUnitQuantity", type: "FLOAT", value: m.get("productionUnitQuantity") },
                        { name: "IdealCycleValue", type: "FLOAT", value: m.get("idealCycleValue") },
                        { name: "IdealCycleTime", type: "VARCHAR", value: m.get("idealCycleTime") },
                        { name: "SetpointOEE", type: "VARCHAR", value: m.get("setpointOEE") },
                    ],
                    function (data) {
                        that.refresh(); 
                    }, function (data) {
                        that.refresh();
                    }
                );
            }
        }

        , lineProductConfigurationChanged: function (a, b, c) {
            var that = this;
            var fromFetch = (c && c.from == "fetch") ? true : false;
            if (!fromFetch) {
                this.model.saveProductConfiguration();
            }
        }

        , 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.checkRender);
            this.listenTo(this.model.get("productMachineConfigurations"), "change", this.productMachineConfigurationChanged);
            this.listenTo(this.model, "change:setpointOEE", this.lineProductConfigurationChanged, 500);
        }

        , 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.options.MYREFERENCES.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.options.MYREFERENCES.subviews, function (sview) {
                sview.show();
            });
        }

        , resetModel: function () {
            this.model.set(this.model.defaults);
        }

        , hide: function () {
            this.options.state = app.view_states.hidden;

            this.resetModel();
            this.hideSubviews();

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

        , hideSubviews: function () {
            _.each(this.options.MYREFERENCES.subviews, function (sview) {
                sview.hide();
            });
        }

        , preRender: function () {
            app.models.subnavbar.set("dateControl", false);
            app.models.subnavbar.set("dateTimeScopeControl", false);
            app.models.subnavbar.set("sections", "4-4-4");
            app.models.subnavbar.set("subnavbar", true);
        }
    });

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

});
