//SCREEN-BOILERPLATE

//this boilerplate builds screens that are gonna be shown in the <div class="content"> tag of our main HTML.
//do not build app components with this boilerplate, only screens (reports)

define([
  // Application variable, always include it to have access to app methods.
  "app",

  //templates-loader: this loads templates async.
  "js/templates-loader",
  'backgrid',
  "modules/modal",
  "modules/modal2",
  'modules/elt/equipment-counter',

  "Mousetrap",

  "js/jstree/jstree",
  "js/backgrid-0.3.5/extensions/select-integer-cell/backgrid-select-integer-cell",

],

function (app, T, Backgrid, Modal, Modal2, EquipmentCounter, Mousetrap) {

    var TREE_NODE_ROOT_ID = -1;

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

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            typeId: 0,
            search: '',

            collapsed: false,

            procedure: '',

            selected: null,

            types: [],
            models: [],
            internals: [],
        },
        computeds: {
            hasTypes: {
                deps: ['types'],
                get: function (types) {
                    return types.length != 0;
                },
            },
            hasModels: {
                deps: ['models'],
                get: function (models) {
                    return models.length != 0;
                },
            },
        },
        fetchTypes: function () {
            var that = this,
                qp = new Core.Database.QueryParameters();

            qp.Add('@includeInternals', 'BIT', 0);

            qp.Add('@ihId', 'INT', app.models.ihDataSources.get("id"));

            Core.Json.CallProcedure(
                app.DatabaseNames.System + ".EQUIP.GetEquipmentTypes",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if ((resp) && (resp.Table)) {
                                var records = resp.Table;

                                var newItems = _.map(records, function (obj) { return { value: obj.Id, label: obj.Name, }; });

                                that.set("types", newItems);
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error("Server response not valid.");
                            }
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);
                    },
                    Secured: true,
                    Async: false,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
        fetchModels: function () {
            var that = this,
                qp = new Core.Database.QueryParameters();

            qp.Add('@includeInternals', 'BIT', 1);

            qp.Add('@ihId', 'INT', app.models.ihDataSources.get("id"))

            Core.Json.CallProcedure(
                app.DatabaseNames.System + ".EQUIP.GetAssignableEquipmentModels",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if ((resp) && (resp.Table)) {
                                var records = resp.Table;

                                var filter = _.where(records, { Internal: true });

                                var internals = _.map(filter, function (obj) { return { value: obj.Id, label: obj.TypeName.toUpperCase(), style: (obj.ChildHierarchyId.IsNull != true) ? 'font-weight:bold;' : '', Template: 'main' } });

                                var newItems = _.map(records, function (obj) { return { Internal: false, value: obj.Id, label: obj.TypeName, iconId: obj.IconId, typeId: obj.TypeId, style: (obj.ChildHierarchyId.IsNull != true) ? 'font-weight:bold;' : '', Template: 'main' }; });

                                that.set('internals', internals);

                                that.set("models", newItems);
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error("Server response not valid.");
                            }
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);
                    },
                    Secured: true,
                    Async: false,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
        initialize: function () {
        },
    });

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

    Screen.Views.Main = Backbone.Epoxy.View.extend({
        template: "equipments"
        , id: "equipments"
        , title: "Equipments"
        //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

        , items: null
        , currentModal: null
        , subviews: null
        , templates: null
        , initialize: function () {
            _.extend(this, this.options);

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

            var that = this;

            this.tree = null;

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

            this.templates = {
                newEquipmentModal: null,
                assignEquipmentModal: null,
                unassignEquipmentModal: null,
                machineConfiguration: null,
                createEquipment: null,
            };
            
            this.model = model;
            this.model.fetchTypes();
            this.model.fetchModels();
            
            this.items = new Screen.Models.Items();

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



            this.subviews = {
                machineConfiguration: {
                    view: null,
                    model: null
                },
                createEquipment: {
                    view: null,
                    model: null,
                },
                subnavbarControls: new Screen.Views.SubnavBarControls({
                    model: this.model,
                    parent: this,
                    container: app.views.subnavbar.getSectionContainer(1, 12),
                    events:
                        function () {
                            try {
                                return {
                                    'click .btn-add-item': _.bind(that.newEquipmentBtn_click, that),
                                    'click .btn-tree': _.bind(that.btnCollapseExpandTree, that),
                                };
                            } catch (Error) { console.error(Error); }
                    },
                }),
            };

            if (this.viewParams.sectionParam1) {
                this.model.set('typeId', this.viewParams.sectionParam1)
            }

            this.bindEvents();
        }

        , events: {
            //"click .btn-add-item": "addItem",
            //"click .btn-add-area": "addArea",
            //"click .btn-add-line": "addLine",
            //"click .btn-add-machine": "addMachine",
        }
        
        , 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.items, "add", this.itemsChanged);
            this.listenTo(this.items, "remove", this.itemsChanged);
            this.listenTo(this.items, "change", this.itemsChanged);
            this.listenTo(this.model, "change:typeId", this.search_filters_changed);
            this.listenTo(this.model, "change:search", _.debounce(this._search_changed, 800));
        }

        , _refresh: function (opt) {
            try {
                //console.log('autorefresh: ' + new Date().toString()); 
                if (this.autoRefresh.toid != null) {
                    clearTimeout(this.autoRefresh.toid);
                    this.autoRefresh.toid = null;
                }

                var attrs = this.model.toJSON();

                this.refreshItemsColl(_.extend(
                    {},
                    opt,
                    {
                        params: {
                            typeId: attrs.typeId,
                            search: attrs.search,
                        }
                    })
                );

                if (this.autoRefresh.enabled == true) {
                    this.autoRefresh.toid = setTimeout(
                        _.bind(this._refresh, this),
                        this.autoRefresh.every
                    );
                }
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        refresh: function (options) {
            try {
                var that = this,
                    opt = _.extend({}, options);

                //if (this.viewParams.sectionParam1 != this.model.get('typeId')) {
                //    this.model.set('typeId', this.viewParams.sectionParam1)
                //}

                var params = this.model.toJSON();

                this._refresh(_.extend(
                    {},
                    params,
                    {
                        reset: true,
                    }
                ));
            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        refreshItemsColl: function (options) {
            try {
                var that = this,
                    attrs = this.model.toJSON(),
                    opt = _.extend({}, { params: {}, refresh: true, }, options);

                if (opt.reset == true) {
                    this.model.set({
                        isLoading: true,
                    });
                }

                //Parameter details:
                // > Parameter 'reset' is used to reload only the first page of records and
                // show the 'Loading' poster.
                // > Parameter 'refresh' is uset to reload all the currently loaded records
                // without showing the 'Loading' poster.
                this.items.fetch(_.extend(
                    {},
                    opt,
                    {
                        params: {
                            ihId: app.models.ihDataSources.get("id"),
                            typeIds: (attrs.typeId > 0) ? attrs.typeId : null,
                            search: attrs.search,
                        },
                        codesText: app.translate(that, "root_tree_text"),
                        callback: function () {
                            //that.tree.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.tree.refresh(true);
                            }
                        },
                    })
                );

            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },

        render: function (container) {
            var that = this;
            var thatContainer = (container != null && container != undefined) ? container : this.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/custom-screens/modules/equipments/configuration/equipments/";

            T.render.call(this, this.template, function (tmp) {
                if (!that.i18n) that.i18n = {};
                app.getI18NJed(that, that.template, function (i18nJED) {
                    //storing internationalization data
                    that.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();


                    that.bindViewScopedEvents();

                    that.subviews.subnavbarControls.render();

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

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

                                cb.call(this, data);
                            },
                            expand_selected_onload: true,
                        },
                        types: {
                            //"root": {
                            //    icon: 'data:image/gif;base64, ',
                            //},
                            //"#": {
                            //    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: _.bind(that.customTreeCtxMenu, that),
                        },
                        sort: function (a, b) {
                            var nodea = this.get_node(a);
                            var nodeb = this.get_node(b);

                            var collection = that.items;
                            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.tree = that.$el.find(".tree").jstree(true);

                    that.$el.find(".tree").bind({
                        "rename_node.jstree": _.bind(that.onRenameNode, that),
                        "create_node.jstree": _.bind(that.onCreateNode, that),
                        //"delete_node.jstree": _.bind(that.onDeleteNode, that),
                        //"enable_node.jstree": _.bind(that.onEnableNode, that), 
                        "move_node.jstree": _.bind(that.onMoveNode, that),
                        "select_node.jstree": _.bind(that.onSelectNode, that),
                        "deselect_node.jstree": _.bind(that.onDeselectNode, that),
                        "deselect_all.jstree": _.bind(that.onDeselectNode, that),
                        "refresh.jstree": _.once(function () {
                            that.$el.find(".tree").jstree("open_all");
                        }),
                        "refresh.jstree": _.bind(function () {
                            //that.$el.find(".tree").jstree("open_all");
                            //var id = that.$el.find(".tree").jstree("get_selected");
                            that.$el.find(".tree").jstree(true).deselect_all();
                            var node = that.$el.find(".tree").jstree("get_node", that.model.get('selected'));
                            that.$el.find(".tree").jstree("select_node", node);
                            that.$el.find(".tree").jstree("open_node", node);

                            if (node) {
                                that.$el.find(".tree").jstree(true).get_node(node.id, true).children('.jstree-anchor').focus();
                                that.$el.find(".tree").jstree(true).select_node(node);
                                that.model.set('selected', null);
                            }
                        }),
                    });

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

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

                    //appending view to the main container

                    that.templates.newEquipmentModal = Handlebars.compile(that.$el.find('#new_equipment_modal_template').html());

                    that.templates.assignEquipmentModal = Handlebars.compile(that.$el.find('#assign_equipment_modal_template').html());

                    that.templates.unassignEquipmentModal = Handlebars.compile(that.$el.find('#unassign_equipment_modal_template').html());

                    that.templates.machineConfiguration = Handlebars.compile(that.$el.find('#machine_configuration').html());
                    //that.templates.assignEquipmentModal = Handlebars.compile(that.$el.find('#assign_equipment_modal').html());
                    that.templates.createEquipment = Handlebars.compile(that.$el.find('#create_equipment').html());


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

                    that.startAutoRefresh();
                }, true, customPath);
            }, customPath);
        },
        search_filters_changed: function () {
            try {
                var params = this.model.toJSON();

                app.router.navigate(
                    app.router.resolveURL(
                        app.router.currentModule,
                        _.extend(
                            {},
                            params,
                            {
                                section: app.router.currentParameters.section,
                                sectionParam1: params.typeId,
                            }
                        ),
                        false
                    ),
                    { trigger: false, }
                );

                this._refresh({ reset: true, });
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        _search_changed: function () {
            try {
                this.doSearch.call(this); 
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        doSearch: function () {
            var search = this.model.get("search");
            
            this.model.set('search', search);

            this._refresh({ reset: true, });
        },

        onCreateNode: function (e, obj) {
            var that = this;
            var node = obj.node;
            var instance = obj.instance;
            var parent;
            var collection = this.items;
            
            parent = node.parent;

            if (parent == null) {
                parent = TREE_NODE_ROOT_ID;
            }

            this.setTreeLoadingState(true);

            try {
                //numeric type is in node.original.type
                collection.addNode(node.text, parent, node.original.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);
                }, 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);
                this.startAutoRefresh();
            }
        },
        //, onDeleteNode: function (e, obj) {
        //    var that = this;
        //    if (this.subviews.machineConfiguration.view)
        //        this.subviews.machineConfiguration.view.close();

        //    var node = obj.node;
        //    var instance = obj.instance;
        //    var collection = this.items;

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

        //        }, 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.subviews.machineConfiguration.view)
                this.subviews.machineConfiguration.view.close();

            this.setTreeLoadingState(true);

            try {
                var collection = this.items;
                collection.enableNode(node.id, function (ref, ids) {
                    instance.refresh(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.items;

            parent = node.parent;

            if (parent == null) {
                parent = TREE_NODE_ROOT_ID;
            }

            this.setTreeLoadingState(true);

            try {
                collection.reorderNode(node.id, parent, obj.position + 1, function (ref, ids) {
                    //instance.refresh(true); 
                    //that.setTreeLoadingState(false);
                    that._autoRefresh({ action: 'MOVE', });

                }, function () {
                    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.items;

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

                    that.startAutoRefresh();

                }, function () {
                    instance.refresh(true);
                });
            }
            catch (e) {
                console.error((e.stack) ? e.stack : new Error(e).stack);

                this.setTreeLoadingState(false);

                that.startAutoRefresh();
            }
        },
        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.items;

            if (!node.original.equipmentId)
                return;

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

            if (this.subviews.createEquipment.view)
                this.subviews.createEquipment.view.close();

            if (obj.selected.length < 2) {
                if (node && node.data && node.data.enabled) {

                    if ((node.original.type == 'plant') || (node.original.type == 'area'))
                        this.subviews.subnavbarControls.$el.find('.btn-add-item').prop('disabled', false);
                    else
                        this.subviews.subnavbarControls.$el.find('.btn-add-item').prop('disabled', true);

                    var machineConfigurationContainer = this.$el.find(".machine-configuration-container");

                    var model = new Screen.Models.MachineConfiguration({
                        id: node.id,
                        ihId: app.models.ihDataSources.get("id"),
                        equipmentId: node.original.equipmentId,
                        parent: that,
                    });

                    this.subviews.machineConfiguration.view = new Screen.Views.MachineConfiguration({
                        container: machineConfigurationContainer,
                        model: model,
                        parent: that,
                        i18n: that.i18n[that.template], 
                        template: that.templates.machineConfiguration
                    });

                    model.fetch({
                        data: {
                            id: node.id,
                            ihId: app.models.ihDataSources.get("id"),
                        }
                    });


                    this.subviews.machineConfiguration.view.render();

                    this.listenToOnce(this.subviews.machineConfiguration.view, "nodeUpdated", function (model, item) {
                        try {

                            that.model.set('selected', item.Id);

                            that._refresh(_.extend(
                                {},
                                //params,
                                {
                                    refresh: true,
                                    //params: _.extend(
                                    //    {},
                                    //    params,
                                    //    {
                                    //        ihId: app.models.ihDataSources.get("id"),
                                    //    }
                                    //),
                                }
                            ));

                            that.setTreeLoadingState(true);
                            that.model.fetchModels();

                            this.subviews.machineConfiguration.view.close();
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    });
                }
            }
        },
        onDeselectNode: function (e, obj) {
            var that = this;
            var node = obj.node;
            var instance = obj.instance;

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

            if (this.subviews.createEquipment.view)
                this.subviews.createEquipment.view.close();
        },
        unassignNode: function (data) {
            var tree = this.tree,
                selected = tree.get_selected(),
                node = data,
                that = this,
                collection = this.items;

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

            if (this.subviews.createEquipment.view)
                this.subviews.createEquipment.view.close();

            this.setTreeLoadingState(true);

            try {
                var collection_unassignNode = function () {
                    collection.unassignNode(
                        node.id,
                        app.models.ihDataSources.get("id"),
                        function (ref, ids) {
                            that.model.set('selected', ids[0]);

                            that.setTreeLoadingState(true);

                            that._autoRefresh();


                            //tree.refresh(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"));
                            }

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

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

                this.setTreeLoadingState(false);
            }
        },
        deleteNode: function (data) {
            var tree = this.tree,
                selected = tree.get_selected(),
                node = data,
                that = this,
                collection = this.items;

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

            if (this.subviews.createEquipment.view)
                this.subviews.createEquipment.view.close();
            
            this.setTreeLoadingState(true);

            try {
                var collection_deleteNode = function () {
                    collection.deleteNode(
                        node.id,
                        app.models.ihDataSources.get("id"),
                        function (ref, ids) {
                            that.model.set('selected', ids[0]);

                            that.setTreeLoadingState(true);
                            
                            that._autoRefresh();


                            //tree.refresh(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"));
                            //}

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

                collection_deleteNode(/*true, false*/);

                this.setTreeLoadingState(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.tree;
            var selected = tree.get_selected();

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

            this.onEnableNode(null, {
                node: data,
                instance: tree,
            });
            //tree.enable_node(data); 
        },
        renameNode: function (data) {
            var tree = this.tree;
            var selected = tree.get_selected();

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

            if (data) {
                tree.edit((data.id) ? data.id : data);
            }
        },
        //, nodeDoubleClick: function (e, data) {
        //    var node = $(e.target).closest("li");
        //    var data = this.tree.get_node(node.prop("id"));

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

        getDefaultName: function (tree, props, success, error) {
            var defaultName = "";

            var that = this;
            var QP = new QueryParameters();

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

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetEquipmentTypeNewDefaultName", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;

                        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 {
                            defaultName = data[0].DefaultName;

                            if (success != null && _.isFunction(success))
                                success.call(this, defaultName);
                        }
                    } else {
                        error.call(this, that);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
        btnCollapseExpandTree: function (e) {
            var collapsed = this.model.get('collapsed');

            var btn_collapse = this.$el.find('.btn-collapse-tree');
            var btn_expand = this.$el.find('.btn-expand-tree');

            if (collapsed) {
                this.tree.open_all();
                $('.btn-collapse-tree').removeClass('hide');
                $('.btn-expand-tree').addClass('hide');

                this.model.set('collapsed', false);
            } else {
                this.tree.close_all();
                $('.btn-collapse-tree').addClass('hide');
                $('.btn-expand-tree').removeClass('hide');

                this.model.set('collapsed', true);
            }

        },
        //addItem: function (opt) {
        //    this.stopAutoRefresh();

        //    var that = this;
        //    var tree = this.tree;
            
        //    //this.getDefaultName(tree, [
        //    //        { name: "DefaultName", type: "VARCHAR", value: app.translate(this, "default_node_name") }
        //    //],
        //    //    function (defaultName) {
        //    //        var selected = tree.get_selected();
        //    //        var sel = null;
        //    //        var selected_node = null;

        //    //        if (!selected.length) {
        //    //            selected[0] = TREE_NODE_ROOT_ID;
        //    //        }

        //    //        sel = selected[0];
        //    //        selected_node = tree.get_node(sel);

        //    //        sel = tree.create_node(sel, { "text": defaultName, "type": this.model.get('typeId') }, "last", function (a, b, c) {
        //    //            a;
        //    //        });
        //    //    },
        //    //    function (that) {
        //    //        var errorCode = 'UNKNOWN';
        //    //        errorCode = code && _.isString(code) && code.length > 0 ? code : errorCode;

        //    //        app.views.topMessages.showMessage(app.translate(that, errorCode.toString() + "_error_code_message"));

        //    //        that.startAutoRefresh();
        //    //    }
        //    //);

        //    var selected = tree.get_selected();
        //    var sel = null;
        //    var selected_node = null;

        //    if (!selected.length) {
        //        selected[0] = TREE_NODE_ROOT_ID;
        //    }

        //    sel = selected[0];
        //    selected_node = tree.get_node(sel);

        //    sel = tree.create_node(sel, { "text": "","type": this.model.get('typeId'), "icon":"fa fa-minus" }, "last", function (a, b, c) {
        //        a;
        //    });
            
        //},
        addArea: function () {
            var tree = this.tree;
            var newArea = tree.create_node(null, { type: "area" });
            //if (newArea) tree.edit(newArea); 
        },
        addLine: function () {
            //var tree = this.tree;
            //var newLine = tree.create_node(null, { type: "line" });
            ////if (newLine) tree.edit(newLine); 


            var tree = this.tree;
            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.tree;
            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);
                //}
            }
        },
        filterEquipments: function (id, typeId) {
            //The param typeId indicates the type to be exclude
            //(including his direct childrens and all of his parents)

            var items = this.items,
                equipments = [],
                currentParent = null,
                i = 0;

            //Get items where this type exists
            if (items.where({ typeId: typeId }))
                var existing = items.where({ typeId: typeId });

            //Exclude parents where this type exists
            for (i = 0; i < existing.length; i++) {
                //Exclude direct parent
                currentitem = existing[i];

                if (currentitem.attributes.id != id && currentitem.attributes.equipmentId != null) {
                    equipments.push({
                        value: currentitem.attributes.id,
                        label: currentitem.attributes.text,
                        style: '',
                        Template: 'main'
                    });
                }
            }

            //Return valid child types
            return equipments;
        },
        filterLocations: function (id, typeId) {
            //The param typeId indicates the type to be exclude
            //(including his direct childrens and all of his parents)

            var items = this.items,
                locations = [],
                currentParent = null,
                i = 0;

            //Get items where this type exists
            if (items.where({ type: 'area'}))
                var existing = items.where({ type: 'area' });

            //Exclude parents where this type exists
            for (i = 0; i < existing.length; i++) {
                //Exclude direct parent
                currentitem = existing[i];

                if (currentitem.attributes.id != id ) {
                    locations.push({
                        value: currentitem.attributes.id,
                        label: currentitem.attributes.text,
                    });
                }
            }

            //Get items where this type exists
            if (items.where({ type: 'plant' }))
                var existing = items.where({ type: 'plant' });

            //Exclude parents where this type exists
            for (i = 0; i < existing.length; i++) {
                //Exclude direct parent
                currentitem = existing[i];

                if (currentitem.attributes.id != id) {
                    locations.push({
                        value: currentitem.attributes.id,
                        label: currentitem.attributes.text,
                    });
                }
            }
            //Return valid child types
            return locations;
        },
        filterModels: function (id, typeId) {
            //The param typeId indicates the type to be exclude
            //(including his direct childrens and all of his parents)

            var models = this.model.get('models'),
                items = this.items,
                excludeModels = [],
                childs = [],
                parents = [],
                currentParent = null,
                i = 0;

            //First, exclude the type itself
            var itself = _.findWhere(models, { typeId: typeId });

            if (itself)
                excludeModels.push(itself.value);

            //Get items where this type exists
            if (items.where({ typeId: typeId }))
                var existing = items.where({ typeId: typeId });

            //Exclude parents where this type exists
            for (i = 0; i < existing.length; i++) {
                //Exclude direct parent
                currentitem = existing[i];

                var itself = _.findWhere(models, { typeId: currentitem.attributes.typeId });

                if (itself)
                    excludeModels.push(itself.value);
                //excludeModels.push(currentParent.attributes.parent);
                while (currentitem = items.where({ id: currentitem.attributes.parent })[0]) {
                    //Exclude parent from current parent
                    var excludeId = _.findWhere(models, { typeId: currentitem.attributes.typeId });
                    if (excludeId)
                        excludeModels.push(excludeId.value);
                }
            }

            if (items.where({ typeId: typeId }))
                parents = items.where({ typeId: typeId });

            //Exclude all parents
            for (i = 0; i < parents.length; i++) {
                //Exclude direct parent
                currentParent = parents[i];
                //excludeModels.push(currentParent.attributes.parent);
                while (currentParent = items.where({ id: currentParent.attributes.parent })[0]) {
                    //Exclude parent from current parent
                    var excludeId = _.findWhere(models, { typeId: currentParent.attributes.typeId });
                    if (excludeId)
                        excludeModels.push(excludeId.value);
                }
            }


            //Return valid child types
            return _.reject(this.model.get('models'), function (obj) { return _.indexOf(excludeModels, obj.value) != -1; });
        },
        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;
            }

        },
        customTreeCtxMenu: function (node) {
            var that = this,
                tree = this.tree;

            //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 = {
                addPlant: {
                    label: app.translate([this, that], 'add_plant'),
                    action: function (obj) {
                        that.addInternal(obj, 'plant');
                    }
                },
                addArea: {
                    label: app.translate([this, that], 'add_area'),
                    action: function (obj) {
                        that.addInternal(obj, 'area');
                    }
                },
                createItem: {
                    label: app.translate([this, that], 'add_equipment'),
                    action: function (obj) {
                        that.newEquipmentBtn_click(obj);
                        //that.addItem();
                    },
                    //this.addItem(),
                },
                createEquipment: {
                    label: app.translate([this, that], 'create_equipment'),
                    action: function (obj) {
                        that.createEquipmentBtn_click(obj);
                        //that.addItem();
                    },
                    //this.addItem(),
                },
                assignEquipment: {
                    label: app.translate([this, that], 'assign_equipment'),
                    action: function (obj) {
                        that.assignEquipment_click(obj);
                    },
                    //this.addItem(),
                },
                unassignEquipment: {
                    label: app.translate([this, that], 'unassign_equipment'),
                    action: function (obj) {
                        that.unassignEquipment_click(obj);

                        //that.currentModal = new Modal.Views.Main({
                        //    focusOk: false,
                        //    focusSelector: '#btn-cancel',
                        //    title: app.translate([that, app], "unassign_item_confirm_title"),
                        //    message: app.translate([that, app], "unassign_item_message"),
                        //    buttons_type: "CONTINUE-CANCEL",
                        //});

                        //that.listenToOnce(that.currentModal, "continue", function (modal) {
                        //    try {
                        //        that.unassignNode(node);
                        //        that.currentModal = null;
                        //    }
                        //    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        //});

                        //that.currentModal.show();
                    },
                    //this.addItem(),
                },
                //renameItem: {
                //    label: "Rename",
                //    action: function (obj) {
                //        that.renameNode(node);
                //    },
                //},
                deleteItem: {
                    label: app.translate([this, that], 'delete'),
                    action: function (obj) {
                        that.currentModal = new Modal.Views.Main({
                            focusOk: false,
                            focusSelector: '#btn-cancel',
                            title: app.translate([that, app], "delete_item_confirm_title"),
                            message: app.translate([that, app], "delete_item_message"),
                            buttons_type: "CONTINUE-CANCEL",
                        });

                        that.listenToOnce(that.currentModal, "continue", function (modal) {
                            try {
                                that.deleteNode(node);
                                that.currentModal = null;
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });

                        that.currentModal.show();

                        //that.deleteNode(node);
                    },
                },
                enableItem: {
                    label: "Enable",
                    action: function (obj) {
                        that.enableNode(node);
                    }
                },
                
            };

            switch (node.original.type.toUpperCase()) {
                //case "AREA":
                //    break;
                //case "LINE":
                //    break;
                case "MACHINE":
                    delete items["createAreaItem"];
                    break;
                case "COMPANY":
                    delete items["createItem"];
                    delete items["createEquipment"];
                    delete items["createMachineItem"];
                    delete items["addArea"];
                    delete items["assignEquipment"];
                    delete items["unassignEquipment"];
                    delete items["deleteItem"];
                    delete items["enableItem"];
                    delete items["renameItem"];
                    break;
                case "PLANT":
                    delete items["addPlant"];
                    delete items["createMachineItem"];
                    delete items['createEquipment'];
                    delete items["assignEquipment"];
                    delete items["unassignEquipment"];
                    delete items["enableItem"];
                    delete items["renameItem"];
                    break;
                case "AREA":
                    delete items["addPlant"];
                    delete items["addArea"];
                    delete items["assignEquipment"];
                    delete items['createEquipment'];
                    delete items["unassignEquipment"];
                    delete items["createMachineItem"];
                    delete items["enableItem"];
                    delete items["renameItem"];
                    break;
                default:
                    delete items["createMachineItem"];
                    delete items["addPlant"];
                    delete items["addArea"];
                    delete items["enableItem"];
                    delete items["renameItem"];
                    break;
            }

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

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


            if (node && node.original.type != 'area' && node.original.type != 'plant') {
                if (node.original.equipmentId) {
                    delete items["createItem"];
                    delete items["createEquipment"];
                    delete items["assignEquipment"];
                } if (!node.original.equipmentId) {
                    delete items["createItem"];
                    delete items["unassignEquipment"];
                }
            } 

            var parentNode = this.tree.get_node(node.parent);

            if (parentNode && parentNode.original && (parentNode.original.type == 'area' || parentNode.original.type == 'plant')) {
                delete items["unassignEquipment"];
            }

            return items;
        },

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

            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);
                });
            }
        },
        itemsChanged: function (a, b, c) {
            var fromFetch = (
                            (c && c.from && c.from == "fetch") ||
                            (!c && b && b.from == "fetch")
                            ) ? true : false;

            if (fromFetch) {
                this.debounced_refreshTree();
            }
        },
        newEquipmentBtn_click: function (model) {
            try {
                var that = this,
                    attrs = attrs = this.tree._model.data[this.tree.get_selected()].original,
                    modelsFiltered = this.filterModels(attrs.id, attrs.typeId);

                this.currentModal = new Screen.Views.NewEquipmentModal({
                    model: new Screen.Models.NewEquipmentModal({
                        ihId: app.models.ihDataSources.get("id"),
                        parentId: attrs.id,
                        parentTypeId: attrs.typeId,
                        models: modelsFiltered,
                    }),
                    i18n: this.i18n[this.template],
                    template: this.templates.newEquipmentModal,
                });


                this.listenTo(this.currentModal, 'saving', function (modal, data, callbacks) {
                    try {
                        that.items.upsertItem(
                            null,
                            [   
                                { name: "ihId", type: 'INT', value: data.ihId },
                                { name: "ModelId", type: "INT", value: data.modelId },
                                { name: "ParentId", type: "INT", value: data.parentId },
                                { name: "Name", type: "VARCHAR", value: data.name }
                            ],
                            function (coll, id) {
                                try {
                                    callbacks.success(id);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            function (coll, msg) {
                                try {
                                    callbacks.error(msg);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            }
                        );
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                })
                    .listenToOnce(this.currentModal, 'finish', function (modal, output) {
                        try {
                            if (output.result == 'SUCCESS') {
                                var params = that.model.toJSON();

                                that.currentModal = null;

                                that.model.set('selected', output.id);

                                that._refresh(_.extend(
                                    {},
                                    params,
                                    {
                                        refresh: true,
                                        //params: _.extend(
                                        //    {},
                                        //    params,
                                        //    {
                                        //        ihId: app.models.ihDataSources.get("id"),
                                        //    }
                                        //),
                                    }
                                ));

                                that.setTreeLoadingState(true);
                                that.model.fetchModels();
                                //var node = _.where(that.tree.get_json(null, { flat: true }), { id: output.id.toString() });

                                //that.tree.deselect_all();
                                //that.tree.select_node(node);
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    });;

                this.currentModal.show();
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        createEquipmentBtn_click: function (obj) {
            var that = this,
                attrs = this.tree._model.data[this.tree.get_selected()].original;

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

            if (this.subviews.createEquipment.view)
                this.subviews.createEquipment.view.close();

                    var createEquipmentContainer = this.$el.find(".create-equipment-container");

                    var model = new Screen.Models.MachineConfiguration({
                        id: attrs.id,
                        ihId: app.models.ihDataSources.get("id"),
                        parent: that,
                    });

                    this.subviews.createEquipment.view = new Screen.Views.CreateEquipment({
                        container: createEquipmentContainer,
                        model: model,
                        parent: that,
                        i18n: that.i18n[that.template],
                        template: that.templates.createEquipment
                    });

                    model.fetch({
                        data: {
                            id: attrs.id,
                            ihId: app.models.ihDataSources.get("id"),
                        }
                    });

           
                     this.subviews.createEquipment.view.render();


            this.listenToOnce(this.subviews.createEquipment.view, "equipmentAdded", function (a, b) {
                that.model.set('selected', b.Id);

                that.setTreeLoadingState(true);
                that._autoRefresh();
                that.model.fetchModels();

                if (that.subviews.createEquipment.view)
                    that.subviews.createEquipment.view.close();
            });

        },
        addInternal: function (model, type) {
            try {

                var that = this,
                    attrs = attrs = this.tree._model.data[this.tree.get_selected()].original;

                var model = _.where(this.model.get('internals'), { label: type.toUpperCase() });

                that.items.upsertItem(
                    null,
                    [
                        { name: 'ihId', type: 'INT', value: app.models.ihDataSources.get("id") },
                        { name: "ModelId", type: "INT", value: model[0].value},
                        { name: "ParentId", type: "INT", value: attrs.id },
                        { name: "Internal", type: "BIT", value: true }
                    ],
                    function (coll, data) {
                        try {
                            that.model.set('selected', data.id);

                            that.setTreeLoadingState(true);
                            that._autoRefresh();
                            that.model.fetchModels();
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    function (coll, msg) {
                        try {
                            app.views.topMessages.showMessage(app.translate([this, app], msg), { stay: 5 * 1000, });

                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    }
                );
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }

        },
        assignEquipment_click: function (model) {
            try {
                var that = this,
                    attrs = attrs = this.tree._model.data[this.tree.get_selected()].original,
                    equipFiltered = this.filterEquipments(attrs.id, attrs.typeId);

                this.currentModal = new Screen.Views.AssignEquipmentModal({
                    model: new Screen.Models.AssignEquipmentModal({
                        modelId: attrs.id,
                        ihId: app.models.ihDataSources.get("id"),
                        equipments: equipFiltered,
                        codesText: app.translate(that, "root_tree_text"),
                    }),
                    parent: that,
                    i18n: this.i18n[this.template],
                    template: this.templates.assignEquipmentModal,
                });


                this.listenTo(this.currentModal, 'saving', function (modal, data, callbacks) {
                    try {
                        that.items.assignItem(
                            [
                                { name: 'ihId', type: 'INT', value: data.ihId },
                                { name: "ModelId", type: "INT", value: data.modelId },
                                { name: "EquipmentModelId", type: "INT", value: data.equipmentModelId},
                                //{ name: "Name", type: "VARCHAR", value: data.name }
                            ],
                            function (coll, item) {
                                try {
                                    callbacks.success(item.id);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            function (coll, msg) {
                                try {
                                    callbacks.error(msg);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            }
                        );
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                })
                    .listenToOnce(this.currentModal, 'finish', function (modal, output) {
                        try {
                            if (output.result == 'SUCCESS') {
                                var params = that.model.toJSON();

                                that.currentModal = null;

                                that.model.set('selected', output.id);

                                that._refresh(_.extend(
                                    {},
                                    params,
                                    {
                                        refresh: true,
                                        ihId: app.models.ihDataSources.get("id"),
                                    }
                                ));

                                that.setTreeLoadingState(true);
                                that.model.fetchModels();
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    });;

                this.currentModal.show();
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        unassignEquipment_click: function (model) {
            try {
                var that = this,
                    attrs = this.tree._model.data[this.tree.get_selected()].original,
                    locations = this.filterLocations();

                this.currentModal = new Screen.Views.UnassignEquipmentModal({
                    model: new Screen.Models.UnassignEquipmentModal({
                        ihId: app.models.ihDataSources.get("id"),
                        modelId: attrs.id,
                        locations: locations,
                        codesText: app.translate(that, "root_tree_text"),
                    }),
                    parent: that,
                    i18n: this.i18n[this.template],
                    template: this.templates.unassignEquipmentModal,
                });


                this.listenTo(this.currentModal, 'saving', function (modal, data, callbacks) {
                    try {
                        that.items.unassignItem(
                            data.modelId,
                            [   
                                { name: 'ihId', type: 'INT', value: data.ihId },
                                { name: "locationModelId", type: "INT", value: (data.locationModelId == '') ? null : data.locationModelId },
                            ]
                            , function (coll, item) {
                                try {
                                    callbacks.success(item.id);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            function (coll, msg) {
                                try {
                                    callbacks.error(msg);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            }

                        );
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                })
                    .listenToOnce(this.currentModal, 'finish', function (modal, output) {
                        try {
                            if (output.result == 'SUCCESS') {
                                var params = that.model.toJSON();

                                that.currentModal = null;

                                that.model.set('selected', output.id);

                                that._refresh(_.extend(
                                    {},
                                    params,
                                    {
                                        refresh: true,
                                        ihId: app.models.ihDataSources.get("id"),
                                    }
                                ));

                                that.setTreeLoadingState(true);
                                that.model.fetchModels();
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    });;

                this.currentModal.show();
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        debounced_refreshTree: _.debounce(function () {
            var that = this;
            var types = [];
            var iconedItems = [];

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

            iconedItems = _.filter(this.items.models, function (data) {
                return data.attributes.iconId
            });

            //refresh tree icons
            for (var i = 0; i < iconedItems.length; i++) {
                if (_.indexOf(types, iconedItems[i].attributes.type.toLowerCase()) == -1 && iconedItems[i].attributes.iconId) {
                    this.tree.settings.types[iconedItems[i].attributes.type.toLowerCase()] =
                        {
                        icon:iconedItems[i].attributes.iconData,
                            //_.findWhere(
                            //    that.model.get('icons'),
                            //    { id: that.model.get('types')[i].iconId }
                            //).data
                        };
                    types.push(iconedItems[i].attributes.type.toLowerCase());
                }
            }

            this.tree.refresh(true);
        }, 500),

        append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.state == app.view_states.loading
                || this.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.state = app.view_states.shown;
                container.append(el);

                this.onappend(this);
            }

            if (this.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        },
        _autoRefresh: function (opt) {
            if (this.autoRefresh.toid != null) {
                clearTimeout(this.autoRefresh.toid);
                this.autoRefresh.toid = null;
            }

            this.refresh(opt);

            if (this.autoRefresh.enabled == true) {
                this.autoRefresh.toid = setTimeout(_.bind(this._autoRefresh, this), 30 * 1000);
            }
        },
        bindViewScopedEvents: function () {
        },
        close: function () {
            this.state = app.view_states.closed;

            //If currentModal exists, hide it and erase it.
            if (this.currentModal) {
                this.currentModal.hide();
                this.currentModal = null;
            }

            this.stopAutoRefresh();
            this.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        },
        closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) sview.close();
            });
        },
        hide: function () {
            this.state = app.view_states.hidden;

            this.$el.hide();
            this.unbind();
            this.stopListening();
        },
        preRender: function () {
            app.models.subnavbar.set("dateControl", false);
            app.models.subnavbar.set("notificationBar", false);
            app.models.subnavbar.set("dateTimeScopeControl", false);
            app.models.subnavbar.set("subnavbar", true);
            app.models.subnavbar.set("sections", "12");
        },
        reRender: function () {
        },
        show: function () {
            this.state = app.view_states.shown;

            this.bindEvents();
            this.$el.show();
        },
        startAutoRefresh: function () {
            try {
                if (this.autoRefresh.enabled !== true) {
                    var that = this;

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

                    this.autoRefresh.enabled = true;

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

    Screen.Models.Item = Backbone.Model.extend({
        initialize: function () {
        }
        , defaults: {
            id: null,
            ihId: null,
            parent: null,
            type: null,
            typeId: null,
            text: null,
            order: null,
            iconId: null,
            iconData: null,
            deleted: false,
            enabled: true,
        }
    });

    Screen.Models.Items = Backbone.Collection.extend({
        model: Screen.Models.Item,
        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();

            if (options.params) {
                QP.Add("@TypeIds", "VARCHAR", options.params.typeIds);
                QP.Add("@Search", "VARCHAR", options.params.search);
                QP.Add("@ihId", "INT", options.params.ihId);
            }

            var items = [];
            items.push({
                id: TREE_NODE_ROOT_ID,
                parent: '#',
                type: "Company",
                text: options.codesText,
                state: {
                    opened: true,
                },
                icon: 'fa fa-cogs icon-style',
                a_attr: { style: "background : #c1c1c1; border: 2px solid #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
            });

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetEquipments", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        //var icons = data.Table3;
                        var data = data.Table;

                        for (var i = 0; i < data.length; i++) {
                            var itemData = data[i];
                            var equipment = {
                                id: itemData.Id,
                                equipmentId: itemData.EquipmentId,
                                parent: ((itemData.ParentId != null) && (itemData.ParentId != -1))
                                            ? itemData.ParentId
                                            : TREE_NODE_ROOT_ID,
                                type: itemData.TypeName.toLowerCase(),
                                typeId: itemData.TypeId,
                                text: (itemData.Name) ? itemData.Name : itemData.TypeName,
                                order: itemData.Order - 1,
                                deleted: itemData.Deleted,
                                enabled: !itemData.Deleted,
                                data: {
                                    enabled: !itemData.Deleted,
                                },
                                //state: {

                                //},
                                icon: (itemData.IconData) ? itemData.IconData : 'fa fa-minus',
                                a_attr: (itemData.Name || itemData.Internal)
                                    ? { style: "background: #f1f1f1; border: 2px dotted #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
                                    : { style: "background: #f1f1f1;color: #999999; border: 2px dotted #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
                                //a_attr: (!itemData.Name || itemData.Name == 'New node')
                                //    ? { style: "background : #cccccc; border: 2px dotted #b1b1b1; border-radius:5px; margin-bottom:3px; padding-right:10px;text-decoration:none;" }
                                //    : { style: "background : #f1f1f1; border: 2px dotted #c1c1c1; border-radius:5px; margin-bottom:3px; padding-right:10px;text-decoration:none;" }
                            };

                            items.push(equipment);
                        }
                    }

                    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;
        },
        fetchDetails: function (options) {
            var that = this;

            var QP = new QueryParameters();
            if (options.data) {
                if (options.data.id && options.data.ihId) {
                    QP.Add("Id", "INT", options.data.id);
                    QP.Add("ihId", "INT", options.data.ihId);

                    if (options.data.id == -1)
                        this.loaded = true;
                }


            }
            //QP.Add("includeIcons", "BIT", 1);

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetEquipmentDetails", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table.0")) {
                        var machineData = data.Table[0];

                        var machineConfiguration = _.extend({}, that.attributes, {
                            id: machineData.Id,
                            typeName: machineData.TypeName,
                            iconId: machineData.IconId,
                            typeId: machineData.TypeId,
                            parentId: ((machineData.ParentId != null) && (machineData.ParentId != -1))
                                ? machineData.ParentId
                                : TREE_NODE_ROOT_ID,
                            name: machineData.Name,
                            quantity: machineData.Quantity,
                            deleted: !machineData.Enabled,
                            hierarchyList: (machineData.HierarchyList) ? machineData.HierarchyList : '/'
                        });


                        if (options.callback != null && _.isFunction(options.callback))
                            options.callback.call(this, that, machineData);
                    }
                },
                Secured: true
            }, app.ConnectionStrings.app);
        },
        getAssignableEquipments: function (options) {
            var that = this;

            var QP = new QueryParameters();
            if (options && options.params) {
                if (options.params.id) QP.Add("Id", "INT", options.params.id);
                if (options.params.ihId) QP.Add("ihId", "INT", options.params.ihId);
            }

            //QP.Add("includeIcons", "BIT", 1);

            var items = [];
            items.push({
                id: TREE_NODE_ROOT_ID,
                parent: '#',
                type: "root",
                text: options.codesText,
                state: {
                    opened: true,
                },
                icon: 'fa fa-cogs icon-style',
                a_attr: { style: "background : #c1c1c1; border: 2px solid #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
            });

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetAssignableEquipments", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var models = data.Table;
                        //var templates = data.Table1
                        //var icons = data.Table1;

                        for (var i = 0; i < models.length; i++) {
                            var itemData = models[i];
                            var equipmentModel = {
                                id: itemData.Id,
                                parent: ((itemData.ParentId != null) && (itemData.ParentId != -1))
                                    ? itemData.ParentId
                                    : TREE_NODE_ROOT_ID,
                                typeId: itemData.TypeId,
                                text: itemData.Name,
                                //enabled: itemData.Enabled,
                                state: {
                                    opened: true,
                                },
                                order: itemData.Order - 1,
                                //order: 0,
                                data: {
                                    enabled: itemData.Enabled,
                                },
                                icon: (itemData.IconData) ? itemData.IconData : 'fa fa-minus',
                                a_attr: { style: (itemData.Enabled) 
                                    ? "background: #f1f1f1; border: 2px dotted #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" 
                                    : "background : #c1c1c1; border: 2px solid #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;"
                                }
                            };

                            items.push(equipmentModel);
                        }

                    }

                    that['set'](items, { from: "fetch" });

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

            return this;
        },
        fetchPreview: function (options) {
            var that = this;

            var QP = new QueryParameters();
            if (options && options.params) {
                if (options.params.id) QP.Add("Id", "INT", options.params.id);
                if (options.params.ihId) QP.Add("ihId", "INT", options.params.ihId);
            }

            //QP.Add("includeIcons", "BIT", 1);

            var items = [];
            items.push({
                id: TREE_NODE_ROOT_ID,
                parent: '#',
                type: "root",
                text: options.codesText,
                state: {
                    opened: true,
                },
                icon: 'fa fa-cogs icon-style',
                a_attr: { style: "background : #c1c1c1; border: 2px solid #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
            });

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetEquipmentTypeTemplatePreview", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var models = data.Table;
                        //var templates = data.Table1
                        //var icons = data.Table1;

                        for (var i = 0; i < models.length; i++) {
                            var itemData = models[i];
                            var equipmentModel = {
                                id: itemData.Id,
                                parent: ((itemData.ParentId != null) && (itemData.ParentId != -1))
                                    ? itemData.ParentId
                                    : TREE_NODE_ROOT_ID,
                                typeId: itemData.TypeId,
                                text: itemData.TypeName,
                                state: {
                                    opened: true,
                                },
                                order: itemData.Order - 1,
                                //order: 0,
                                data: {
                                    enabled: itemData.Enabled,
                                },
                                icon: (itemData.IconData) ? itemData.IconData : 'fa fa-minus',
                                a_attr: { style: "background: #f1f1f1; border: 2px dotted #c1c1c1; border-radius:5px; margin-bottom:3px; line-height: 28px;height: 28px;padding-right: 10px; text-decoration:none;" }
                            };

                            items.push(equipmentModel);
                        }

                    }

                    that['set'](items, { from: "fetch" });

                    if (options.callback != null && _.isFunction(options.callback))
                        options.callback.call(this, that);
                },
                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") }
                    ]);
                }
            }
        },
        assignItem: function ( 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.System + ".EQUIP.AssignEquipment", 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.TypeName,//.toLowerCase(),
                                text: itemData.Name,
                                order: itemData.Order - 1,
                                deleted: itemData.Deleted,
                                enabled: !itemData.Deleted,
                                data: {
                                    enabled: !itemData.Deleted,
                                }
                            };

                            if (success != null && _.isFunction(success))
                                success.call(this, that, item);
                        }
                    } else {
                        error.call(this, that);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
        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.System + ".EQUIP.UpsertEquipment", 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.TypeName,//.toLowerCase(),
                                text: itemData.Name,
                                order: itemData.Order - 1,
                                deleted: itemData.Deleted,
                                enabled: !itemData.Deleted,
                                data: {
                                    enabled: !itemData.Deleted,
                                }
                            };

                            if (success != null && _.isFunction(success))
                                success.call(this, that, item);
                        }
                    } else {
                        if (!data.Message)
                            data.Message = 'UNKNOWN';

                        error.call(this, that, data.Message);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
        unassignItem: 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.System + ".EQUIP.UnassignEquipment", 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 {
                            if (data[0].Message) {
                                app.views.topMessages.showMessage(app.translate(app, data[0].Message));
                            } 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);
        },
        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.System + ".EQUIP.RemoveEquipment", 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 {
                            if (data[0].Message) {
                                app.views.topMessages.showMessage(app.translate(app, data[0].Message));
                            } else {
                                ids = _.pluck(data, 'Id');

                                if (success != null && _.isFunction(success))
                                    success.call(this, that, ids);
                            }
                        }
                    } else {
                        var code = null;
                        if(data.Message)
                            code = data.Message
                        else
                            code = 'UNKNOWn'

                        error.call(this, that, code);
                    }
                },
                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);
            QP.Add("@Enabled", "BIT", 1);

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

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.SetEquipmentEnabled", 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.System + ".EQUIP.MoveEquipment", 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: "TypeId", type: "INT", value: (parseInt(type) == 0) ? null : parseInt(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);

                that.startAutoRefresh();
            });
        },
        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);
            }
        },
        unassignNode: function (id, ihId,/*checkHasData,*/ success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.unassignItem(
                    id,
                    [
                        { name: "ihId", type: "INT", value: ihId},
                    ]
                    , 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);
                    }
                );
            }
        },
        deleteNode: function (id, ihId, /*checkHasData,*/ success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.deleteItem(
                    id,
                    [
                        { name: "ihId", type: "INT", value: ihId },
                    ]
                    , 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);
            }
        }
    });

    Screen.Models.MachineConfiguration = Backbone.Epoxy.Model.extend({
        defaults: {
            id: null,
            ihId: null,
            name: null,
            type: null,
            typeName: null,
            statusCode: null,
            deleted: null,
            icon: null,
            internal: false,
            items: null,

            ////behind the scenes
            statusCodes: [],
            statusCodesBinding: [],
            types: [],
            typesBinding: [],
            counters: [],
            countersBinding: [],
            tags: [],
            tagsBinding: [],
        },
        initialize: function () {
            _.extend(
                this, 
                { 
                    loaded: false,
                }, 
                this.options
            );
        }
        , fetch: function (options) {
            var that = this;

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

            if (options.params) {
                if (options.params.typeIds)
                    QP.Add("TypeIds", "VARCHAR", options.params.typeIds);
                if (options.params.search)
                    QP.Add("Search", "VARCHAR", options.params.search);
                if (options.params.ihId)
                    QP.Add("ihId", "INT", options.data.ihId);
            }

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.GetEquipments", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table.0")) {
                        var machineData = data.Table[0];
                        //var statusCodeList = data.Table1;
                        //var typesList = data.Table2;
                        //var delayCodes = data.Table2;

                        //var statusCodesBinding = _.map(statusCodeList, function (obj) { return { label: obj.Name, value: obj.Code }; });
                        //var typesBinding = _.map(typesList, 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) ? machineData.Name : '',
                            type: machineData.TypeId,
                            typeName: machineData.TypeName,
                            statusCode: app.translate([app], machineData.StatusCode + '_label'),
                            statusName: (machineData.StatusName) ? app.translate([app], machineData.StatusCode + '_label') : '',
                            deleted: machineData.Deleted,
                            icon: machineData.IconData,
                            equipmentId: machineData.EquipmentId,
                            internal: machineData.Internal,
                            //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,

                            //statusCodes: statusCodeList,
                            //statusCodesBinding: statusCodesBinding,
                            //types: typesList,
                            //typesBinding: typesBinding,
                            //tagsBindingDigital: tagsBindingDigital,
                            //tagsBindingReal: tagsBindingReal,
                            //delayCodesBinding: delayCodesBinding,
                        });

                        that.loaded = true;

                        that.set(machineConfiguration, { from: "fetch" });
                    }
                },
                Secured: true
            }, app.ConnectionStrings.app);
        }
        , save: function (opt) {
            var that = this;
            var options = {
                callback: function () { }
            };

            _.extend(options, opt);

            var QP = new QueryParameters();

            var params = [
                ["@Id", "INT", "id"],
                ["@ihId", "INT", "ihId"],
                ["@Name", "VARCHAR", "name"],
                //["@TypeId", "INT", "type"],
            ];

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

            if (this.get('equipmentId')) {
                QP.Add('@EquipmentId', 'INT', this.get('equipmentId'));
            }

            if (this.get('internal')) {
                QP.Add('@Internal', 'BIT', this.get('internal'));
            }

            Core.Json.CallProcedure(app.DatabaseNames.System + ".EQUIP.UpsertEquipment", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table.0")) {
                        var item;
                        if (data.Table1)
                            item = data.Table1[0];
                        else
                            item = data.Table[0];

                        if (options.callback != null && _.isFunction(options.callback))
                            options.callback.call(this, that, item);
                    } else {
                        if (Core.Object.Eval(data, "Message")) {
                            if (options.callback != null && _.isFunction(options.callback)) {
                                options.callback.call(this, that, data);
                            }

                            console.error(data.Message);
                        }
                        else
                            console.error("Server response not valid.");
                    }
                },
                Async: true,
                Secured: true
            }, app.ConnectionStrings.app);
        },
        computeds: {
        },
        fetchTags: function () {
            var that = this;
            var qp = new Core.Database.QueryParameters();

            qp.Add('@OnlyEnabledTags', 'BIT', 1);
            qp.Add('@RowsToFetch', 'INT', 999999999);

            Core.Json.CallProcedure(
                app.DatabaseNames.IH + ".WEB.GetTagsCatalog",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if ((resp) && (resp.Table)) {
                                var records = resp.Table;

                                var newItems = _.map(records, function (obj) { return { value: obj.TagID, label: (obj.Alias) ? obj.Alias : obj.Name, }; });

                                that.set("tags", newItems);
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error("Server response not valid.");
                            }
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);
                    },
                    Secured: true,
                    Async: false,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
    });

    Screen.Views.MachineConfiguration = Backbone.Epoxy.View.extend({
        template: 'fixed',
        i18n:null,
         id: "equipments"
        , title: "Equipments"
        //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 () {
            _.extend(this, this.options);

            var that = this;

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

            if (this.viewParams) {
            }

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

            this.i18n = {
                global: this.i18n
            };

            this.subviews = {};
            
            this.model.fetchTags();

            //this.counterConfigurations = new Screen.Collections.CounterConfigurations();

            //this.counterConfigurations.fetch({
            //    params: {
            //        id: this.model.get('equipmentId'),
            //    }
            //});

            //EquipmentCounter.Collections.EquipmentCounters.fetch({
            //    async: false,
            //    success: function (records) {
            //        try {
            //            that.model.set(
            //                'counters',
            //                _.map(records, function (obj) { return { value: obj.id, label: obj.name, }; })
            //            );

            //        }
            //        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
            //    },
            //});

            this.grids = {
                grid: null,
            };

            this.bindEvents();
            //_.bindAll(this);

            this.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.advancedOptions = !that.advancedOptions;
                that.advopt(that.advancedOptions);
                return false;
            });
        },

        events: {
            "click .btn-add-counter": "addNewBtn_click",
            "click .btn-save": "saveMachineConfiguration",
            "click .btn-cancel": "cancelMachineConfiguration",
            "submit #detailsForm": "formPreventSubmit",
        },

        formPreventSubmit: function (e) {
            e.preventDefault();
        },

        render: function (container, viewParams) {
            var that = this;
            var thatContainer = this.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/custom-screens/modules/equipments/configuration/" + this.template + "/";

            if (this.model.loaded) {

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

                that.applyBindings();

                model = this.model; 
                var editable = true;


                        //end

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

                        //end:

            } else {
                setTimeout(function () {
                    if (!that.model.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);
            }
        },
       
        addNewBtn_click: function (e) {
            try {
                this.addNew();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        discardRow: function (m) {
            //to discard just remove the model from the collection.
            m.collection.remove(m);
        }

        , append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.state == app.view_states.loading
                || this.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.state = app.view_states.shown;
                container.append(el);

                this.onappend(this);
            }

            if (this.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.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);

            if (this.model.get('internal')) {
                this.model.save({
                    callback: function (model, item) {
                        if (item.Message) {
                            app.views.topMessages.showMessage(app.translate(that.parent, item.Message));
                        } else {
                            app.views.topMessages.showMessage(app.translate(that.parent, "machine_configuration_saved"));
                            that.trigger(
                                'nodeUpdated',
                                this,
                                item,
                            );
                        }
                    }
                });
            }
        }

        , cancelMachineConfiguration: function () {
            this.setSaveCancelButtons(false);
            this.counterConfigurations.fetch({
                params: {
                    id: this.model.get("equipmentId"),
                    ihId: app.models.ihDataSources.get('id'),
                },
                reset: true,
            });

            this.model.fetch({
                data: {
                    id: this.model.get("id"),
                    ihId: app.models.ihDataSources.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);
            //this.listenTo(this.counterConfigurations, "add change remove", this.checkButtonsState);
        }

        , bindViewScopedEvents: function () {
        }

        , unbindViewScopedEvents: function () {
        }

        , close: function () {
            this.state = app.view_states.closed;

            this.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        }

        , closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) sview.close();
            });
        }

        , show: function () {
            this.state = app.view_states.shown;

            this.showSubviews();
            this.bindEvents();
            this.$el.show();
        }

        , showSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) sview.show();
            });
        }

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

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

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

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

        , hideSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) 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);
        }
    });


    Screen.Views.CreateEquipment = Backbone.Epoxy.View.extend({
        //template: "equipments"
        i18n: null,
        id: "equipments"
        , title: "Equipments"
        //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 () {
            _.extend(this, this.options);

            var that = this;

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

            if (this.viewParams) {
            }

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

            this.subviews = {};


            //this.model.fetchTags();


            //this.counterConfigurations.fetch({
            //    params: {
            //        id: this.model.get('id'),
            //    }
            //});

            this.grids = {
                grid: null,
            };

            this.bindEvents();
            //_.bindAll(this);

            this.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.advancedOptions = !that.advancedOptions;
                that.advopt(that.advancedOptions);
                return false;
            });
        },

        events: {
            //"click .btn-add-counter": "addNewBtn_click",
            "click .btn-save": "createEquipment",
            "click .btn-cancel": "cancelCreation",
            "submit #detailsForm": "formPreventSubmit",
        },

        formPreventSubmit: function (e) {
            e.preventDefault();
        },

        render: function (container, viewParams) {
            var that = this;
            var thatContainer = this.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/custom-screens/modules/equipments/configuration/" + this.template + "/";

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

                    //loading the view and appeding it to the views's $el.
                    that.$el.html(that.template(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.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);
            }
        },

        actionOnRow: function (model, action) {
            try {
                switch (action.toUpperCase()) {
                    case 'DELETE':
                        this.discardRow(model);
                        break;
                }
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        addNewBtn_click: function (e) {
            try {
                this.addNew();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        addNew: function () {
            this.counterConfigurations.unshift({
                id: (this.counterConfigurations.models.length * - 1) - 1,
                isNew: true,
                editing: true,
            });
        },
        discardRow: function (m) {
            //to discard just remove the model from the collection.
            m.collection.remove(m);
        }

        , append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.state == app.view_states.loading
                || this.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.state = app.view_states.shown;
                container.append(el);

                this.onappend(this);
            }

            if (this.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.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);
        }

        , createEquipment: function () {
            var that = this,
                attrs = that.model.toJSON();

            this.setSaveCancelButtons(false);

            this.model.save({
                callback: function (model, item) {
                    if (item.Message) {
                        app.views.topMessages.showMessage(app.translate(that.parent, item.Message));
                    } else {
                        app.views.topMessages.showMessage(app.translate(that.parent, "new_equipment_saved"));
                        that.trigger(
                            'equipmentAdded',
                            this,
                            item,
                        );
                    }
                }
            });
        }

        , cancelMachineConfiguration: function () {
            this.setSaveCancelButtons(false);
            //this.counterConfigurations.fetch({
            //    params: {
            //        id: this.model.get("id"),
            //        ihId: app.ihDataSources.get('id'),
            //    },
            //    reset: true,
            //});
            this.model.fetch({
                data: {
                    id: this.model.get("id"),
                    ihId: app.models.ihDataSources.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);
            //this.listenTo(this.counterConfigurations, "add change remove", this.checkButtonsState);
        }

        , bindViewScopedEvents: function () {
        }

        , unbindViewScopedEvents: function () {
        }

        , close: function () {
            this.state = app.view_states.closed;

            this.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        }

        , closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) sview.close();
            });
        }

        , show: function () {
            this.state = app.view_states.shown;

            this.showSubviews();
            this.bindEvents();
            this.$el.show();
        }

        , showSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) sview.show();
            });
        }

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

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

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

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

        , hideSubviews: function () {
            _.each(this.subviews, function (sview) {
                if (sview.cid) 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);
        }
    });
    
    //Screen.Models.CounterConfiguration = Backbone.Epoxy.Model.extend({
    //    defaults: {
    //        id: null,
    //        equipmentId: null,
    //        counterId: null,
    //        tagId: null,
    //        tagAscFlank: null,
    //        tag2Id: null,
    //        tag2AscFlank: null,
    //        tagResetValue: null,
    //        tagRealAsDigital: null,
    //        active: null,
    //    },
    //    parse: function (obj) {
    //        return {
    //            id: obj.Id,
    //            equipmentId: obj.EquipmentId,
    //            counterId: obj.EquipmentCounterId,
    //            tagId: obj.TagId,
    //            tagAscendingFlank: obj.TagAscendingFlank,
    //            tag2Id: obj.Tag2Id,
    //            tag2AscendingFlank: obj.Tag2AscendingFlank,
    //            tagResetValue: obj.TagResetValue,
    //            tagRealAsDigital: obj.TagRealAsDigital,
    //            active: obj.Active,
    //        }
    //    }
    //});

    //Screen.Collections.CounterConfigurations = Backbone.Collection.extend({
    //    model: Screen.Models.CounterConfiguration,

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

    //    comparator: function (a, b) {
    //        var attrsA = a.toJSON(),
    //            attrsB = b.toJSON();

    //        if (attrsA.isNew) return -1;
    //        else if (attrsB.isNew) return 1;
    //        else if (attrsA.name < attrsB.name) return -1;
    //        else if (attrsA.name > attrsB.name) return 1;
    //        else return 0;
    //    },

    //    fetch: function (opt) {
    //        var that = this,
    //            qp = new Core.Database.QueryParameters(),
    //            ttimestamp = this.transaction_timestamp = new Date().getTime(),
    //            options = opt ? _.clone(opt) : {};

    //        this.isFetching = true;
            
    //        //if (options.reset) {
    //        //this.resetPagination(true);

    //        this.fixedParameters = [
    //            { Name: '@id', Type: 'INT', Value: options.params.id, },
    //        ];
    //        //}

    //        _.each(this.fixedParameters, function (qpParams) {
    //            qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
    //        });

    //        if (options.refresh) {
    //            qp.Add('@fromRow', 'INT', 0);
    //            qp.Add('@rowsToFetch', 'INT', this.currentPage * this.pageSize);
    //        }
    //        else if (options.reset) {
    //            qp.Add('@fromRow', 'INT', 0);
    //            qp.Add('@rowsToFetch', 'INT', this.pageSize);
    //        }
    //        else {
    //            qp.Add('@fromRow', 'INT', (this.currentPage - 1) * this.pageSize);
    //            qp.Add('@rowsToFetch', 'INT', this.pageSize);
    //        }


    //        Core.Json.CallProcedure(
    //            app.DatabaseNames.System + ".EQUIP.GetEquipmentConfiguration",
    //            qp,
    //            {
    //                onSuccess: function (resp) {
    //                    try {
    //                        //checking transaction timestamp
    //                        if (ttimestamp != that.transaction_timestamp)
    //                            return;

    //                        if ((resp) && (resp.Table)) {
    //                            var records = resp.Table,
    //                                newColl;

    //                            newColl = _.map(records, that.model.prototype.parse);

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

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

    //                            if (!options.reset) {
    //                                var editingItems = _.where(that.toJSON(), { isNew: true });
    //                                [].push.apply(newColl, editingItems);
    //                            }

    //                            that[method](newColl, { from: 'fetch' })
    //                                .trigger('fetch', that, records);

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

    //                            that.isFetching = false;
    //                        }
    //                        else {
    //                            if ((resp) && (resp.Message))
    //                                console.error(resp.Message);
    //                            else
    //                                console.error('Server response not valid.');
    //                        }
    //                    }
    //                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
    //                },
    //                Async: options.async,
    //                Secured: true,
    //            },
    //            app.ConnectionStrings.app
    //        );

    //        return this;
    //    },
    //    upsert: 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.System + '.EQUIP.UpdateEquipmentConfiguration',
    //            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 (data.Message)
    //                            error.call(this, that, data.Message);
    //                        else
    //                            error.call(this, that);
    //                    }
    //                },
    //                onError: function (data) {
    //                    if (error != null && _.isFunction(error))
    //                        error.call(this, that);
    //                },
    //                Async: true,
    //                Secured: true,
    //            },
    //            app.ConnectionStrings.app
    //        );
    //    },
    //    removeItem: function (id, success, error) {
    //        var model = this.get(id);
    //        if (model) {
    //            var that = this;
    //            var qp = new QueryParameters();

    //            qp.Add('@Id', 'INT', id);

    //            Core.Json.CallProcedure(
    //                app.DatabaseNames.System + '.EQUIP.RemoveEquipmentConfiguration',
    //                qp, {
    //                onSuccess: function (data) {
    //                    if (data && data.Table && data.Table.length > 0) {
    //                        var data = data.Table[0];

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

    Screen.Models.EquipmentType = Backbone.Epoxy.Model.extend({
        defaults: {
            id: null,
            typeId: null,
            name: null,
            hasChildren: null,
            hierarchyId: null,
            parentHierarchyId: null,
            enabled: null,
        },
        parse: function (obj) {
            return {
                id: obj.Id,
                typeId: obj.TypeId,
                name: obj.Name,
                hasChildren: obj.HasChildren,
                hierarchyId: obj.HierarchyId,
                parentHierarchyId: obj.ParentHierarchyId,
                enabled: obj.Enabled,
            }
        }
    });

    Screen.Collections.EquipmentTypes = Backbone.Collection.extend({
        model: Screen.Models.EquipmentType,

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

        fetch: function (opt) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                ttimestamp = this.transaction_timestamp = new Date().getTime(),
                options = opt ? _.clone(opt) : {};

            this.isFetching = true;

            //if (options.reset) {
            //this.resetPagination(true);

            this.fixedParameters = [
            ];
            //}

            _.each(this.fixedParameters, function (qpParams) {
                qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
            });

                qp.Add('@fromRow', 'INT', 0);
                qp.Add('@rowsToFetch', 'INT', -1);


            Core.Json.CallProcedure(
                app.DatabaseNames.System + ".EQUIP.GetEquipmentTypes",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            //checking transaction timestamp
                            if (ttimestamp != that.transaction_timestamp)
                                return;

                            if ((resp) && (resp.Table)) {
                                var records = resp.Table,
                                    newColl;

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

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

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

                                //if (!options.reset) {
                                //    var editingItems = _.where(that.toJSON(), { isNew: true });
                                //    [].push.apply(newColl, editingItems);
                                //}

                                that[method](newColl, { from: 'fetch' })
                                    .trigger('fetch', that, records);

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

                                that.isFetching = false;
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error('Server response not valid.');
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    Async: options.async,
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
    });

    Screen.Models.NewEquipmentModal = Backbone.Epoxy.Model.extend({
        defaults: {
            message: null,

            ihId: null,
            parentId: null,
            modelId: null,
            models: [],
            //equipmentId: null,
            //equipmentName: null,

            name: '',

            processing: false,
            errorMsg: "",
        },
    });

    Screen.Views.NewEquipmentModal = Modal2.Views.SimpleModal.extend({
        className: Modal2.Views.SimpleModal.prototype.className + ' new-equipment-modal',

        i18n: null,
        innerModal: null,
        templates: null,
        modelsGrid: null,
        //isAssign: null,
        initialize: function (options) {
            _.extend(this, options);

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

            //this.model.fetchTypes();

            this.items = new Screen.Models.Items();

            //this.items.fetch(
            //    {
            //        params: [
            //            //{ Name: 'scriptId', Type: 'INT', Value: this.model.get('scriptId') },
            //            //{ Name: 'includeExamples', Type: 'INT', Value: 1 },
            //            //{ Name: 'includeOnline', Type: 'INT', Value: 1 },
            //            //{ Name: 'timezoneCode', Type: 'VARCHAR', Value: app.models.user.get("timezoneCode") },
            //        ],
            //    }
            //)

            this.bindEvents();

            return this;
        },
        bindEvents: function () {
            Modal.Views.SimpleModal.prototype.bindEvents.apply(this, arguments);
            //this.listenTo(this.items, 'fetch', this.collection_fetch);
            this.listenTo(this.model, "change:modelId", this.idChanged);
        },

        render: function () {

            Modal.Views.SimpleModal.prototype.render.apply(this, arguments);
            var that = this;

            this.tree = null;

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

            Core.Include({
                Widgets: []
                , Events: {
                    onLoad: function () {

                        that.applyBindings();

                        that.modelsSelect = new FormSelectBootstrap(that.$("#selectType").get(0), {
                            Events: {
                                onValueChange: [_.bind(that.modelSelectChanged, that)]
                            }
                            , Templates: {
                                //"parent": "<option value={{Id}} data-content='<span>{{Name}}</span><img data=\"data:image/gif;base64,{{Data}}\"></img>'></option>"
                                "default": "<option value={{value}} data-content='<span>{{label}}</span>'></option>",
                                "main": "<option value={{value}} style=\"{{style}}\" data-content='<span  >{{label}}</span>' > </option>"
                            }
                        });

                        that.ignoreDropdownEvent = true;

                        that.modelsSelect.SetOptionsData(
                            [{ "value": 0, "label": "Choose...", Template: "default" }].concat(that.model.get('models'))
                        );

                        that.ignoreDropdownEvent = false;

                        //onViewComplete();
                    }
                }
                , ExternalWidgets: [
                    { Name: 'FormWidgetBase', URL: '/IndustrialDashboard/Widgets/FormWidgets2/FormWidgetBase/', JS: ['FormWidgetBase.js'] }
                    , { Name: 'FormWidget', URL: '/IndustrialDashboard/Widgets/FormWidgets2/FormWidget/', JS: ['FormWidget.js'], CSS: ['FormWidget.css'] }
                ]
            });

        },
        modelSelectChanged: function (e) {
            try {
                if (!this.ignoreDropdownEvent) {
                    var modelId = this.modelsSelect.GetValue();

                    this.model.set({
                        modelId: (parseInt(modelId, 10) == 0) ? null : modelId
                    });
                }
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        idChanged: function (a, b) {
            var that = this,
                text = app.translate([that], "root_tree_preview");


            this.items.fetchPreview(_.extend(
                {},
                {
                    params: {
                        id: b,
                        ihId: app.models.ihDataSources.get('id'),
                    },
                    codesText: text,
                    callback: function () {
                        //that.tree.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') {


                        if (that.tree == null) {

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

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

                                        data[1].parent = TREE_NODE_ROOT_ID;

                                        cb.call(this, data);
                                    },
                                },
                                types: {
                                    //"root": {
                                    //    icon: 'data:image/gif;base64, ',
                                    //},
                                    //"#": {
                                    //    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: _.bind(that.customTreeCtxMenu, that),
                                //},
                                sort: function (a, b) {
                                    var nodea = this.get_node(a);
                                    var nodeb = this.get_node(b);

                                    var collection = that.items;
                                    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.tree = that.$el.find(".jstreePreview").jstree(true);
                        } else {
                            var data = that.items.toJSON();

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

                            data[1].parent = TREE_NODE_ROOT_ID;
                            that.tree.settings.core.data = data;
                            that.tree.refresh();
                        }

                        that.$el.find(".jstreePreview").jstree('open_all');

                        that.setTreeLoadingState(false);

                        //    that.tree.refresh(true);
                        //}
                    },
                }));
        },
        setTreeLoadingState: function (isLoading) {
            var tree = this.tree;

            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);
                });
            }
        },
        save: function () {
            var that = this,
                attrs = this.model.toJSON();

            if (attrs.processing == false) {
                this.model.set('processing', true);

                try {
                    this.trigger(
                        'saving',
                        this,
                        attrs,
                        {
                            success: function (id) {
                                try {
                                    that.model.set('processing', false);

                                    that.finish({ result: 'SUCCESS', id: id });

                                    that.hide();
                                    //setTimeout(_.bind(that.hide, that), 1500);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            error: function (errorMsg) {
                                try {
                                    app.views.topMessages.showMessage(app.translate([{ options: { i18n: { 1: that.i18n, }, }, template: 1, }, app], errorMsg), { stay: 5 * 1000, });
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                                finally {
                                    that.model.set('processing', false);
                                }
                            },
                        }
                    );
                }
                catch (e) {
                    this.model.set('processing', false);
                    throw e;
                }
            }
        },
        show: function () {
            if (!this.isRendered) {
                this.render();
            }
            else {
                this.$el.modal({
                    keyboard: false,
                    backdrop: 'static',
                });
            }

            return this;
        },
        hide: function () {
            if (this.innerModal)
                this.innerModal.hide();

            var result = Modal.Views.SimpleModal.prototype.hide.apply(this, arguments);
            return result;
        },
        removeRow: function (model) {
            var that = this;
            model.collection.removeItem(
                model.get('id')
                , function (coll, data) {
                    app.views.topMessages.showMessage(app.translate([that, app], 'SAVED_CHANGES_SUCCESSFUL'), { stay: 5 * 1000, });

                    that.items.remove(model);

                    that.collection_fetch();
                }
                , function (coll, msg) {
                    app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 10 * 1000, });
                }
            );
        },
        downloadScript: function (m) {
            try {
                var that = this;

                Script.download(
                    {
                        params: {
                            id: m.get('id')
                        },
                        success: function (model, data) {
                            try {
                                // Blob for saving.
                                var blob = new Blob([new Uint8Array(data.Content)], { type: 'application/octet-stream' });

                                // Tell the browser to download the file.
                                saveAs(blob, data.FileName);
                            }
                            catch (error) {
                                console.error((error.stack) ? error.stack : new Error(error).stack);
                            }
                        },
                        error: function (model, msg) {
                            try {
                                app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 5 * 1000, });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                    }
                );
            }
            catch (error) {
                console.error((error.stack) ? error.stack : new Error(error).stack);
            }
        },

        acceptBtn_click: function (e) {
            try {
                this.save();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        collection_fetch: function (col, resp) {
            var that = this;
            var s = [];
            var e = [];

            this.items.each(
                function (m) {
                    if (m.get('statusCode') == 'EXAMPLE') {
                        e.push(m);
                    }
                    else {
                        s.push(m);
                    }
                }
            );

            s.forEach(function (model, index) {
                model.set('curSourceId', that.model.get('curSourceId'));
            });

            this.sources.set(s);

            this.examples.set(e);

            if (this.toCloneSource && !this.sources.findWhere({ id: -1 })) {
                this.addNewClone(this.toCloneSource);
            }
        },
    });

    Screen.Models.AssignEquipmentModal = Backbone.Epoxy.Model.extend({
        defaults: {
            message: null,


            modelId: null,
            equipmentModelId: null,
            equipments: [],
            name: null,
            type: null,
            hierarchyList: null,

            available: true,

            codesText: null,


            processing: false,
            errorMsg: "",
        },
    });

    Screen.Views.AssignEquipmentModal = Modal2.Views.SimpleModal.extend({
        className: Modal2.Views.SimpleModal.prototype.className + ' assign-equipment-modal',

        i18n: null,
        innerModal: null,
        templates: null,
        modelsGrid: null,
        initialize: function (options) {
            _.extend(this, options);

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

            //this.model.fetchTypes();

            this.items = new Screen.Models.Items();

            

            //this.items.fetch(
            //    {
            //        params: [
            //            //{ Name: 'scriptId', Type: 'INT', Value: this.model.get('scriptId') },
            //            //{ Name: 'includeExamples', Type: 'INT', Value: 1 },
            //            //{ Name: 'includeOnline', Type: 'INT', Value: 1 },
            //            //{ Name: 'timezoneCode', Type: 'VARCHAR', Value: app.models.user.get("timezoneCode") },
            //        ],
            //    }
            //)

            this.bindEvents();

            return this;
        },
        bindEvents: function () {
            Modal.Views.SimpleModal.prototype.bindEvents.apply(this, arguments);
            //this.listenTo(this.items, 'fetch', this.collection_fetch);
            this.listenTo(this.model, "change:equipmentModelId", this.idChanged);
        },

        render: function () {

            Modal.Views.SimpleModal.prototype.render.apply(this, arguments);
            var that = this;

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

            this.items.getAssignableEquipments(_.extend(
                {},
                {
                    params: {
                        id: this.model.get('modelId'),
                        ihId: this.model.get('ihId')
                    },
                    codesText: this.model.get('codesText'),
                    callback: function (model, item) {
                        if (item.length > 1) {
                            that.model.set('available', true);

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

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

                                        data[1].parent = TREE_NODE_ROOT_ID;

                                        cb.call(this, data);
                                    },
                                },
                                sort: function (a, b) {
                                    var nodea = this.get_node(a);
                                    var nodeb = this.get_node(b);

                                    var collection = that.items;
                                    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.tree = that.$el.find(".jstreePreview").jstree(true);



                            that.$el.find(".jstreePreview").jstree('open_all');

                            that.setTreeLoadingState(false);

                            that.$el.find(".jstreePreview").bind({
                                "select_node.jstree": _.bind(that.onSelectNode, that),
                            });
                        } else {
                            that.model.set('available', null);
                        }
                    }
                }));

            //if (this.tree) {
            //    that.$el.find(".treePreview").bind({
            //        "select_node.jstree": _.bind(that.onSelectNode, that),
            //        "ready.jstree": _.bind(function () {
            //            $('jstreePreview li').each(function () {
            //                $(".jstreePreview").jstree().disable_node(this.id);
            //            })
            //        }),
            //    });
            //}
            //that.append(thatContainer, that.$el);

            //Core.Include({
            //    Widgets: []
            //    , Events: {
            //        onLoad: function () {

            //            that.applyBindings();

            //            that.modelsSelect = new FormSelectBootstrap(that.$("#selectEquipment").get(0), {
            //                Events: {
            //                    onValueChange: [_.bind(that.modelSelectChanged, that)]
            //                }
            //                , Templates: {
            //                    //"parent": "<option value={{Id}} data-content='<span>{{Name}}</span><img data=\"data:image/gif;base64,{{Data}}\"></img>'></option>"
            //                    "default": "<option value={{value}} data-content='<span>{{label}}</span>'></option>",
            //                    "main": "<option value={{value}} style=\"{{style}}\" data-content='<span  >{{label}}</span>' > </option>"
            //                }
            //            });

            //            that.ignoreDropdownEvent = true;

            //            that.modelsSelect.SetOptionsData(
            //                [{ "value": 0, "label": "Choose...", Template: "default" }].concat(that.model.get('equipments'))
            //            );

            //            that.ignoreDropdownEvent = false;

            //            //onViewComplete();
            //        }
            //    }
            //    , ExternalWidgets: [
            //        { Name: 'FormWidgetBase', URL: '/IndustrialDashboard/Widgets/FormWidgets2/FormWidgetBase/', JS: ['FormWidgetBase.js'] }
            //        , { Name: 'FormWidget', URL: '/IndustrialDashboard/Widgets/FormWidgets2/FormWidget/', JS: ['FormWidget.js'], CSS: ['FormWidget.css'] }
            //    ]
            //});



            //that.modelsSelect.SetValue(that.model.get('iconId'), { silent: true, force: true });

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

            //onViewComplete();

        },
        modelSelectChanged: function (e) {
            try {
                if (!this.ignoreDropdownEvent) {
                    var modelId = this.modelsSelect.GetValue();

                    this.model.set({
                        equipmentModelId: (parseInt(modelId, 10) == 0) ? null : modelId
                    });
                }
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        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;



            var that = this;
            var node = obj.node;
            var instance = obj.instance;
            var collection = this.items;


            if (obj.selected.length < 2) {;
                if (node && node.data && node.data.enabled) {
                    that.model.set('name', node.text);
                    that.model.set('equipmentModelId', node.id);
                } else {
                    that.model.set('name', null);
                    that.model.set('equipmentModelId', null);
                }
            }
        },
        idChanged: function (a, b) {
            var that = this,
                text = app.translate([that], "root_tree_preview");


            this.items.fetchDetails(_.extend(
                {},
                {
                    data: {
                        id: b,
                    },
                    callback: function (model, item) {

                        that.model.set({
                            name: item.Name,
                            type: item.TypeName,
                            hierarchyList: item.HierarchyList
                        });
                        
                    },
                }));
        },
        setTreeLoadingState: function (isLoading) {
            var tree = this.tree;

            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);
                });
            }
        },
        save: function () {
            var that = this,
                attrs = this.model.toJSON();

            if (attrs.processing == false) {
                this.model.set('processing', true);

                try {
                    this.trigger(
                        'saving',
                        this,
                        attrs,
                        {
                            success: function (id) {
                                try {
                                    that.model.set('processing', false);

                                    that.finish({ result: 'SUCCESS', id: id });

                                    that.hide();
                                    //setTimeout(_.bind(that.hide, that), 1500);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            error: function (errorMsg) {
                                try {
                                    app.views.topMessages.showMessage(app.translate([{ options: { i18n: { 1: that.i18n, }, }, template: 1, }, app], errorMsg), { stay: 5 * 1000, });
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                                finally {
                                    that.model.set('processing', false);
                                }
                            },
                        }
                    );
                }
                catch (e) {
                    this.model.set('processing', false);
                    throw e;
                }
            }
        },
        show: function () {
            if (!this.isRendered) {
                this.render();
            }
            else {
                this.$el.modal({
                    keyboard: false,
                    backdrop: 'static',
                });
            }

            return this;
        },
        hide: function () {
            if (this.innerModal)
                this.innerModal.hide();

            var result = Modal.Views.SimpleModal.prototype.hide.apply(this, arguments);
            return result;
        },
        removeRow: function (model) {
            var that = this;
            model.collection.removeItem(
                model.get('id')
                , function (coll, data) {
                    app.views.topMessages.showMessage(app.translate([that, app], 'SAVED_CHANGES_SUCCESSFUL'), { stay: 5 * 1000, });

                    that.items.remove(model);

                    that.collection_fetch();
                }
                , function (coll, msg) {
                    app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 10 * 1000, });
                }
            );
        },
        downloadScript: function (m) {
            try {
                var that = this;

                Script.download(
                    {
                        params: {
                            id: m.get('id')
                        },
                        success: function (model, data) {
                            try {
                                // Blob for saving.
                                var blob = new Blob([new Uint8Array(data.Content)], { type: 'application/octet-stream' });

                                // Tell the browser to download the file.
                                saveAs(blob, data.FileName);
                            }
                            catch (error) {
                                console.error((error.stack) ? error.stack : new Error(error).stack);
                            }
                        },
                        error: function (model, msg) {
                            try {
                                app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 5 * 1000, });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                    }
                );
            }
            catch (error) {
                console.error((error.stack) ? error.stack : new Error(error).stack);
            }
        },


        acceptBtn_click: function (e) {
            try {
                this.save();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        collection_fetch: function (col, resp) {
            var that = this;
            var s = [];
            var e = [];

            this.items.each(
                function (m) {
                    if (m.get('statusCode') == 'EXAMPLE') {
                        e.push(m);
                    }
                    else {
                        s.push(m);
                    }
                }
            );

            s.forEach(function (model, index) {
                model.set('curSourceId', that.model.get('curSourceId'));
            });

            this.sources.set(s);

            this.examples.set(e);

            if (this.toCloneSource && !this.sources.findWhere({ id: -1 })) {
                this.addNewClone(this.toCloneSource);
            }
        },
    });

    Screen.Models.UnassignEquipmentModal = Backbone.Epoxy.Model.extend({
        defaults: {
            message: null,


            modelId: null,
            locationModelId: null,
            locations: [],
            name: null,
            type: null,
            hierarchyList: null,

            available: true,

            codesText: null,


            processing: false,
            errorMsg: "",
        },
    });

    Screen.Views.UnassignEquipmentModal = Modal2.Views.SimpleModal.extend({
        className: Modal2.Views.SimpleModal.prototype.className + ' unassign-equipment-modal',

        i18n: null,
        innerModal: null,
        templates: null,
        modelsGrid: null,
        initialize: function (options) {
            _.extend(this, options);

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

            this.items = new Screen.Models.Items();


            this.bindEvents();

            return this;
        },
        bindEvents: function () {
            Modal.Views.SimpleModal.prototype.bindEvents.apply(this, arguments);
            //this.listenTo(this.items, 'fetch', this.collection_fetch);
        },

        render: function () {

            Modal.Views.SimpleModal.prototype.render.apply(this, arguments);
            var that = this;

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

           
        },
        idChanged: function (a, b) {
            var that = this,
                text = app.translate([this, that], "root_tree_preview");


            this.items.fetchDetails(_.extend(
                {},
                {
                    data: {
                        id: b,
                    },
                    callback: function (model, item) {

                        that.model.set({
                            name: item.Name,
                            type: item.TypeName,
                            hierarchyList: item.HierarchyList
                        });

                    },
                }));
        },
        save: function () {
            var that = this,
                attrs = this.model.toJSON();

            if (attrs.processing == false) {
                this.model.set('processing', true);

                try {
                    this.trigger(
                        'saving',
                        this,
                        attrs,
                        {
                            success: function (id) {
                                try {
                                    that.model.set('processing', false);

                                    that.finish({ result: 'SUCCESS', id: id });

                                    that.hide();


                                    //setTimeout(_.bind(that.hide, that), 1500);
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                            },
                            error: function (errorMsg) {
                                try {
                                    app.views.topMessages.showMessage(app.translate([{ options: { i18n: { 1: that.i18n, }, }, template: 1, }, app], errorMsg), { stay: 5 * 1000, });
                                }
                                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                                finally {
                                    that.model.set('processing', false);
                                }
                            },
                        }
                    );
                }
                catch (e) {
                    this.model.set('processing', false);
                    throw e;
                }
            }
        },
        show: function () {
            if (!this.isRendered) {
                this.render();
            }
            else {
                this.$el.modal({
                    keyboard: false,
                    backdrop: 'static',
                });
            }

            return this;
        },
        hide: function () {
            if (this.innerModal)
                this.innerModal.hide();

            var result = Modal.Views.SimpleModal.prototype.hide.apply(this, arguments);
            return result;
        },
        removeRow: function (model) {
            var that = this;
            model.collection.removeItem(
                model.get('id')
                , function (coll, data) {
                    app.views.topMessages.showMessage(app.translate([that, app], 'SAVED_CHANGES_SUCCESSFUL'), { stay: 5 * 1000, });

                    that.items.remove(model);

                    that.collection_fetch();
                }
                , function (coll, msg) {
                    app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 10 * 1000, });
                }
            );
        },
        downloadScript: function (m) {
            try {
                var that = this;

                Script.download(
                    {
                        params: {
                            id: m.get('id')
                        },
                        success: function (model, data) {
                            try {
                                // Blob for saving.
                                var blob = new Blob([new Uint8Array(data.Content)], { type: 'application/octet-stream' });

                                // Tell the browser to download the file.
                                saveAs(blob, data.FileName);
                            }
                            catch (error) {
                                console.error((error.stack) ? error.stack : new Error(error).stack);
                            }
                        },
                        error: function (model, msg) {
                            try {
                                app.views.topMessages.showMessage(app.translate([that, app], msg), { stay: 5 * 1000, });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                    }
                );
            }
            catch (error) {
                console.error((error.stack) ? error.stack : new Error(error).stack);
            }
        },


        acceptBtn_click: function (e) {
            try {
                this.save();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        collection_fetch: function (col, resp) {
            var that = this;
            var s = [];
            var e = [];

            this.items.each(
                function (m) {
                    if (m.get('statusCode') == 'EXAMPLE') {
                        e.push(m);
                    }
                    else {
                        s.push(m);
                    }
                }
            );

            s.forEach(function (model, index) {
                model.set('curSourceId', that.model.get('curSourceId'));
            });

            this.sources.set(s);

            this.examples.set(e);

            if (this.toCloneSource && !this.sources.findWhere({ id: -1 })) {
                this.addNewClone(this.toCloneSource);
            }
        },
    });


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

        initialize: function () {
            _.extend(this, this.options);

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

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

            this.bindEvents();
        },
        events: {
        },

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

            //the screens have a custompath, so it has to be specified in the customPath variable that is
            //then sent to the template loader.
            var customPath = "/app/custom-screens/modules/equipments/configuration/" + this.template + "/";

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

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

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

                    that.applyBindings();

                    //that.$el.find('.clear-search').clearSearch();

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

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

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

        append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.state == app.view_states.loading
                || this.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.state = app.view_states.shown;
                container.append(el);

                this.onappend(this);
            }

            if (this.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        },
        close: function () {
            this.state = app.view_states.closed;

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

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

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

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

});
