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

  "custom-screens/screen-builder/sb-environment",
],

function (app, T, Modal, SBEnvironment) {

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

    Viewer.Models.Main = Backbone.Model.extend({
        defaults: {
            frameSrc: "",
            backgroundColor: null, 
        }
    });

    //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.
    Viewer.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "viewer" + ((viewParams && viewParams.id) ? "-" + viewParams.id.toString() : "");
                
            var id = null;
            try{
                id = parseInt(app.router.currentRoute.replace("!/screens/", ""), 10)
            } catch (error) { console.log("Error while trying to parse screen id from url bar. Error:" + error.toString()); }
            
            return ("viewer-{{screenId}}").replace("{{screenId}}", id); 
        } catch (Error) { }
    }

    Viewer.Views.Main = Backbone.View.extend({
        template: "viewer"
        , id: "viewer"
        , title: "Viewer"
        //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 () { };

            var screenId = null;
            if (this.options.viewParams) {
                screenId = (this.options.viewParams.id) ? this.options.viewParams.id : null;
            }

            //try {
            //    screenId = parseInt(app.router.currentRoute.replace("!/screens/", ""), 10)
            //} catch (error) { console.log("Error while trying to parse screen id from url bar. Error:" + error.toString()); }

            this.options.listeners = {};
            this.options.environment = null;

            var model = new Viewer.Models.Main({
                id: screenId,
                frameSrc: app.foldersRoot + ("/built-screens/{{screenId}}/screen.html?{{versionTimestamp}}").replace("{{screenId}}", screenId.toString()).replace("{{versionTimestamp}}", new Date().getTime().toString()),
            });

            this.model = model;

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

        events: {
        },

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

            //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/viewer/";

            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(that.model.toJSON()));

                    //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
                    //appending view to the main container 

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

                    that.options.environment = new SBEnvironment.Class({
                        frame: that.$el.find('.viewer-frame'),
                        screenId: that.model.get("id"),
                        mode: SBEnvironment.Enums.Modes.Viewer,
                    });

                    that.fitToHeight(); 
                    that.bindViewScopedEvents();
                }, true, customPath);
            }, customPath);
        }
        , frameLoaded: function () {
            var that = this;
            that.options.environment.injectEnvironmentToFrame();
            that.$el.append("<style> body { background-color:" + that.options.environment.readConfig(that.$el.find('.viewer-frame').contents(), "backgroundColor") + " !important; }</style>");
        }
        , fitToHeight: function () {
            this.$el.find(".resize-height-to-fit").height($(window).height() - 80);
        }
        , 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;
            }
        }
        , refresh: function () {
            try {

            } catch (Error) { }
        }
        , 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
        }
        , bindViewScopedEvents: function () {
            var that = this;
            this.options.listeners['focus'] = _.bind(that.fitToHeight, that);
            window.addEventListener('focus', this.options.listeners['focus'], false); //Cope with window being resized whilst on another tab

            this.options.listeners['resize'] = _.debounce(_.bind(that.fitToHeight, that), 250);
            window.addEventListener('resize', this.options.listeners['resize'], false);

            this.options.listeners['readystatechange'] = _.bind(that.fitToHeight, that);
            window.addEventListener('readystatechange', this.options.listeners['readystatechange'], false);

            this.options.listeners['fullscreenchange'] = _.bind(that.fitToHeight, that);
            document.addEventListener('fullscreenchange', this.options.listeners['fullscreenchange'], false);

            this.$el.find(".viewer-frame").load(this.frameLoaded);
        }
        , unbindViewScopedEvents: function () {
            if (this.options.tagViewers) this.options.tagViewers.destroy();
            window.removeEventListener('focus', this.options.listeners['focus'], false);
            window.removeEventListener('resize', this.options.listeners['resize'], false);
            window.removeEventListener('readystatechange', this.options.listeners['readystatechange'], false);
            document.removeEventListener('fullscreenchange', this.options.listeners['fullscreenchange'], false);
            this.$el.find(".viewer-frame").off("load");
        }
        , close: function () {
            this.options.state = app.view_states.closed;
            this.unbindViewScopedEvents();

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

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

});