//SCREEN-BOILERPLATE

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

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

  //templates-loader: this loads templates async.
  "js/templates-loader",

  "modules/modal",

  "Mousetrap", 

  "js/jstree/jstree", 

],

function (app, T, Modal, Mousetrap) {

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

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

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

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

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

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

            var items = [];
            Core.Json.CallProcedure(app.DatabaseNames.IHDelays + ".WebApp.GetProductionItemsTree", QP, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var data = data.Table;

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

                            items.push(prodItem);
                        }
                    }

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

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

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

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

            Core.Json.CallProcedure(app.DatabaseNames.IHDelays + ".WebApp.UpsertProductionItem", 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);
        },
        deleteItem: function (id, success, error) {
            var that = this;
            var QP = new QueryParameters();

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

            Core.Json.CallProcedure(app.DatabaseNames.IHDelays + ".WebApp.RemoveProductionItem", 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);
        },
        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.IHDelays + ".WebApp.MoveProductionItem", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var data = data.Table;
                        var ids = _.pluck(data, 'Id');

                        if (success != null && _.isFunction(success))
                            success.call(this, that, ids);
                    } else {
                        error.call(this, that);
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
        addNode: function (text, parent, type, position, success, error) {
            var that = this; 
            this.upsertItem(null, [
                { name: "ParentId", type: "INT", value: (parent == "#") ? null : parent },
                { name: "Type", type: "VARCHAR", value: type },
                { name: "Name", type: "VARCHAR", value: text },
            ], function (ref, ids) {
                that.add({
                    id: ids[0],
                    parent: (parent == "#") ? '#' : parseInt(parent), 
                    text: text,
                    type: type,
                    order: position, 
                });

                if (success && _.isFunction(success))
                    success.call(this, that, ids); 
            }, 
            function (ref) {
                if (error && _.isFunction(error))
                    error.call(this, that); 
            });
        },
        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, ids) {
                        if (_.indexOf(ids, parseInt(id)) != -1) {
                            model.set("text", text);

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

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

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

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

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

    OEEConfiguration.Views.Main = Backbone.View.extend({
        template: "oee-configuration"
        , id: "oee-configuration"
        , title: "OEE Configuration"
        //default not cacheable, change this if you want the view to be cacheable
        // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
        , isCacheable: true
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

            this.options.linesTree = null; 

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

            this.model = model;

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

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

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

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

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

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

            T.render.call(this, this.template, function (tmp) {
                if (!that.options.i18n) that.options.i18n = {};
                app.getI18NJed(that, that.template, function (i18nJED) {
                    //storing internationalization data
                    that.options.i18n[that.template] = i18nJED;
                    //start: before the view is visible, but the template was already loaded (not instanced nor appended)

                    //end:

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

                    //start: the view was already loaded an is on a div element, but not appended to the main container
                    //here you can perform anything you want DOM related, by getting the dom element via that.$el.find("#id")
                    //or this.$("#id")
                    //end

                    $.jstree.defaults.core.themes.variant = "large";
                    var times = 0; 
                    that.$el.find(".tree").jstree({
                        core: {
                            check_callback: true, 
                            data: function (obj, cb) {
                                var data = that.model.get("linesTreeItems").toJSON(); 
                                cb.call(this, data);
                            },
                        },
                        types: {
                            "#": {
                                valid_children: ['line'],
                                //max_children: 1
                            },
                            "line": {
                                "icon": "fa fa-sitemap",
                                valid_children: ['machine'],
                                //max_children: 1
                            },
                            "machine": {
                                "icon": "fa fa-cog",
                                max_children: 0
                            }
                        }, 
                        contextmenu: {
                            items: that.customLinesTreeCtxMenu, 
                        },
                        sort: function (a, b) {
                            var nodea = this.get_node(a);
                            var nodeb = this.get_node(b);

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

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

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

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

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

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

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

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

        , customLinesTreeCtxMenu: function (node) {
            var that = this; 
            // The default set of all items
            var items = {};

            if (OEEConfiguration.Config.addRemoveEnabled) {
                items.createItem = {
                    label: "Add Machine",
                    action: this.addMachine,
                };
            }

            if (OEEConfiguration.Config.renameEnabled) {
                items.renameItem = {
                    label: "Rename",
                    action: function (obj) {
                        that.renameNode(node);
                    },
                };
            }

            if (OEEConfiguration.Config.addRemoveEnabled) {
                items.deleteItem = {
                    label: "Delete",
                    action: function (obj) {
                        that.deleteNode(node);
                    },
                };
            }

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

            return items;
        }

        , onCreateNode: function (e, obj) {
            var node = obj.node;
            var instance = obj.instance; 
            var collection = this.model.get("linesTreeItems"); 
            collection.addNode(node.text, node.parent, node.type, obj.position + 1, function (ref, ids) {
                instance.set_id(node, ids[0]);
                instance.edit(node);

                if (app.custom_modules["oee-machines-dropdown"])
                    app.custom_modules["oee-machines-dropdown"].model.fetch(); 
            }, function () {
                instance.refresh(); 
            }); 
        }

        , onRenameNode: function(e, obj){
            var node = obj.node;
            var instance = obj.instance;
            var collection = this.model.get("linesTreeItems");
            collection.renameNode(node.id, node.text, function (ref, ids) {
                instance.set_id(node, ids[0]);

                if (app.custom_modules["oee-machines-dropdown"])
                    app.custom_modules["oee-machines-dropdown"].model.fetch();
            }, function () {
                instance.refresh();
            });
        }

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

            var node = obj.node;
            var instance = obj.instance;
            var collection = this.model.get("linesTreeItems");
            collection.deleteNode(node.id, function (ref, ids) {

                if (app.custom_modules["oee-machines-dropdown"])
                    app.custom_modules["oee-machines-dropdown"].model.fetch();
            }, function () {
                instance.refresh();
            });
        }

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

            collection.reorderNode(node.id, node.parent, obj.position + 1, function (ref, ids) {
                //instance.refresh(); 
                that._autoRefresh();
            }, function () {
                instance.refresh();
            });
        }

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

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

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

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

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

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

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

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

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

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

        , renameNode: function (data) {
            var tree = this.options.linesTree;
            var selected = tree.get_selected();
            
            if (selected.length > 0)
                data = selected[0]; 

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

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

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

            tree.delete_node(data); 
        }

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

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

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

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

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

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

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

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

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

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

                this.options.onappend(this);
            }

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

            if (this.options.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        }

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

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

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

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

            this.refresh();

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

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

        , refresh: function () {
            try {
                var that = this; 
                this.model.get("linesTreeItems").fetch({
                    //callback: function () {
                    //    that.options.linesTree.refresh(); 
                    //}, 
                });
            } catch (Error) { }
        }

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

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

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

        , bindEvents: function () {
            //this function should be in every view that uses listenTo anywhere
            //all the model bindings or view-model binding should be here, to manage
            //the show/hide view easily
            this.listenTo(this.model.get("linesTreeItems"), "add", this.linesTreeItemsChanged);
            this.listenTo(this.model.get("linesTreeItems"), "remove", this.linesTreeItemsChanged);
            this.listenTo(this.model.get("linesTreeItems"), "change", this.linesTreeItemsChanged);
        }

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

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

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

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

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

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

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

        , reRender: function () {
        }
    });

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

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

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

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

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

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

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

                            badUnitProducedTagId: machineData.BadUnitProducedTagId,
                            badUnitProducedTagAscendingFlank: machineData.BadUnitProducedTagAscendingFlank,
                            badUnitProducedTagResetsAt: machineData.BadUnitProducedTagResetsAt, 

                            unitProducedIncludesBadUnits: machineData.UnitProducedIncludesBadUnits, 

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

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

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

                        that.options.loaded = true;

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

            runningTagId: null,
            runningTagAscendingFlank: null, 
            
            unitProducedTagId: null,
            unitProducedTagAscendingFlank: null,
            unitProducedTagResetsAt: null, 

            badUnitProducedTagId: null,
            badUnitProducedTagAscendingFlank: null,
            badUnitProducedTagResetsAt: null, 

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

            microDelayValue: null,
            microDelayTime: null, 

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

            _.extend(options, opt); 

            var QP = new QueryParameters();

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

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

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

    OEEConfiguration.Views.MachineConfiguration = Backbone.Epoxy.View.extend({
        template: "oee-configuration"
        , id: "oee-configuration"
        , title: "OEE Configuration"
        //default not cacheable, change this if you want the view to be cacheable
        // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
        , isCacheable: false
        , bindings: "data-bind"
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

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

            this.options.MYREFERENCES.subviews = {};

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

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

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

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

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

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

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

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

                        that.applyBindings(); 

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

                        //end:

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

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

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

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

                this.options.onappend(this);
            }

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

            if (this.options.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        }

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

        , refresh: function (viewParams) {
        }

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

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

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

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

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

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

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

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

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

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

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

        , bindViewScopedEvents: function () {
        }

        , unbindViewScopedEvents: function () {
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

});
