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

  "custom-screens/IHConfiguration/tags-configuration-v2/tags-configuration",
  "custom-screens/IHConfiguration/tags-export-configuration/tags-export-configuration",
  "custom-screens/IHConfiguration/data-sources-configuration-v2/data-sources-configuration", 
  "custom-screens/IHConfiguration/account-information/account-information",
  "custom-screens/IHConfiguration/users/users", 
  "custom-screens/IHConfiguration/install-agent/install-agent",
  "custom-screens/IHConfiguration/system-network-configuration/system-network-configuration",
  "custom-screens/IHConfiguration/reset-to-factory-defaults/reset-to-factory-defaults",
  "custom-screens/IHConfiguration/network-overview-d3js/network-overview",
  //"custom-screens/IHConfiguration/dot-programs/dot-programs",
  "custom-screens/IHConfiguration/security/profiles/profiles",
//  "custom-screens/IHConfiguration/send-agent-commands/send-agent-commands",
  "custom-screens/about/about",
  "custom-screens/IHConfiguration/upload-update/upload-update",

//  "custom-modules/datablocks-conflicts/datablocks-conflicts",
],

function (app, T, Modal, Handlebars

        //screens
        , TagsConfiguration, TagsExportConfiguration, DataSourcesConfiguration, AccountInformation
        , Users, InstallAgent, SystemNetworkConfiguration
        , ResetToFactoryDefaults
        , NetworkOverview
        //, DotPrograms

        , SecurityProfiles
        //, SendAgentCommands

        , About
        , UploadUpdate

        //modules
      //  , DatablocksConflicts
        ) {

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

    ConfigurationDashboard.Models.Main = Backbone.Model.extend({
        defaults: {
            screenModules: {
                "tags": TagsConfiguration,
                "tagsexportconfiguration": TagsExportConfiguration,
                "datasources": DataSourcesConfiguration,
                "networkoverview": NetworkOverview,
                "accountinformation": AccountInformation,
                "users": Users,
                "installagent": InstallAgent,
                "systemnetworkconfiguration": SystemNetworkConfiguration,
                "resettofactorydefaults": ResetToFactoryDefaults,
               // "dotprograms": DotPrograms,
                "securityprofiles": SecurityProfiles,
                //"commands": SendAgentCommands,
                "about": About,
                "update": UploadUpdate,
            }
        }
    });

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

    ConfigurationDashboard.Views.Main = Backbone.View.extend({
        template: "configuration-dashboard"
        , id: "configuration-dashboard"
        , title: "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
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            _.bindAll(this);

            if (this.options.viewParams) { }

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

            this.model = model;

            this.options.MYREFERENCES = {
                autoRefresh: {
                    enabled: false
                    , toid: null
                }
                , subviews: {

                }
            };

            this.getConfigurationRoutes();
            this.bindEvents();  
        },
        routingtimestamp: null,

        getConfigurationRoutes: function () {
            var routes = app.getRoutes("configuration-dashboard", false, false, null);
            var screenModules = this.model.get("screenModules");

            _.each(routes, function (t) {
                if (!screenModules[t.Route]) {
                    screenModules[t.Route] = t.ModulePath + t.Name; 
                }
            }); 
        }, 

        events: {
            'click .btn-hide-sidemenu': 'hide_sidemenu', 
        }, 

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

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

            T.render.call(this, this.template, function (tmp) {

                //start: before the view is visible, but the template was already loaded (not instanced nor appended)
                var ctx = {
                    showUsers: (($.inArray("AdminUserRole", app.models.user.get("roles")) != -1
                        || $.inArray("SupervisorUserRole", app.models.user.get("roles")) != -1) ? true : false),
                    showSystemAdminDashboard: (($.inArray("SystemAdminRole", app.models.user.get("roles")) != -1) ? true : false),
                    showSystemNetworkConfiguration: ($.inArray("AdminUserRole", app.models.user.get("roles")) != -1),
                    showResetToFactoryDefaults: ($.inArray("AdminUserRole", app.models.user.get("roles")) != -1),
                    showTagsExporationConfiguration: ($.inArray("AdminUserRole", app.models.user.get("roles")) != -1),
                };
                //end:

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

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

                that.bindViewScopedEvents(); 

                that.refresh(viewParams, { fromRender: true });

                //that.updateDisplayDataSourcesItemErrorIcon();

            }, customPath);
        }

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

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

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

        , hide_sidemenu: function () {
            this.$el.find('.configuration-sidemenu').fadeOut();
            this.$el.find('.hamburguer-menu').removeClass('hide'); 

            this.$el.find('.configuration-content').removeClass('offset3').removeClass('span9');
            this.$el.find('.configuration-content').addClass('offset1').addClass('span11');
            app.models.subnavbar.set({ span: 11, offset: 1 });
        }

        , _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.options.MYREFERENCES.autoRefresh.toid = setTimeout(this._autoRefresh, 1);
            } catch (Error) { console.error(Error); }
        }

        , _autoRefresh: function () {
            //console.log("autorefresh: " + new Date().toString()); 
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }
           
            this.refresh(false); 

            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: _.debounce(function (viewParams, opt) {
            try {
                var that = this;
                var thatContainer = this.options.container;

                var options = {
                    fromRender: false,
                    preventAskBeforeClose: false, 
                }; 

                _.extend(options, opt); 

                if (!viewParams || !viewParams.section) {
                    viewParams.section = "tags"; 
                }

                var screenModule = that.model.get("screenModules")[viewParams.section.toLowerCase()];

                var screenParams = {
                    sectionParam1: (viewParams && viewParams.sectionParam1) ? viewParams.sectionParam1 : null,
                    sectionParam2: (viewParams && viewParams.sectionParam2) ? viewParams.sectionParam2 : null,
                };

                var currentScreen = (that.options.MYREFERENCES.subviews.screen &&
                                    that.options.MYREFERENCES.subviews.screen.id)
                                    ? that.options.MYREFERENCES.subviews.screen.id : null;

                var routingtimestamp_temp = this.routingtimestamp = new Date().getTime();
                var continue_fn = function (screenModule) {
                    if (routingtimestamp_temp != that.routingtimestamp) {
                        return;
                    }

                    var screenModuleId = (screenModule && screenModule.generateID) ? screenModule.generateID(screenParams) : false;

                    if (screenModule != null && screenModule != undefined && ((currentScreen != screenModuleId) || !screenModuleId)) {

                        //checking if the view has a beforeClose method defined or a boolean variable
                        var currentScreen = that.options.MYREFERENCES.subviews.screen;
                        if (currentScreen && currentScreen.beforeClose != null && currentScreen.beforeClose != undefined
                            && (_.isFunction(currentScreen.beforeClose) || _.isBoolean(currentScreen.beforeClose))) {
                            var allowClose = (_.isFunction(currentScreen.beforeClose)) ? currentScreen.beforeClose.call(this) : currentScreen.beforeClose;

                            if (allowClose === false && options.preventAskBeforeClose !== true) {
                                this.showAskBeforeCloseModal(
                                    currentScreen.askBeforeCloseOpt,
                                    viewParams
                                );

                                return;
                            }
                        }

                        that.$el.find("[data-screenid]").removeClass("active");
                        //if there's a screen already opened then close it.
                        if (that.options.MYREFERENCES.subviews.screen && that.options.MYREFERENCES.subviews.screen.close) {
                            that.options.MYREFERENCES.subviews.screen.close();
                        }

                        if (!NProgress.isStarted()) NProgress.start();

                        that.options.MYREFERENCES.subviews.screen = new screenModule.Views.Main({
                            parent: this,
                            container: that.$el.find("#configuration_dashboard_screen_container"),
                            viewParams: screenParams,
                            onappend: ((options.fromRender) ? that.options.onappend : function () { NProgress.done(); })
                        });

                        that.$el.find("[data-screenid='" + that.options.MYREFERENCES.subviews.screen.id + "']").addClass("active");

                        that.options.MYREFERENCES.subviews.screen.preRender(screenParams);
                        that.options.MYREFERENCES.subviews.screen.render(null, screenParams);
                    } else {
                        that.$el.find("[data-screenid='" + that.options.MYREFERENCES.subviews.screen.id + "']").addClass("active");
                        that.options.MYREFERENCES.subviews.screen.refresh(screenParams);
                    }

                    that._fixSidemenuPosition();
                }

                if (_.isString(screenModule)) {
                    require([screenModule], function (sm) {
                        continue_fn(sm); 
                    }); 
                } else {
                    continue_fn(screenModule); 
                }

            } catch (Error) { console.error(Error); }
        }, 50)

        , showAskBeforeCloseModal: function (viewAskOpt, viewParams) {
            var that = this,
                askOpt = {
                    events: {},
                    type: 'CONTINUE-CANCEL',
                    title: 'Closing screen',
                    message: 'Current screen will be closed. Do you want to continue?',
                },
                askModalOpt = {
                    id: 'ask-before-close',
                    allowCancel: true,
                    focusOk: true,
                },
                askModal;

            _.extend(askOpt, viewAskOpt);

            askModalOpt.buttons_type = askOpt.type;
            askModalOpt.message = askOpt.message;
            askModalOpt.title = askOpt.title;

            askModal = new Modal.Views.Main(askModalOpt);

            askModal.bind("cancel", function () {
                if (askOpt.events.cancel)
                    askOpt.events.cancel();

                app.router.navigate(app.router.previousRoute, { silent: true });
                app.router.currentRoute = app.router.previousRoute;
            });
            askModal.bind("continue", function () {
                if (askOpt.events.continue)
                    askOpt.events.continue();

                askModal.hide();

                that.refresh(viewParams, { preventAskBeforeClose: true }); 
            });

            askModal.show();
        }

        , _fixSidemenuPosition: function(){
            var sidemenu = $(".configuration-sidemenu");

            //if ($(".fixed-subnavbar").is(":visible")) {
            if (app.models.subnavbar.get("subnavbar")) {
                sidemenu.css("margin-top", "-80px");
            } else {
                sidemenu.css("margin-top", "-11px");
            }

            sidemenu.height($(window).height() - sidemenu.offset().top);
        }
        /*
        , updateDisplayDataSourcesItemErrorIcon: function () {
            var hasConflicts = app.models.datablocksConflicts.get('hasConflicts'),
                icon = $("#menu_datasources_error_icon");

            if (hasConflicts) {
                icon.css("display", "block")
                    .addClass("animated dur-3s bounceInLeft")
                    .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
                        icon
                            .removeClass("bounceInLeft")
                            .addClass("infinite bounce2");
                    });
            }
            else if (icon.hasClass("animated")) {
                icon.one('webkitAnimationIteration mozAnimationIteration MSAnimationIteration oanimationiteration animationiteration', function () {
                    icon.removeClass("infinite bounce2")
                        .addClass("bounceOutLeft")
                        .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
                            icon.css("display", "none")
                                .removeClass("animated dur-3s bounceOutLeft");
                        });
                });
            }
        }
        */
        , _gridRefreshComplete: function () {
        }

        , window_resize: function (e) {
            try {
                this._fixSidemenuPosition();
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        }

        , 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

            $(window).on('resize', _(this.window_resize).debounce(500).bind(this));

           // this.listenTo(app.models.datablocksConflicts, "change:hasConflicts", this.updateDisplayDataSourcesItemErrorIcon);
        }

        , bindViewScopedEvents: function () {
            this.listenTo(app.models.subnavbar, "change:subnavbar", this._fixSidemenuPosition); 
        }

        , unbindViewScopedEvents: function () {
            this.stopListening(app.models.subnavbar, "change:subnavbar", this._fixSidemenuPosition); 
        }

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

            this.postHideClose();
            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.bindViewScopedEvents(); 
            this.$el.show();
        }

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

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

            this.unbindViewScopedEvents();
            this.postHideClose(); 
            this.hideSubviews();
            this.$el.hide();
            this.unbind();
            this.stopListening();
        }

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

        , postHideClose: function () {
            app.models.subnavbar.set({span: 12, offset: 0});
        }

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

        , reRender: function (viewParams) {
            this.refresh(viewParams);
        }

    });

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

});
