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

  "Mousetrap",

  "js/jstree/jstree",

],

function (app, T, Modal, Mousetrap) {

    var TREE_NODE_ROOT_ID = -2;

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

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

    OEEConfiguration.Models.TreeItems = Backbone.Collection.extend({
        model: OEEConfiguration.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.GetProductionItemsTree", 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,
                                order: itemData.Order - 1,
                                enabled: itemData.Enabled,
                                data: {
                                    enabled: itemData.Enabled,
                                }
                            };

                            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 () {
            //this.listenTo(this, "add", this.syncToDB);
            //this.listenTo(this, "remove", this.syncToDB);
            //this.listenTo(this, "change", this.syncChangeToDB);
        },
        syncChangeToDB: function (a, b, c) {
            var from = (c && c.from) ? c.from : "unknown";
            if (from != "fetch") {
                if (a && a.changed && a.changed["text"]) {
                    this.upsertItem(a.get("id"), [
                        { name: "Name", type: "VARCHAR", value: a.get("text") }
                    ]);
                }
            }
        },
        upsertItem: function (id, props, success, error) {
            var that = this;
            var QP = new QueryParameters();
            QP.Add("Id", "INT", id);

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

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.UpsertProductionItem", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        //var ids = [];

                        if (data && data.length > 0 && data[0].Status && data[0].Status == "FAILURE") {
                            var failureCode = "UNKNOWN";
                            failureCode = (data[0].Code) ? data[0].Code : failureCode;

                            if (error != null && _.isFunction(error))
                                error.call(this, that, failureCode);
                        } else {
                            //ids = _.pluck(data, 'Id');

                            //if (success != null && _.isFunction(success))
                            //    success.call(this, that, ids);

                            var itemData = data[0];

                            var item = {
                                id: itemData.Id,
                                parent: ((itemData.ParentId != null) && (itemData.ParentId != -1))
                                            ? itemData.ParentId
                                            : TREE_NODE_ROOT_ID,
                                type: itemData.Type.toLowerCase(),
                                text: itemData.Name,
                                order: itemData.Order - 1,
                                enabled: itemData.Enabled,
                                data: {
                                    enabled: itemData.Enabled,
                                }
                            };

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

            QP.Add("@Id", "INT", id);

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

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.RemoveProductionItem", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = [];

                        if (data && data.length > 0 && data[0].Status && data[0].Status == "FAILURE") {
                            var failureCode = "UNKNOWN";
                            failureCode = (data[0].Code) ? data[0].Code : failureCode;

                            if (error != null && _.isFunction(error))
                                error.call(this, that, failureCode);
                        } else {
                            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);
        },
        enableItem: function (id, props, success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("@Id", "INT", id);

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

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.EnableProductionItem", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = [];

                        if (data && data.length > 0 && data[0].Status && data[0].Status == "FAILURE") {
                            var failureCode = "UNKNOWN";
                            failureCode = (data[0].Code) ? data[0].Code : failureCode;

                            if (error != null && _.isFunction(error))
                                error.call(this, that, failureCode);
                        } else {
                            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);
        },
        reorderItem: function (id, parent, order, success, error) {
            var that = this;
            var QP = new QueryParameters();

            QP.Add("@Id", "INT", id);
            QP.Add("@ParentId", "INT", parent);
            QP.Add("@Order", "INT", order);

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.MoveProductionItem", 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 (text, parent, type, position, success, error) {
            var that = this;
            this.upsertItem(null, [
                { name: "ParentId", type: "INT", value: (parent == "#") ? null : parent },
                { name: "Type", type: "VARCHAR", value: type },
                { name: "Name", type: "VARCHAR", value: text },
            ], function (ref, item) {
                that.add(item);

                if (success && _.isFunction(success))
                    success.call(this, that, item);
            },
            //], function (ref, ids) {
                //that.add({
                //    id: ids[0],
                //    parent: ((parent != null) && (parent != "#") && (parseInt(parent, 10) != -1))
                //                ? parseInt(parent, 10)
                //                : TREE_NODE_ROOT_ID,
                //    type: type,
                //    text: text,
                //    order: position,
                //    enabled: true,
                //    data: {
                //        enabled: true,
                //    },
                //});

                //if (success && _.isFunction(success))
                //    success.call(this, that, ids);
            //},
            function (ref, code) {
                if (error && _.isFunction(error))
                    error.call(this, that, code);
            });
        },
        renameNode: function (id, text, success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.upsertItem(id, [
                    { name: "Name", type: "VARCHAR", value: text }
                ], function (ref, item) {
                    if (item.id == parseInt(id, 10)) {
                        model.set("text", item.text);

                        if (success && _.isFunction(success))
                            success.call(this, that, item);
                    }
                    //if (_.indexOf(ids, parseInt(id)) != -1) {
                    //    model.set("text", text);

                    //    if (success && _.isFunction(success))
                    //        success.call(this, that, ids);
                    //}
                    else {
                        if (error && _.isFunction(error))
                            error.call(this, that);
                    }
                }, function (ref) {
                    if (error && _.isFunction(error))
                        error.call(this, that);
                });
            } else {
                if (error && _.isFunction(error))
                    error.call(this, that);
            }
        },
        deleteNode: function (id, checkUnusedBatches, checkHasData, success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.deleteItem(
                    id,
                    [
                        { name: "CheckUnusedBatches", type: "BIT", value: _.isBoolean(checkUnusedBatches) ? checkUnusedBatches : false },
                        { name: "CheckHasData", type: "BIT", value: _.isBoolean(checkHasData) ? checkHasData : false },
                    ]
                    , function (ref, ids) {
                        //Comment out remove from coll because this will be done by a refresh later.
                        ////removing from collection; 
                        //that.remove(model);

                        if (success && _.isFunction(success))
                            success.call(this, that, ids);
                    },
                    function (ref, code) {
                        if (error && _.isFunction(error))
                            error.call(this, that, code);
                    }
                );
            }
        },
        enableNode: function (id, success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.enableItem(
                    id,
                    [
                    ]
                    , function (ref, ids) {
                        if (success && _.isFunction(success))
                            success.call(this, that, ids);
                    },
                    function (ref, code) {
                        if (error && _.isFunction(error))
                            error.call(this, that, code);
                    }
                );
            }
        },
        reorderNode: function (id, parent, order, success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.reorderItem(id, parent, order, function (ref, ids) {
                    if (_.indexOf(ids, parseInt(id)) != -1) {
                        //model.set({
                        //    parent: (parent == "#") ? '#' : parseInt(parent),
                        //    order: order,
                        //});

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

    OEEConfiguration.Models.Main = Backbone.Model.extend({
        defaults: {
            procedure: '',
            linesTreeItems: null,
        },
        initialize: function () {
            this.set("linesTreeItems", new OEEConfiguration.Models.TreeItems());
        },
    });

    //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.
    OEEConfiguration.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "oee-configuration";
        } catch (Error) { }
    }

    OEEConfiguration.Views.Main = Backbone.View.extend({
        template: "oee-configuration"
        , id: "oee-configuration"
        , title: "OEE 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: 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 OEEConfiguration.Models.Main({
                procedure: "dbo.procedureName"
            });

            this.model = model;

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

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

            this.bindEvents();
            _.bindAll(this);
        },

        events: {
            "click .btn-add-area": "addArea",
            "click .btn-add-line": "addLine",
            "click .btn-add-machine": "addMachine",
        },

        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/oee-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;
                    //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());

                    //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();

                                //setting disabled nodes
                                _.each(data, function (t) { t.li_attr = { "class": (t.enabled) ? "" : "node-disabled" } });

                                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']
                            },
                            "line": {
                                "icon": "fa fa-sitemap",
                                valid_children: ['machine'],
                            },
                            "machine": {
                                "icon": "fa fa-cog",
                                max_children: 0
                            },
                            "loading": {
                                "icon": "fa fa-spinner fa-spin",
                                valid_children: ['area', 'line', 'machine'],
                            },
                        },
                        contextmenu: {
                            items: that.customLinesTreeCtxMenu,
                        },
                        sort: function (a, b) {
                            var nodea = this.get_node(a);
                            var nodeb = this.get_node(b);

                            var collection = that.model.get("linesTreeItems");
                            var model_a = collection.get(nodea.id);
                            var model_b = collection.get(nodeb.id);

                            if (model_a && model_b)
                                return model_a.get("order") > model_b.get("order") ? 1 : -1;
                            else if (model_a) return -1;
                            else if (model_b) return 1;
                            else return -1;
                        },
                        plugins: [
                            "contextmenu",
                            "dnd", //Drag and drop
                            "wholerow",
                            "types",
                            "sort",
                        ],
                    });

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

                    that.$el.find(".tree").bind({
                        "rename_node.jstree": that.onRenameNode,
                        "create_node.jstree": that.onCreateNode,
                        //"delete_node.jstree": that.onDeleteNode,
                        //"enable_node.jstree": that.onEnableNode, 
                        "move_node.jstree": that.onMoveNode,
                        "select_node.jstree": that.onSelectNode,
                        "deselect_node.jstree": that.onDeselectNode,
                        "deselect_all.jstree": that.onDeselectNode,
                        "refresh.jstree": _.once(function () {
                            that.$el.find(".tree").jstree("open_all");
                        }),
                    });

                    //that.options.MYREFERENCES.subviews.machineConfiguration.view = new OEEConfiguration.Views.MachineConfiguration({
                    //    container: that.$el.find(".machine-configuration-container"),
                    //    model: new OEEConfiguration.Models.MachineConfiguration(), 
                    //}); 

                    //that.options.MYREFERENCES.subviews.machineConfiguration.view.render(); 

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

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

        , customLinesTreeCtxMenu: function (node) {
            var that = this;

            //Return empty if node is disabled (disabled here means the jstree disabled, not the production item disabled status).
            if (node.state.disabled == true)
                return [];

            // The default set of all items
            var items = {
                createAreaItem: {
                    label: "Add Area",
                    action: this.addArea,
                },
                createLineItem: {
                    label: "Add Line",
                    action: this.addLine,
                },
                createMachineItem: {
                    label: "Add Machine",
                    action: this.addMachine,
                },
                renameItem: {
                    label: "Rename",
                    action: function (obj) {
                        that.renameNode(node);
                    },
                },
                deleteItem: {
                    label: "Delete",
                    action: function (obj) {
                        that.deleteNode(node);
                    },
                },
                enableItem: {
                    label: "Enable",
                    action: function (obj) {
                        that.enableNode(node);
                    }
                }
            };

            switch (node.type.toUpperCase()) {
                case "AREA":
                    delete items["createAreaItem"];
                    delete items["createMachineItem"];
                    break;
                case "LINE":
                    delete items["createAreaItem"];
                    delete items["createLineItem"];
                    break;
                case "MACHINE":
                    delete items["createAreaItem"];
                    delete items["createLineItem"];
                    delete items["createMachineItem"];
                    break;
                case "ROOT":
                    delete items["createMachineItem"];
                    delete items["deleteItem"];
                    delete items["enableItem"];
                    delete items["renameItem"];
                    break;
            }

            //if (node.type != "line") {
            //    delete items["createItem"]; 
            //}

            if (node && node.data && !node.data.enabled) {
                delete items["createAreaItem"];
                delete items["createLineItem"];
                delete items["createMachineItem"];
                delete items["deleteItem"];
            } else {
                delete items["enableItem"];
            }

            return items;
        }

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


            //If parent is equals to TREE_NODE_ROOT_ID it is neccesary change it to a valid value. But the right value will depends
            //on the type of the item moved. If the item moved is a line, change parent to -1 to move it under
            //the internal area. If the item moved is an area, change parent to null because area do not have parent.
            if (node.parent != TREE_NODE_ROOT_ID) {
                parent = node.parent;
            }
            else {
                //if (node.type == "machine")
                //    parent = node.parent;
                if (node.type == "line")
                    parent = -1;
                else if (node.type == "area")
                    parent = null;
            }

            this.setTreeLoadingState(true);

            try {
                collection.addNode(node.text, parent, node.type, obj.position + 1, function (ref, item) {
                    instance.set_id(node, item.id);
                    //instance.set_id(node, ids[0]);
                    node.data = { enabled: true, }

                    that.setTreeLoadingState(false);

                    instance.edit(node);

                    app.models.appController.set("menuChanged", true);
                }, function (ref, code) {
                    var errorCode = 'UNKNOWN';
                    errorCode = code && _.isString(code) && code.length > 0 ? code : errorCode;

                    app.views.topMessages.showMessage(app.translate(that, errorCode.toString() + "_error_code_message"));
                    instance.refresh(true);
                });
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);
            }
        }

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

            this.setTreeLoadingState(true);

            try {
                collection.renameNode(node.id, node.text, function (ref, item) {
                    instance.set_id(node, item.id);
                    //instance.set_id(node, ids[0]);

                    that.setTreeLoadingState(false);

                    app.models.appController.set("menuChanged", true);
                }, function () {
                    instance.refresh(true);
                });
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);
            }
        }

        //, onDeleteNode: function (e, obj) {
        //    var that = this;
        //    if (this.options.MYREFERENCES.subviews.machineConfiguration.view)
        //        this.options.MYREFERENCES.subviews.machineConfiguration.view.close();

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

        //    var collection_deleteNode = function (checkUnopenedBatches, checkHasData) {
        //        collection.deleteNode(node.id, checkUnopenedBatches, checkHasData, function (ref, ids) {
        //            instance.refresh();

        //            app.models.appController.set("menuChanged", true);
        //        }, function (ref, code) {
        //            var errorCode = 'UNKNOWN';
        //            errorCode = code && _.isString(code) && code.length > 0 ? code : errorCode;

        //            if (errorCode == "HASUNOPENEDBATCHES") {
        //                showUnopenedBatchesModal();
        //            } else {
        //                app.views.topMessages.showMessage(app.translate(that, errorCode.toString() + "_error_code_message"));
        //            }

        //            instance.refresh();
        //        });
        //    }

        //    var showUnopenedBatchesModal = function () {
        //        var that = this;
        //        var modal = new Modal.Views.Main({
        //            id: "has-unopened-batches",
        //            title: app.translate(that, "unopened_batches_modal_title"),
        //            message: app.translate(that, "unopened_batches_modal_body"),
        //            allowCancel: true,
        //            buttons_type: "CONTINUE-CANCEL"
        //        });

        //        modal.on("continue", function () {
        //            collection_deleteNode(false, false);
        //        });

        //        modal.show();
        //    };

        //    collection_deleteNode(true, false);
        //}

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

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

            this.setTreeLoadingState(true);            

            try {
                var collection = this.model.get("linesTreeItems");
                collection.enableNode(node.id, function (ref, ids) {
                    instance.refresh(true);

                    app.models.appController.set("menuChanged", true);
                }, function (ref, code) {
                    var errorCode = 'UNKNOWN';
                    errorCode = code && _.isString(code) && code.length > 0 ? code : errorCode;

                    app.views.topMessages.showMessage(app.translate(that, errorCode.toString() + "_error_code_message"));
                    instance.refresh(true);
                });
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);
            }
        }

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

            //If parent is equals to TREE_NODE_ROOT_ID it is neccesary change it to a valid value. But the right value will depends
            //on the type of the item moved. If the item moved is a line, change parent to -1 to move it under
            //the internal area. If the item moved is an area, change parent to null because area do not have parent.
            if (node.parent != TREE_NODE_ROOT_ID) {
                parent = node.parent;
            }
            else {
                //if (node.type == "machine")
                //    parent = node.parent;
                if (node.type == "line")
                    parent = -1;
                else if (node.type == "area")
                    parent = null;
            }

            this.setTreeLoadingState(true);

            try {
                collection.reorderNode(node.id, parent, obj.position + 1, function (ref, ids) {
                    //instance.refresh(true); 
                    that._autoRefresh({ action: 'MOVE', });
                }, function () {
                    instance.refresh(true);
                });
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);
            }
        }

        , onSelectNode: function (e, obj) {
            //Select node event is fired event for right click. We don't want that because
            //we don't want to refresh item selected data on right click. So return if it is
            //right click.
            
            //Right click = 2. Also check if 'obj.event.button' because select node also is fired by
            //keyboard. In that case 'obj.event.button' is undefined. Also 'obj.event' can be undefined (but don't know why!).
            if ((obj.event) && (obj.event.button) && (obj.event.button == 2))
                return;

            this.checkAddLineMachineButtons(e, obj);

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

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

            if (obj.selected.length < 2) {
                if (node.type == "machine" && (node && node.data && node.data.enabled)) {
                    var machineConfigurationContainer = this.$el.find(".machine-configuration-container");

                    var model = new OEEConfiguration.Models.MachineConfiguration(null, {
                        parent: that,
                    });

                    this.options.MYREFERENCES.subviews.machineConfiguration.view = new OEEConfiguration.Views.MachineConfiguration({
                        container: machineConfigurationContainer,
                        model: model,
                        parent: that,
                    });

                    model.fetch({
                        data: {
                            id: node.id,
                        }
                    });

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

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

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

        , setTreeLoadingState: function (isLoading) {
            var tree = this.options.linesTree;

            var rootNode = tree.get_node(TREE_NODE_ROOT_ID);

            if (isLoading == true) {
                tree.set_type(rootNode, 'loading');

                $('.tree li').each(function () {
                    tree.disable_node(this.id);
                });
            }
            else {
                tree.set_type(rootNode, 'root');

                $('.tree li').each(function () {
                    tree.enable_node(this.id);
                });
            }
        }

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

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

            if (data) {
                tree.edit((data.id) ? data.id : data);
            }
        }

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

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

            //tree.delete_node(data);

            var that = this;
            if (this.options.MYREFERENCES.subviews.machineConfiguration.view)
                this.options.MYREFERENCES.subviews.machineConfiguration.view.close();

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

            this.setTreeLoadingState(true);

            try {
                var collection_deleteNode = function (checkUnopenedBatches, checkHasData) {
                    collection.deleteNode(node.id, checkUnopenedBatches, checkHasData, function (ref, ids) {
                        that._autoRefresh();
                        //instance.refresh(true);

                        app.models.appController.set("menuChanged", true);
                    }, function (ref, code) {
                        var errorCode = 'UNKNOWN';
                        errorCode = code && _.isString(code) && code.length > 0 ? code : errorCode;

                        if (errorCode == "HASUNOPENEDBATCHES") {
                            showUnopenedBatchesModal();
                        } else {
                            app.views.topMessages.showMessage(app.translate(that, errorCode.toString() + "_error_code_message"));
                        }

                        //that._autoRefresh();
                        instance.refresh(true);
                    });
                }

                var showUnopenedBatchesModal = function () {
                    var that = this;
                    var modal = new Modal.Views.Main({
                        id: "has-unopened-batches",
                        title: app.translate(that, "unopened_batches_modal_title"),
                        message: app.translate(that, "unopened_batches_modal_body"),
                        allowCancel: true,
                        buttons_type: "CONTINUE-CANCEL"
                    });

                    modal.on("continue", function () {
                        collection_deleteNode(false, false);
                    });

                    modal.show();
                };

                collection_deleteNode(true, false);
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);
            }
        }

        , enableNode: function (data, a, b, c) {
            var tree = this.options.linesTree;
            var selected = tree.get_selected();

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

            this.onEnableNode(null, {
                node: data,
                instance: tree,
            });
            //tree.enable_node(data); 
        }

        , addArea: function () {
            var tree = this.options.linesTree;
            var newArea = tree.create_node(null, { type: "area" });
            //if (newArea) tree.edit(newArea); 
        }

        , addLine: function () {
            //var tree = this.options.linesTree;
            //var newLine = tree.create_node(null, { type: "line" });
            ////if (newLine) tree.edit(newLine); 


            var tree = this.options.linesTree;
            var selected = tree.get_selected();
            var sel = null;
            var selected_node = null;

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

            if ((!selected_node) || (selected_node.type == "area") || (selected_node.type == "root")) {
                sel = tree.create_node(sel, { "type": "line" }, "last", function (a, b, c) {
                    a;
                });
                //if (sel) {
                //    tree.edit(sel);
                //}
            }
        }

        , addMachine: function (e, data) {
            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 (selected_node.type == "line") {
                sel = tree.create_node(sel, { "type": "machine" }, "last", function (a, b, c) {
                    a;
                });
                //if (sel) {
                //    tree.edit(sel);
                //}
            }
        }

        //, nodeDoubleClick: function (e, data) {
        //    var node = $(e.target).closest("li");
        //    var data = this.options.linesTree.get_node(node.prop("id"));

        //    if (data && data.id) {
        //        this.options.linesTree.edit(data.id);
        //    }
        //}

        , checkAddLineMachineButtons: function (e, data) {
            var btnAddArea = this.$el.find(".btn-add-area"),
                btnAddLine = this.$el.find(".btn-add-line"),
                btnAddMachine = this.$el.find(".btn-add-machine");

            switch (data.node.type.toUpperCase()) {
                case "AREA":
                    btnAddArea.prop("disabled", true);
                    btnAddLine.prop("disabled", false);
                    btnAddMachine.prop("disabled", true);
                    break;
                case "LINE":
                    btnAddArea.prop("disabled", true);
                    btnAddLine.prop("disabled", true);
                    btnAddMachine.prop("disabled", false);
                    break;
                case "MACHINE":
                    btnAddArea.prop("disabled", true);
                    btnAddLine.prop("disabled", true);
                    btnAddMachine.prop("disabled", true);
                    break;
                default:
                    btnAddArea.prop("disabled", false);
                    btnAddLine.prop("disabled", false);
                    btnAddMachine.prop("disabled", true);
                    break;
            }

            //if (data.node.type == "line") {
            //    btnAddMachine.prop("disabled", false);
            //} else {
            //    btnAddMachine.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 (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        }

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

            this.refresh(opt);

            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 (options) {
            try {
                var that = this,
                    opt = _.extend({}, options);

                this.model.get("linesTreeItems").fetch({
                    codesText: app.translate(that, "root_tree_text"),
                    callback: function () {
                        //that.options.linesTree.refresh(); 

                        //Force to set loading state to false if action is MOVE because the refresh after
                        //this transaction does not modify the collection. So callback of tree changes is not
                        //fired and laoding state and jstree objects are not refreshed. Due to that it is necessary
                        //do it here.
                        if (opt.action == 'MOVE') {
                            that.setTreeLoadingState(false);

                            that.options.linesTree.refresh(true);
                        }
                    }, 
                });
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        }

        , 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 () {
            //Force to set loading state to false. Maybe it is not necessary all the times
            //but some transactions do not set loading state to false because they call for a refresh.
            this.setTreeLoadingState(false);

            this.options.linesTree.refresh(true);
        }, 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 () {
        }
    });

    OEEConfiguration.Models.MachineConfiguration = Backbone.Epoxy.Model.extend({
        initialize: function (attrs, opts1) {
            var opts = { loaded: false, };
            this.options = _.extend(this.options ? this.options : {}, opts, opts1);
        }
        , fetch: function (options) {
            var that = this;

            var QP = new QueryParameters();
            if (options.data) {
                if (options.data.id) QP.Add("ProductionItemId", "INT", options.data.id);
            }

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetMachineConfiguration", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table.0")) {
                        var machineData = data.Table[0];
                        var tagList = data.Table1;
                        var delayCodes = data.Table2;

                        var tagsBinding = _.map(tagList, function (obj) { return { label: obj.Name, value: obj.Id }; });
                        var tagsBindingReal = _.map(_.where(tagList, { DataType: 'REAL' }), function (obj) { return { label: obj.Name, value: obj.Id }; });
                        var tagsBindingDigital = _.map(_.where(tagList, { DataType: 'DIGITAL' }), function (obj) { return { label: obj.Name, value: obj.Id }; });
                        var delayCodesBinding = _.map(delayCodes, function (obj) {
                            return {
                                label: ((obj.Id == -2) ? app.translate(that.options.parent, obj.Name) : obj.Name),
                                value: obj.Id
                            };
                        });

                        var machineConfiguration = _.extend({}, that.attributes, {
                            id: machineData.Id,
                            name: machineData.Name,
                            hasBatchOpened: machineData.HasBatchOpened,

                            runningTagId: machineData.RunningTagId,
                            runningTagAscendingFlank: machineData.RunningTagAscendingFlank,

                            unitProducedTagId: machineData.UnitProducedTagId,
                            unitProducedTagAscendingFlank: machineData.UnitProducedTagAscendingFlank,
                            unitProducedTagResetsAt: machineData.UnitProducedTagResetsAt,

                            badUnitProducedTagId: machineData.BadUnitProducedTagId,
                            badUnitProducedTagAscendingFlank: machineData.BadUnitProducedTagAscendingFlank,
                            badUnitProducedTagResetsAt: machineData.BadUnitProducedTagResetsAt,
                            badUnitProducedManualEnabled: machineData.BadUnitProducedManualEnabled,
                            badUnitProducedManualUnits: machineData.BadUnitProducedManualUnits,

                            unitProducedIncludesBadUnits: machineData.UnitProducedIncludesBadUnits,

                            maintenanceModeTagId: machineData.MaintenanceModeTagId,
                            maintenanceModeTagAscendingFlank: machineData.MaintenanceModeTagAscendingFlank,
                            maintenanceModeDelayCodeId: machineData.MaintenanceModeDelayCodeId,

                            microDelayValue: machineData.MicroDelayValue,
                            microDelayTime: machineData.MicroDelayTime,

                            tags: tagList,
                            tagsBinding: tagsBinding,
                            tagsBindingDigital: tagsBindingDigital,
                            tagsBindingReal: tagsBindingReal,
                            delayCodesBinding: delayCodesBinding,
                        });

                        that.options.loaded = true;

                        that.set(machineConfiguration, { from: "fetch" });
                    }
                },
                Secured: true
            }, app.ConnectionStrings.app);
        }
        , defaults: {
            id: null,
            name: null,

            runningTagId: null,
            runningTagAscendingFlank: null,

            unitProducedTagId: null,
            unitProducedTagAscendingFlank: null,
            unitProducedTagResetsAt: null,

            badUnitProducedTagId: null,
            badUnitProducedTagAscendingFlank: null,
            badUnitProducedTagResetsAt: null,
            badUnitProducedManualEnabled: null,
            badUnitProducedManualUnits: null,

            maintenanceModeTagId: null,
            maintenanceModeTagAscendingFlank: null,
            maintenanceModeDelayCodeId: null,

            microDelayValue: null,
            microDelayTime: null,

            //behind the scenes
            tags: [],
            tagsBinding: [],
            tagsBindingDigital: [],
            tagsBindingReal: [],
            delayCodesBinding: [],
        }
        , save: function (opt) {
            var that = this;
            var options = {
                callback: function () { }
            };

            _.extend(options, opt);

            var QP = new QueryParameters();

            var params = [
                ["@Id", "INT", "id"],
                ["@RunningTagId", "INT", "runningTagId"],
                ["@RunningTagAscendingFlank", "BIT", "runningTagAscendingFlank"],
                ["@UnitProducedTagId", "INT", "unitProducedTagId"],
                ["@UnitProducedTagAscendingFlank", "INT", "unitProducedTagAscendingFlank"],
                ["@UnitProducedTagResetsAt", "INT", "unitProducedTagResetsAt"],
                ["@UnitProducedIncludesBadUnits", "BIT", "unitProducedIncludesBadUnits"],
                ["@BadUnitProducedTagId", "INT", "badUnitProducedTagId"],
                ["@BadUnitProducedTagAscendingFlank", "INT", "badUnitProducedTagAscendingFlank"],
                ["@BadUnitProducedTagResetsAt", "INT", "badUnitProducedTagResetsAt"],
                ["@BadUnitProducedManualEnabled", "BIT", "badUnitProducedManualEnabled"],
                ["@BadUnitProducedManualUnits", "VARCHAR", "badUnitProducedManualUnits"],
                ["@MaintenanceModeTagId", "INT", "maintenanceModeTagId"],
                ["@MaintenanceModeTagAscendingFlank", "INT", "maintenanceModeTagAscendingFlank"],
                ["@MaintenanceModeDelayCodeId", "INT", "maintenanceModeDelayCodeId"],
                ["@MicroDelayValue", "FLOAT", "microDelayValue"],
                ["@MicroDelayTime", "VARCHAR", "microDelayTime"],
            ];

            for (var i = 0, len = params.length; i < len; i++) {
                var param = params[i];
                QP.Add(param[0], param[1], this.get(param[2]));
            }

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.UpdateProductionItem", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table.0")) {
                        if (options.callback != null && _.isFunction(options.callback))
                            options.callback.call(this, that);
                    }
                },
                Async: true,
                Secured: true
            }, app.ConnectionStrings.app);
        },
        computeds: {
            runningTag: {
                get: function () {
                    return this.get("runningTagId");
                },
                set: function (val) {
                    return { runningTagId: (val != -1) ? parseInt(val) : null };
                }
            },
            unitProducedTagType: {
                deps: ["unitProducedTagId"],
                get: function () {
                    var tagid = this.get("unitProducedTagId");
                    var tag = _.findWhere(this.get("tags"), { Id: tagid });
                    if (_.isObject(tag)) {
                        return tag.DataType;
                    }
                    return null;
                },
            },
            badUnitProducedTagType: {
                deps: ["badUnitProducedTagId"],
                get: function () {
                    var tagid = this.get("badUnitProducedTagId");
                    var tag = _.findWhere(this.get("tags"), { Id: tagid });
                    if (_.isObject(tag)) {
                        return tag.DataType;
                    }
                    return null;
                },
            },
            unitProducedAgentType: {
                deps: ["unitProducedTagId"],
                get: function () {
                    var tagid = this.get("unitProducedTagId");
                    var tag = _.findWhere(this.get("tags"), { Id: tagid });
                    if (_.isObject(tag)) {
                        return tag.AgentType;
                    }
                    return null;
                },
            },
            badUnitProducedAgentType: {
                deps: ["badUnitProducedTagId"],
                get: function () {
                    var tagid = this.get("badUnitProducedTagId");
                    var tag = _.findWhere(this.get("tags"), { Id: tagid });
                    if (_.isObject(tag)) {
                        return tag.AgentType;
                    }
                    return null;
                },
            },
        }
    });

    OEEConfiguration.Views.MachineConfiguration = Backbone.Epoxy.View.extend({
        template: "oee-configuration"
        , id: "oee-configuration"
        , title: "OEE 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
        , 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.bindEvents();
            //_.bindAll(this);

            this.options.advancedOptions = false;
            var that = this;
            Mousetrap.bind('b a c k d o o r', function (e) {
                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    // internet explorer
                    e.returnValue = false;
                }

                that.options.advancedOptions = !that.options.advancedOptions;
                that.advopt(that.options.advancedOptions);
                return false;
            });
        },

        events: {
            "click .btn-save": "saveMachineConfiguration",
            "click .btn-cancel": "cancelMachineConfiguration",
        },

        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/oee-configuration/";

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

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

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

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

        , setSaveCancelButtons: function (val) {
            var btnSave = this.$el.find(".btn-save");
            var btnCancel = this.$el.find(".btn-cancel");

            btnSave.prop("disabled", !val);
            btnCancel.prop("disabled", !val);
        }

        , saveMachineConfiguration: function () {
            var that = this;

            this.setSaveCancelButtons(false);
            this.model.save({
                callback: function () {
                    app.views.topMessages.showMessage(app.translate(that.options.parent, "machine_configuration_saved"));
                    that.model.fetch({
                        data: {
                            id: that.model.get("id"),
                        }
                    });
                }
            });
        }

        , cancelMachineConfiguration: function () {
            this.setSaveCancelButtons(false);
            this.model.fetch({
                data: {
                    id: this.model.get("id"),
                }
            });
        }

        , checkUnitProducedFlankOpt: function () {
            var chkbox = this.$el.find("#unitProducedChkboxContainer");
            var tagid = this.model.get("unitProducedTagId");
            chkbox.css("visibility", "hidden");

            var tag = _.findWhere(this.model.get("tags"), { Id: tagid });
            if (_.isObject(tag)) {
                if (tag.DataType == 'DIGITAL') {
                    chkbox.css("visibility", "visible");
                }
            }
        }

        , advopt: function (e) {
            this.$el.find(".counter-resets-at").css('display', e ? 'block' : 'none');
        }

        , 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, "change", this.checkButtonsState);
        }

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

});
