/// <reference path="http://localhost:50976/IndustrialDashboard/Scripts/IndustrialDashboard-debug.js" />
define([
  // Application.
  "app",

  "Mousetrap", 

  //templates-loader
  "js/templates-loader"

],

function (app, Mousetrap, T) {

    var Menu = { Model: {}, Views: {} }

    Menu.Model = Backbone.Model.extend({
        defaults: {
            ID: null
            , Name: null
            , Parent: null
            , URL: null
            , NavigableURL: null
            , Visible: null
            , Enabled: null
            , children: []
            , Route: null
            , Parameters: null

            , OpenSideSubmenu: false
        },
        initialize: function () {
            this.set("children", new Menu.ChildItemsCollection(this.get("children")));
        }
        , toJSON: function () {
            if (this._isSerializing) {
                return this.id || this.cid;
            }
            this._isSerializing = true;
            var json = _.clone(this.attributes);
            _.each(json, function (value, name) {
                value && _.isFunction(value.toJSON) && (json[name] = value.toJSON());
            });
            this._isSerializing = false;
            return json;
        }
    });

    Menu.ItemsCollection = Backbone.Collection.extend({
        model: Menu.Model
        , fetch: function () {
            var that = this;

            Core.Json.CallProcedure("FrontEnd.GetMenuData", null, {
                onSuccess: function (data) {
                    var parameters = null;
                    var models = [];
                    if (Core.Object.Eval(data, "Table")) {
                        //menuLinkParameters
                        parameters = data.Table;
                        delete data.Table;
                    }

                    for (var table in data) {
                        var level = data[table];
                        for (var inx = 0; inx < level.length; inx++) {
                            var item = level[inx];

                            if (parameters) {
                                var notUsed = [];
                                var p = null;
                                while ((p = parameters.pop()) != null) {
                                    if (p.MenuLinkID == item.Id) {
                                        if (!item.Parameters) item.Parameters = {};
                                        item.Parameters[p.Name] = p.Value;
                                    } else {
                                        var h = p;
                                        notUsed.push(h);
                                    }
                                }
                                parameters = notUsed;
                            }

                            item.HREF = app.router.resolveURL(item.Route, (item.Parameters) ? item.Parameters : {});
                            item.navigable = app.router.resolveURL(item.Route, (item.Parameters) ? item.Parameters : {}, false);

                            if (item.Parent != null) {
                                var pModel = null; 
                                //for (var i = 0; i < models.length; i++) {
                                //    if (models[i].get("ID") == item.Parent) { pModel = models[i]; break; }
                                //}
                                var pModel = that.findModel(models, item.Parent); 

                                pModel.get("children").push(new Menu.Model({
                                    ID: item.Id
                                    , Name: item.Name
                                    , Parent: item.Parent
                                    , URL: item.HREF
                                    , NavigableURL: item.navigable
                                    , Visible: item.Visible
                                    , Enabled: item.Enabled
                                    , children: []
                                    , Route: item.Route
                                    , Parameters: (item.Parameters) ? item.Parameters : {}

                                    , OpenSideSubmenu: item.OpenSideSubmenu
                                }));

                            } else {
                                models.push(new Menu.Model({
                                    ID: item.Id
                                    , Name: item.Name
                                    , Parent: item.Parent
                                    , URL: item.HREF
                                    , NavigableURL: item.navigable
                                    , Visible: item.Visible
                                    , Enabled: item.Enabled
                                    , children: []
                                    , Route: item.Route
                                    , Parameters: (item.Parameters) ? item.Parameters : {}

                                    , OpenSideSubmenu: item.OpenSideSubmenu
                                })); 
                            }
                        }
                    }

                    //change method is fired.
                    //that.set(that.parse(jsonObj), {});
                    that.reset(models); 
                    return that;
                },
                Async: false
            }, app.ConnectionStrings.app);

        }
        , findModel: function(model, id){
            for (var i = 0; i < model.length; i++) {
                var md = (model.at) ? model.at(i) : model[i]; 
                if (md.get("ID") == id) {
                    return md;
                } else {
                    var children = md.get("children"); 
                    if (children.length > 0) {
                        var inChildren = this.findModel(children, id);
                        if (inChildren != false)
                            return inChildren;
                    }
                }
            }
            return false; 
        }   
        , initialize: function (models, options) {
            this._meta = {}; 

            this.meta("userModel", options.userModel); 
            this.listenTo(this.meta("userModel"), "change", this.fetch);
            this.listenTo(app.models.dateControl, "change:date", this.updateHREFs);
        }
        , meta: function (prop, value) {
            if (value === undefined) {
                return this._meta[prop]
            } else {
                this._meta[prop] = value;
            }
        }
        , updateHREFs: function (model) {
            try {

                var jsonObj;
                //Core.Object.Extend(this.attributes, jsonObj);

                var items = this; 
                for (var i = 0; i < items.length; i++) {
                    var item = items.at(i); 
                    for (var c in item.get("children")) {
                        var child = item.get("children")[c];
                        params = child.get("Parameters");
                        _.extend(params, model.changed); 

                        child.set("URL", app.router.resolveURL(child.get("Route"), child.get("Parameters")));
                        child.set("NavigableURL", app.router.resolveURL(child.get("Route"), child.get("Parameters"), false));
                    }

                    _.extend(item.get("Parameters"), model.changed);

                    item.set("URL", app.router.resolveURL(item.get("Route"), item.get("Parameters")));
                    item.set("NavigableURL", app.router.resolveURL(item.get("Route"), item.get("Parameters"), false));

                }

                this.reset(items.models);

            } catch (Error) { }
        }
    }); 

    Menu.ChildItemsCollection = Backbone.Collection.extend({
        model: Menu.Model
    }); 

    Menu.Views.Main = Backbone.View.extend({
        template: "menu/menu"
        , id: "menu"
        //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.
        //refreshing only the data, maybe?
        , isCacheable: false
        , el: null
        , initialize: function () {
            _.bindAll(this); 

            this.bindEvents(); 
            
        },
        // global view variable (seen in this scopy, public to the view, and SHARED BETWEEN OTHER INSTANCES OF THE SAME VIEW)
        // containing all the variables for this view

        //properties that you wanna scope as private variables for each instance of a view should not be placed here
        //the only way i found to maintain the variables between instances of the same view, is either using models,
        // (each view will have its own model so data is not shared between them), or in case you don't want to use a model
        // you can use the Backbone.View.options object, and doing something like
        // this.options.attributes = {}
        // and storing every single variable inside attributes.
        events: {
            "click #drop1": "autofocus_searchInput"
            , "click .stop-propag": "_stopPropagation"
        },
        render: function () {
            var that = this;

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

                //start: before the view is visible, but the template was already loaded (not instanced nor appended)
                that.$el.empty(); 
                //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")

                var items = that.collection;

                var typeaheadSearchInput = that.$el.find("#nav-dropdown-search-input").get(0);
                var sources = [];
                var sourcesDic = {};

                var containerDesktop = that.$el.find("#items-container-desktop"); 
                var containerMobile = that.$el.find("#items-container-mobile"); 

                var containers = {
                    desktop: containerDesktop
                    , mobile: containerMobile
                };
                var container = null; 

                T.render.call(that, that.template, function (tmpOptions) {
                    var html = tmpOptions({ items: items.toJSON() });
                    containers["desktop"].append(html); 
                }, null, "menu_options_template"); 

                //for (var x in containers) {
                //    container = containers[x]; 
                //    for (var inx = 0; inx < items.length; inx++) {
                //        var item = items.at(inx);
                //        var li = document.createElement('li');
                //        var a = null;
                //        li.className = "nav-header";
                //        li.innerHTML = item.get("Name");

                //        container.appendChild(li);
                //        if (item.get("children")) {
                //            for (var inxChild in item.get("children")) {
                //                var child = item.get("children")[inxChild];
                //                li = document.createElement('li');
                //                a = document.createElement('a');
                //                a.innerHTML = child.get("Name");
                //                if (child.get("URL")) a.href = child.get("URL");
                //                li.appendChild(a);
                //                container.appendChild(li);

                //                //typeahead
                //                if (Core.Array.IndexOf(sources, child.get("Name")) == -1){
                //                    sources.push(child.get("Name"));
                //                    sourcesDic[child.get("Name")] = { URL: child.get("NavigableURL") };
                //                }
                //            }
                //        }
                //    }
                //}

                function _fillTypeaheadArray(items, arr, dic){
                    for (var ix = 0; ix < items.length; ix++) {
                        var md = (items.at) ? items.at(ix) : items[ix];
                        var nurl = md.get("NavigableURL"); 
                        if (Core.String.ValidateEmpty(nurl)){
                            if (Core.Array.IndexOf(arr, md.get("Name")) == -1) {
                                arr.push(md.get("Name"));
                                dic[md.get("Name")] = { URL: md.get("NavigableURL") };
                            }
                        }
                        var children = md.get("children");
                        if (children && children.length > 0) {
                            _fillTypeaheadArray(children, arr, dic); 
                        }
                    }   
                }

                _fillTypeaheadArray(items, sources, sourcesDic); 

                $(typeaheadSearchInput).typeahead({
                    source: sources,
                    items: 3,
                    updater: function (item) {
                        if (sourcesDic[item]) {
                            app.router.navigate(sourcesDic[item].URL, true);
                        }
                    }
                });
                ////:end

            }, null, "main_template");
        }

        , bindEvents: function () {

            /**************************/
            /*MOUSETRAP KEY SHORTCUTS*/
            Mousetrap.bind('ctrl+m', function (e) {
                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    // internet explorer
                    e.returnValue = false;
                }

                $("#drop1").dropdown('toggle');
                $("#drop1").focus();
                return false;
            });
            /**************************/
            /*MOUSETRAP KEY SHORTCUTS*/

            this.listenTo(this.collection, "reset", this.render);
        }

        , _stopPropagation: function (e) {
            e.stopPropagation();
            $(e.currentTarget).blur(); 
        }

        , unbindEvents: function () {
            Mousetrap.unbind("ctrl+m"); 
        }

        , close: function () {
            this.remove();
            this.unbindEvents(); 
            this.unbind();
        }
        , show: function () {
            this.bindEvents(); 
            this.$el.show();
        }
        , hide: function () {
            this.$el.hide();
            this.unbindEvents(); 
            this.unbind();
            this.stopListening();
        },



        //extra methods
        autofocus_searchInput: function () {
            $("#nav-dropdown-search-input").val("");
            setTimeout(function () {
                if ($('#nav-dropdown-search-input').css("display") != "none")
                    $("#nav-dropdown-search-input").focus();
            }, 300);
        }
    });

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

});
