//SCREEN-BOILERPLATE

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

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

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

  "modules/modal",

  "js/jstree/jstree", 

],

function (app, T, Modal) {

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

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

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

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

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

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

            var items = [];
            items.push({
                id: -2,
                parent: '#',
                type: "storage",
                text: options.storageItemText,
            }, 
            {
                id: -1,
                parent: '#',
                type: "root",
                text: options.firstItemText
            });

            Core.Json.CallProcedure(app.DatabaseNames.System + ".SBuilder.GetScreenBuilderMenuTree", 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 item = {
                                id: itemData.Id,
                                parent: (itemData.ParentId != null) ? itemData.ParentId : -1,
                                type: itemData.Type,
                                text: itemData.Name,
                            };

                            items.push(item);
                        }
                    }

                    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 () {
        },
        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", "VARCHAR", id);

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

            Core.Json.CallProcedure(app.DatabaseNames.System + ".SBuilder.UpsertScreen", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var status = { Status: 'FAILED', Code: null }; 
                        if (data && data.Table1) {
                            status = data.Table && data.Table[0] ? data.Table[0] : status;
                        } else {
                            status = { Status: 'SUCCESS', Code: null };
                        }
                        
                        var data = (data.Table1) ? data.Table1 : data.Table;

                        if (status && status.Status == 'SUCCESS') {
                            var ids = _.pluck(data, 'Id');

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

            QP.Add("@Id", "VARCHAR", id);
            QP.Add("@Type", "VARCHAR", type);

            Core.Json.CallProcedure(app.DatabaseNames.System + ".SBuilder.RemoveSBuilderItem", 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, type, parent, success, error) {
            try{
                var that = this;
                this.upsertItem(null, [
                    { name: "ParentId", type: "VARCHAR", value: (parent == "-1") ? null : parent },
                    { name: "Name", type: "VARCHAR", value: text },
                    { name: "Type", type: "VARCHAR", value: type },
                ], function (ref, ids) {
                    var fn_continue = function(){
                        that.add({
                            id: ids[0],
                            parent: (parent == "#") ? '#' : parent,
                            type: type,
                            text: text,
                        });

                        if (success && _.isFunction(success))
                            success.call(this, that, ids);
                    }

                    if (type == "builder-screen") {
                        that.callAPI({
                            action: 'CREATE_SCREEN',
                            screenId: ids[0].toString().replace("sbs-", ""),
                        }, function (status, res) {
                            if (status) {
                                fn_continue(); 
                            } else {
                                if (error && _.isFunction(error))
                                    error.call(this, that);
                            }
                        });
                    } else {
                        fn_continue(); 
                    }
                }, 
                function (ref, code) {
                    if (error && _.isFunction(error))
                        error.call(this, that, code); 
                });
            } catch (error) {
                error;
            }
        },
        renameNode: function (id, text, type, success, error) {
            var that = this;
            var model = this.get(id);

            if (model.get("text") == text) {
                if (success && _.isFunction(success))
                    success.call(this, that, [id]);

                return; 
            }

            if (model){
                this.upsertItem(id, [
                    { name: "Name", type: "VARCHAR", value: text }, 
                    { name: "Type", type: "VARCHAR", value: type }, 
                ], function (ref, ids) {
                    if (_.indexOf(ids, id) != -1) {
                        model.set("text", text);

                        app.models.appController.set("menuChanged", true);

                        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, type, success, error) {
            var that = this;
            var model = this.get(id);
            if (model) {
                this.deleteItem(
                    id, 
                    type, 
                    function (ref, ids) {
                        var continue_fn = function () {
                            //removing from collection; 
                            that.remove(model);

                            app.models.appController.set("menuChanged", true);

                            if (success && _.isFunction(success))
                                success.call(this, that, ids);
                        };

                        if (type == "builder-screen") {
                            that.callAPI({
                                action: 'REMOVE_SCREEN',
                                screenId: ids[0].toString().replace("sbs-", ""),
                            }, function (status, res) {
                                if (status) {
                                    continue_fn(); 
                                } else {
                                    if (error && _.isFunction(error))
                                        error.call(this, that);
                                }
                            });
                        } else {
                            continue_fn(); 
                        }
                    },
                    function (ref) {
                        if (error && _.isFunction(error))
                            error.call(this, that);
                    }
                );
            }
        },
        callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }
    });

    ScreenBuilder.Models.Main = Backbone.Model.extend({
        defaults: {
            treeItems: null, 
        },
        initialize: function () {
            this.set("treeItems", new ScreenBuilder.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.
    ScreenBuilder.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "screen-builder"; 
        } catch (Error) { }
    }

    ScreenBuilder.Views.Main = Backbone.View.extend({
        template: "screen-builder"
        , id: "screen-builder"
        , title: "Screen Builder"
        //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.screensTree = null; 

            var model = new ScreenBuilder.Models.Main({ });

            this.model = model;

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

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

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

        events: {
            "click .btn-add-screen": "addScreen",
            "click .btn-add-menu": "addMenu",
        }, 

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

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

                    //end:

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

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

                    $.jstree.defaults.core.themes.variant = "large";
                    var times = 0; 
                    that.$el.find(".tree").jstree({
                        core: {
                            check_callback: true, 
                            data: function (obj, cb) {
                                var data = that.model.get("treeItems").toJSON(); 
                                cb.call(this, data);
                            },
                            multiple: false,
                            strings: {
                                'New node': app.translate(that, 'new_node_text'),
                            }
                        },
                        types: {
                            "#": {
                                valid_children: ['root'],
                                max_children: 1, 
                            },
                            "root": {
                                icon: "fa fa-desktop",
                                valid_children: ['menu', 'builder-menu', 'screen', 'builder-screen'],
                            },
                            "storage": {
                                //icon: "fa fa-hdd-o",
                                icon: "fa fa-database", 
                                valid_children: [],
                            },
                            "builder-menu": {
                                "icon": "fa fa-bars",
                                valid_children: ['builder-menu', 'builder-screen'],
                            },
                            "builder-screen":{
                                "icon": "fa fa-list-alt",
                                valid_children: ['builder-menu', 'builder-screen'],
                            }, 
                            "menu": {
                                "icon": "fa fa-bars",
                                valid_children: ['menu', 'builder-menu', 'screen', 'builder-screen'],
                            },
                            "screen": {
                                "icon": "fa fa-list-alt",
                                valid_children: ['menu', 'builder-menu', 'screen', 'builder-screen'],
                            },
                        }, 
                        contextmenu: {
                            items: that.customCtxMenu, 
                        },
                        plugins: [
                            "contextmenu",
                            "wholerow",
                            "types",
                        ], 
                    });

                    that.options.screensTree = 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,
                        "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.screensTree.select_node(that.options.screensTree.get_node("-1"));
                        }),
                    });

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

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

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

            // The default set of all items
            var items = {
            };

            if (node.type != "storage") {
                items = {
                    createMenu: {
                        label: app.translate(that, "add_menu_label"),
                        action: that.addMenu,
                    },
                    createScreen: {
                        label: app.translate(that, "add_screen_label"),
                        action: that.addScreen,
                    },
                    deleteItem: {
                        label: app.translate(that, "remove_item_label"),
                        action: function (obj) {
                            that.deleteNode(node);
                        },
                    },
                    renameItem: {
                        label: app.translate(that, "rename_item_label"),
                        action: function (obj) {
                            that.renameNode(node);
                        },
                    }
                }

                if (node.type.indexOf("builder") == -1) {
                    delete items["deleteItem"];
                    delete items["renameItem"];
                }

                if (node.parent == "#") {
                    delete items["deleteItem"];
                    delete items["renameItem"];
                }

                if (node.type == "screen" || node.type == "builder-screen") {
                    delete items["createScreen"];
                    delete items["createMenu"];
                }

                if (node.parents.length > 2){
                    delete items["createMenu"];
                }
            }

            return items;
        }

        , onCreateNode: function (e, obj) {
            var that = this; 
            var node = obj.node;
            var instance = obj.instance; 
            var collection = this.model.get("treeItems"); 
            collection.addNode(node.text, node.type, node.parent, function (ref, ids) {
                instance.set_id(node, ids[0]);
                instance.edit(node); 
            }, function (ref, code) {
                code = (code) ? code : 'UNKNOWN_ERROR';
                app.views.topMessages.showMessage(app.translate(that, code + '_top_message'));

                instance.refresh(); 
            }); 
        }

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

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

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

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

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

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

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

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

                    var id = node.id.replace("sbs-", ""); 
                    var model = new ScreenBuilder.Models.ScreenConfiguration();
                    this.options.MYREFERENCES.subviews.screenConfiguration.view = new ScreenBuilder.Views.ScreenConfiguration({
                        container: codeConfigurationContainer,
                        model: model,
                        parent: that, 
                    });

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

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

                if (node.type == "storage") {
                    var codeConfigurationContainer = this.$el.find(".screen-configuration-container");

                    var model = new ScreenBuilder.Models.StorageConfiguration();
                    this.options.MYREFERENCES.subviews.storageConfiguration.view = new ScreenBuilder.Views.StorageConfiguration({
                        container: codeConfigurationContainer,
                        model: model,
                        parent: that,
                    });

                    model.fetch({
                        data: {
                        }
                    });

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

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

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

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

        , renameNode: function (data) {
            var tree = this.options.screensTree;
            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 that = this; 
            var tree = this.options.screensTree;
            var selected = tree.get_selected();

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

            if (data) {
                var node = tree.get_json(data[0]);
                var type = node.type;
                var text = node.text; 

                var modalConfirm = new Modal.Views.Main({
                    title: app.translate(that, "modal_delete_item_title_" + type),
                    buttons_type: "CONTINUE-CANCEL",
                    message: app.translate(that, "modal_delete_item_message_" + type, [text])
                });

                modalConfirm.on("continue", function () {
                    tree.delete_node(data);
                });

                modalConfirm.show(); 
            }
        }

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

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

            sel = tree.create_node(sel, { "type": "builder-screen" }, "last", function (a, b, c) {
                a; 
            });
        }

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

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

            sel = tree.create_node(sel, { "type": "builder-menu" }, "last", function (a, b, c) {
                a;
            });
        }

        , callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }

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

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

        , checkAddCodeButtons: function (e, data) {
            var btnAddScreen = this.$el.find(".btn-add-screen");
            var btnAddMenu = this.$el.find(".btn-add-menu");
            if (data.node.type != "storage") {
                //if it's not storage

                btnAddScreen.prop("disabled", false);
                btnAddMenu.prop("disabled", false);

                if (data.node.type == "screen" || data.node.type == "builder-screen") {
                    btnAddScreen.prop("disabled", true);
                    btnAddMenu.prop("disabled", true);
                }

                if (data.node.parents.length > 2) {
                    btnAddMenu.prop("disabled", true);
                }
            } else {
                btnAddScreen.prop("disabled", true);
                btnAddMenu.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("treeItems").fetch({
                    firstItemText: app.translate(that, "screens_tree_text"),
                    storageItemText: app.translate(that, "storage_tree_text"),
                    //callback: function () {
                    //    that.options.screensTree.refresh(); 
                    //}, 
                });
            } catch (Error) { }
        }

        , treeItemsChanged: 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.screensTree.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("treeItems"), "add", this.treeItemsChanged);
            this.listenTo(this.model.get("treeItems"), "remove", this.treeItemsChanged);
            this.listenTo(this.model.get("treeItems"), "change", this.treeItemsChanged);
        }

        , close: function () {
            this._stopAutoRefresh();
            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._stopAutoRefresh();

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

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

        , reRender: function () {
            this._startAutoRefresh();
        }
    });

    ScreenBuilder.Models.ScreenConfiguration = Backbone.Epoxy.Model.extend({
        defaults: {
            id: null,
            name: null,
            description: null,
            enabled: null,
            files: [], 

            filesBinding: [], 
        }
        , initialize: function () {
            var opts = { loaded: false, }; 
            this.options = _.extend(this.options ? this.options : {}, opts);
        }
        , fetch: function (options) {
            var that = this; 

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

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

                        var screenConfiguration = _.extend({}, that.attributes, {
                            id: screenData.Id,
                            name: screenData.Name, 
                            description: screenData.Description,
                            enabled: screenData.Enabled,
                        });

                        that.options.loaded = true;
                        that.set(screenConfiguration, { from: "fetch" });
                        that.refreshUploadedFiles(); 
                    }
                },
                Async: true,
                Secured: true
            }, app.ConnectionStrings.app);
        }
        
        , refreshUploadedFiles: function () {
            var that = this; 
            that.callAPI({
                action: 'GET_UPLOADED_FILES',
                screenId: that.get("id"),
                global: false, 
            }, function (status, response) {
                if (status == true && response && response.Data && response.Data.Files) {
                    var files = response.Data.Files;
                    var filesBinding = _.map(files, function (value, key) {
                        return { label: key, value: key }
                    });

                    that.set({ files: files, filesBinding: filesBinding }, { from: "fetch" });
                }
            });
        }

        , callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }

        , save: function (opt) {
            var that = this; 
            var options = {
                callback: function () { }
            };

            _.extend(options, opt); 

            var QP = new QueryParameters();

            var params = [
                ["@Id", "INT", "id"],
                ["@name", "VARCHAR", "name"],
                ["@description", "VARCHAR", "description"],
                ["@enabled", "BIT", "enabled"],
            ]; 

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

            QP.Add("@type", "VARCHAR", "BUILDER-SCREEN"); 

            Core.Json.CallProcedure(app.DatabaseNames.System + ".SBuilder.UpdateSBuilderItem", 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: {
        }
    });

    ScreenBuilder.Views.ScreenConfiguration = Backbone.Epoxy.View.extend({
        template: "screen-builder"
        , id: "screen-builder"
        , title: "Screen Builder"
        //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.saveDebounced = _.debounce(_.bind(this.saveScreenConfiguration, this), 500); 

            this.options.MYREFERENCES.subviews = {};

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

        events: {
            "click .btn-save": "saveScreenConfiguration",
            "click .btn-cancel": "cancelScreenConfiguration",

            "click .fileinput-button": "browseFile",
            "change #fileinput": "fileChanged",
            "click .btn-upload-file": "uploadFile",
            "click .btn-cancel-upload-file": "cancelUploadFile",
            "click .btn-remove-file": "removeFile",
            "click .btn-download-file": "downloadFile",
            "change .files-select": "filesSelectChanged", 
        },

        browseFile: function () {
            try{
                this.$el.find("#fileinput").get(0).click();
            } catch (Error) {
            }
        }

        , fileChanged: function () {
            var file_form = this.$el.find(".add-file-form");
            var review_file_form = this.$el.find(".review-file-form"); 

            var fileinput = this.$el.find("#fileinput").get(0);
            var files = fileinput.files;

            if (files.length > 0) {
                var file = files[0];
                var filename = file.name;

                this.$el.find(".input-file-filename").val(filename);

                file_form.addClass("hide");
                review_file_form.removeClass("hide"); 
            }
        }

        , cancelUploadFile: function () {
            var file_form = this.$el.find(".add-file-form");
            var review_file_form = this.$el.find(".review-file-form");
            var file_upload_failed = this.$el.find(".file-upload-failed");
            
            var fileinput = this.$el.find("#fileinput");
            fileinput.replaceWith(fileinput = fileinput.clone(true));

            review_file_form.addClass("hide"); 
            file_upload_failed.addClass("hide"); 
            this.$el.find(".file-upload-successful-message, .file-detected-on-server-message, .file-upgrade-process-started, " +
                ".file-upgrade-success-message, .file-upgrade-failed-message").addClass("hide"); 
            file_form.removeClass("hide");
        }

        , uploadFile: function () {
            try {
                var review_file_form = this.$el.find(".review-file-form");
                var file_upload_progress = this.$el.find(".file-upload-progress"); 

                var that = this; 

                var fileinput = $("#fileinput").get(0);
                var files = fileinput.files; 
                var formData = new FormData();

                //formData.append('files[]', files);
                for (var i = 0; i < files.length; i++) {
                    var file = files[i];

                    // Add the file to the request.
                    formData.append('files['+ i.toString() +']', file, file.name);
                }

                formData.append("action", "UPLOAD_FILE");
                formData.append("screenId", this.model.get("id"));

                if (formData) {
                    review_file_form.addClass("hide"); 
                    file_upload_progress.removeClass("hide"); 

                    $.ajax({
                        url: app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx",
                        type: 'POST',
                        // handle the progress report
                        xhr: function () {  // Custom XMLHttpRequest
                            var myXhr = $.ajaxSettings.xhr();
                            if (myXhr.upload) { // Check if upload property exists
                                myXhr.upload.addEventListener('progress', _.bind(that.uploadfileProgressHandler, that), false); // For handling the progress of the upload
                            }
                            return myXhr;
                        },

                        // Form data
                        data: formData,

                        //Options to tell jQuery not to process data or worry about content-type.
                        cache: false,
                        contentType: false,
                        processData: false
                    })
                    .done(_.bind(that.uploadfileComplete, that))
                    .fail(_.bind(that.uploadfileFailed, that));
                }
            } catch (Error) {
            }
        }

        , uploadfileComplete: function (data) {
            try {
                var file_upload_progress = this.$el.find(".file-upload-progress");
                file_upload_progress.addClass("hide");
                if (data != null && data != undefined && data.Success == true) {
                    this.$el.find(".file-upload-successful-message").removeClass("hide");
                } else {
                    this.uploadfileFailed();
                }

                this.model.refreshUploadedFiles(); 
            } catch (Error) { }
        }

        , uploadfileFailed: function (e) {
            try {
                var file_upload_progress = this.$el.find(".file-upload-progress");
                var file_upload_failed = this.$el.find(".file-upload-failed");

                file_upload_progress.addClass("hide");
                file_upload_failed.removeClass("show");

                this.model.refreshUploadedFiles();
            } catch (Error) { }
        }

        , uploadfileProgressHandler: function (e) {
            var upload_progress_bar = this.$el.find(".file-upload-progress-bar");
            var loaded = e.loaded;
            var total = e.total;

            var percent = (loaded * 100) / total;
            upload_progress_bar.css("width", percent + "%");
        }

        , filesSelectChanged: function () {
            var that = this;
            var filesSelect = this.$el.find(".files-select");

            if (filesSelect && filesSelect.val() && _.isArray(filesSelect.val()) && filesSelect.val().length > 0) {
                this.$el.find(".btn-remove-file").attr("disabled", false);
                this.$el.find(".btn-download-file").attr("disabled", false);
            } else {
                this.$el.find(".btn-remove-file").attr("disabled", true);
                this.$el.find(".btn-download-file").attr("disabled", true);
            }
        }

        , removeFile: function () {
            try{
                var that = this;
                var filesSelect = this.$el.find(".files-select");
                var val = filesSelect.val().join(';');

                this.callAPI({
                    action: "REMOVE_FILE", 
                    files: val, 
                    screenId: this.model.get("id"), 
                }, function (status, res) {
                    that.model.refreshUploadedFiles(); 
                });
            } catch (error) { console.log("Error: " + error.toString()); }
        }

        , downloadFile: function () {
            try {
                var that = this;
                var filesSelect = this.$el.find(".files-select");
                var val = filesSelect.val();
                var files = this.model.get("files"); 

                for (var i = 0, len = val.length; i < len; i++) {
                    try{
                        //trigger automatic download
                        //location.href = files[val[i]] + "?download=true";
                        window.open(files[val[i]], "_blank"); 
                    } catch (error) { console.log("Error while trying to trigger an automatic download."); }
                }
            } catch (error) { }
        }

        , callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }

        , 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/screen-builder/configuration/screen-builder/";

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

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

                        that.applyBindings(); 

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

                        //end:

                    }, true, customPath);
                }, customPath, "screen_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.options.saveDebounced(); 
                //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);
        }

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

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

                    that.options.parent.refresh(); 
                }
            }); 
        }

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

        , 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("subnavbar", false);
            app.models.subnavbar.setAll(false);
        }
    });

    ScreenBuilder.Models.StorageConfiguration = Backbone.Epoxy.Model.extend({
        defaults: {
            id: null,
            name: null,
            description: null,
            enabled: null,
            files: [],

            filesBinding: [],
        }
        , initialize: function () {
            var opts = { loaded: false, };
            this.options = _.extend(this.options ? this.options : {}, opts);
        }
        , fetch: function (options) {
            var that = this;
            that.options.loaded = true;
            that.refreshUploadedFiles(); 
        }
        , refreshUploadedFiles: function () {
            var that = this;
            that.callAPI({
                action: 'GET_UPLOADED_FILES',
                screenId: null,
                global: true,
            }, function (status, response) {
                if (status == true && response && response.Data && response.Data.Files) {
                    var files = response.Data.Files;
                    var filesBinding = _.map(files, function (value, key) {
                        return { label: key, value: key }
                    });

                    that.set({ files: files, filesBinding: filesBinding }, { from: "fetch" });
                }
            });
        }
        , callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }, 
        computeds: {
        }
    });

    ScreenBuilder.Views.StorageConfiguration = Backbone.Epoxy.View.extend({
        template: "screen-builder"
        , id: "screen-builder-storage-configuration"
        , title: "Storage 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();
        },

        events: {
            "click .fileinput-button": "browseFile",
            "change #fileinput": "fileChanged",
            "click .btn-upload-file": "uploadFile",
            "click .btn-cancel-upload-file": "cancelUploadFile",
            "click .btn-remove-file": "removeFile",
            "change .files-select": "filesSelectChanged",
        },

        browseFile: function () {
            try {
                this.$el.find("#fileinput").get(0).click();
            } catch (Error) {
            }
        }

        , fileChanged: function () {
            var file_form = this.$el.find(".add-file-form");
            var review_file_form = this.$el.find(".review-file-form");

            var fileinput = this.$el.find("#fileinput").get(0);
            var files = fileinput.files;

            if (files.length > 0) {
                var file = files[0];
                var filename = file.name;

                this.$el.find(".input-file-filename").val(filename);

                file_form.addClass("hide");
                review_file_form.removeClass("hide");
            }
        }

        , cancelUploadFile: function () {
            var file_form = this.$el.find(".add-file-form");
            var review_file_form = this.$el.find(".review-file-form");
            var file_upload_failed = this.$el.find(".file-upload-failed");

            var fileinput = this.$el.find("#fileinput");
            fileinput.replaceWith(fileinput = fileinput.clone(true));

            review_file_form.addClass("hide");
            file_upload_failed.addClass("hide");
            this.$el.find(".file-upload-successful-message, .file-detected-on-server-message, .file-upgrade-process-started, " +
                ".file-upgrade-success-message, .file-upgrade-failed-message").addClass("hide");
            file_form.removeClass("hide");
        }

        , uploadFile: function () {
            try {
                var review_file_form = this.$el.find(".review-file-form");
                var file_upload_progress = this.$el.find(".file-upload-progress");

                var that = this;

                var fileinput = $("#fileinput").get(0);
                var files = fileinput.files;
                var formData = new FormData();

                //formData.append('files[]', files);
                for (var i = 0; i < files.length; i++) {
                    var file = files[i];

                    // Add the file to the request.
                    formData.append('files[' + i.toString() + ']', file, file.name);
                }

                formData.append("action", "UPLOAD_FILE");
                formData.append("global", true);

                if (formData) {
                    review_file_form.addClass("hide");
                    file_upload_progress.removeClass("hide");

                    $.ajax({
                        url: app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx",
                        type: 'POST',
                        // handle the progress report
                        xhr: function () {  // Custom XMLHttpRequest
                            var myXhr = $.ajaxSettings.xhr();
                            if (myXhr.upload) { // Check if upload property exists
                                myXhr.upload.addEventListener('progress', _.bind(that.uploadfileProgressHandler, that), false); // For handling the progress of the upload
                            }
                            return myXhr;
                        },

                        // Form data
                        data: formData,

                        //Options to tell jQuery not to process data or worry about content-type.
                        cache: false,
                        contentType: false,
                        processData: false
                    })
                    .done(_.bind(that.uploadfileComplete, that))
                    .fail(_.bind(that.uploadfileFailed, that));
                }
            } catch (Error) {
            }
        }

        , uploadfileComplete: function (data) {
            try {
                var file_upload_progress = this.$el.find(".file-upload-progress");
                file_upload_progress.addClass("hide");
                if (data != null && data != undefined && data.Success == true) {
                    this.$el.find(".file-upload-successful-message").removeClass("hide");
                } else {
                    this.uploadfileFailed();
                }

                this.model.refreshUploadedFiles();
            } catch (Error) { }
        }

        , uploadfileFailed: function (e) {
            try {
                var file_upload_progress = this.$el.find(".file-upload-progress");
                var file_upload_failed = this.$el.find(".file-upload-failed");

                file_upload_progress.addClass("hide");
                file_upload_failed.removeClass("show");

                this.model.refreshUploadedFiles();
            } catch (Error) { }
        }

        , uploadfileProgressHandler: function (e) {
            var upload_progress_bar = this.$el.find(".file-upload-progress-bar");
            var loaded = e.loaded;
            var total = e.total;

            var percent = (loaded * 100) / total;
            upload_progress_bar.css("width", percent + "%");
        }

        , filesSelectChanged: function () {
            var that = this;
            var filesSelect = this.$el.find(".files-select");

            if (filesSelect && filesSelect.val() && _.isArray(filesSelect.val()) && filesSelect.val().length > 0) {
                this.$el.find(".btn-remove-file").attr("disabled", false);
            } else {
                this.$el.find(".btn-remove-file").attr("disabled", true);
            }
        }

        , removeFile: function () {
            try {
                var that = this;
                var filesSelect = this.$el.find(".files-select");
                var val = filesSelect.val().join(';');

                this.callAPI({
                    action: "REMOVE_FILE",
                    files: val,
                    global: true, 
                }, function (status, res) {
                    that.model.refreshUploadedFiles();
                });
            } catch (error) { console.log("Error: " + error.toString()); }
        }

        , callAPI: function (data, callback) {
            var that = this;
            $.ajax(app.foldersRoot + "/app/custom-screens/screen-builder/configuration/screen-builder/api/api.aspx", {
                type: 'POST',
                data: data,
                success: function (res) {
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, true, res);
                    }
                },
                error: function (res) {
                    console.log("error");
                    if (callback && _.isFunction(callback)) {
                        callback.call(that, false, res);
                    }
                }
            });
        }

        , 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/screen-builder/configuration/screen-builder/";

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

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

                        that.applyBindings();

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

                        //end:

                    }, true, customPath);
                }, customPath, "storage_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) {
        }

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

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

        , 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("subnavbar", false);
            app.models.subnavbar.setAll(false);
        }
    });

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

});
