/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
*/
/**
 * This should render the main content in the Application Explorer page.
 * Components on this page should be rendered as sub-views.
 * @type {*}
 */
define([
    "underscore", "jquery", "backbone", "view/viewutils", 
    "./application-add-wizard", "model/application", "model/entity-summary", "model/app-tree", "./application-tree",  "./entity-details",
    "text!tpl/apps/details.html", "text!tpl/apps/entity-not-found.html", "text!tpl/apps/page.html"
], function (_, $, Backbone, ViewUtils,
        AppAddWizard, Application, EntitySummary, AppTree, ApplicationTreeView, EntityDetailsView,
        EntityDetailsEmptyHtml, EntityNotFoundHtml, PageHtml) {

    var ApplicationExplorerView = Backbone.View.extend({
        tagName:"div",
        className:"container container-fluid",
        id:'application-explorer',
        template:_.template(PageHtml),
        notFoundTemplate: _.template(EntityNotFoundHtml),
        events:{
            'click .application-tree-refresh': 'refreshApplicationsInPlace',
            'click #add-new-application':'createApplication',
            'click .delete':'deleteApplication'
        },
        initialize: function () {
            this.$el.html(this.template({}))
            $(".nav1").removeClass("active");
            $(".nav1_apps").addClass("active");

            this.treeView = new ApplicationTreeView({
                collection:this.collection,
                appRouter:this.options.appRouter
            })
            if (this.options.initialTrail) this.show(this.options.initialTrail, true);
            this.treeView.on('entitySelected', function(e) {
               this.displayEntityId(e.id, e.get('applicationId'), false);
            }, this);
            // don't draw these -- wait for the "show" command
            this.$('div#app-tree').html(this.treeView.renderFull().el);
            this.$('div#details').html(EntityDetailsEmptyHtml);

            ViewUtils.fetchRepeatedlyWithDelay(this, this.collection)
        },
        refreshApplicationsInPlace: function() {
            // fetch without reset sets of change events, which now get handled correctly
            // (not a full visual recompute, which reset does - both in application-tree.js)
            this.collection.fetch();
        },
        beforeClose: function () {
            this.collection.off("reset", this.render);
            this.treeView.close();
            if (this.detailsView)
                this.detailsView.close();
        },
        show: function(entityId, isPre) {
            var tab = "";
            var tabDetails = "";
            if (entityId) {
                if (entityId[0]=='/') entityId = entityId.substring(1);
                var slash = entityId.indexOf('/');
                if (slash>0) {
                    tab = entityId.substring(slash+1)
                    entityId = entityId.substring(0, slash);
                }
            }
            if (tab) {
                var slash = tab.indexOf('/');
                if (slash>0) {
                    tabDetails = tab.substring(slash+1)
                    tab = tab.substring(0, slash);
                }
                this.preselectTab(tab, tabDetails);
            }
            if (!this.treeView.selectEntity(entityId)) {
                // needs a load, but only allowed if not pre-loading
                if (isPre) { /* don't allow loading if this is a "pre-show" */ }
                else { this.displayEntityId(entityId); }
            }
        },
        showDefaultSelection: function() {
            if (!this.treeView.selectedEntityId && !this.treeView.requestedEntityId) {
                var firstApp = _.first(this.collection.getApplications());
                if (firstApp) this.treeView.selectEntity(firstApp);
            }
        },
        createApplication:function () {
            var that = this;
            if (this._modal) {
                this._modal.close()
            }
            var wizard = new AppAddWizard({
                appRouter:that.options.appRouter,
                callback:function() { that.refreshApplicationsInPlace() }
            })
            this._modal = wizard
            this.$(".add-app #modal-container").html(wizard.render().el)
            this.$(".add-app #modal-container .modal")
                .on("hidden",function () {
                    wizard.close()
                }).modal('show')
        },
        deleteApplication:function (event) {
            // call Backbone destroy() which does HTTP DELETE on the model
            this.collection.get(event.currentTarget['id']).destroy({wait:true})
        },
        /**
         * Causes the tab with the given name to be selected automatically when
         * the view is next rendered.
         */
        preselectTab: function(tab, tabDetails) {
            this.currentTab = tab;
            this.currentTabDetails = tabDetails;
        },
        showDetails: function(app, entitySummary) {
            var that = this;
            ViewUtils.cancelFadeOnceLoaded($("div#details"));

            if (this.detailsView) {
                // if view open, take that tab, but clear the details if the id is different
                if (this.detailsView.model && this.detailsView.model.id && this.detailsView.model.id != entitySummary.id)
                    this.detailsView.options.preselectTabDetails = null;
                this.preselectTab(
                    //this.detailsView.$el.find(".tab-pane.active").attr("id")
                    this.detailsView.options.preselectTab,
                    this.detailsView.options.preselectTabDetails
                    );
                this.detailsView.close();
            }
            if (!this.currentTab) {
                // else if nothing preselect, use summary
                this.preselectTab("summary");
            }
            
            this.detailsView = new EntityDetailsView({
                model: entitySummary,
                application: app,
                appRouter: this.options.appRouter,
                preselectTab: this.currentTab,
                preselectTabDetails: this.currentTabDetails,
            });

            this.detailsView.on("entity.expunged", function() {
                that.preselectTab("summary");
                var id = that.selectedEntityId;
                var model = that.collection.get(id);
                if (model && model.get("parentId")) {
                    that.displayEntityId(model.get("parentId"));
                } else if (that.collection) {
                    that.displayEntityId(that.collection.first().id);
                } else if (id) {
                    that.displayEntityNotFound(id);
                } else {
                    that.displayEntityNotFound("?");
                }
                that.collection.fetch();
            });
            this.detailsView.render( $("div#details") );
            // force the routes to be updated, and clear activities detail possibly (the tab is already shown)
            // (this causes activities view to lose selected sub-tasks, but that's okay)
            this.detailsView.openTab(this.currentTab + (this.currentTabDetails ? '/'+this.currentTabDetails : ''));
        },
        displayEntityId: function (id, appName, afterLoad) {
            var that = this;
            var entityLoadFailed = function() {
                return that.displayEntityNotFound(id);
            };
            if (appName === undefined) {
                var $treebox = that.treeView.getTreebox(id);
                appName = $treebox.children(".entity_tree_node_wrapper").children(".entity_tree_node").data("app-id");
            }
            if (appName === undefined) {
                if (!afterLoad) {
                    // try a reload if given an ID we don't recognise
                    this.collection.includeEntities([id]);
                    this.collection.fetch({
                        success: function() { _.defer(function() { that.displayEntityId(id, appName, true); }); },
                        error: function() { _.defer(function() { that.displayEntityId(id, appName, true); }); }
                    });
                    ViewUtils.fadeToIndicateInitialLoad($("div#details"))
                    return;
                } else {
                    // no such app
                    entityLoadFailed();
                    return; 
                }
            }

            var app = new Application.Model();
            var entitySummary = new EntitySummary.Model;

            app.url = "/v1/applications/" + appName;
            entitySummary.url = "/v1/applications/" + appName + "/entities/" + id;
            if (id !== this.treeView.selectedEntityId)
                this.treeView.selectEntity(id);

            // in case the server response time is low, fade out while it refreshes
            // (since we can't show updated details until we've retrieved app + entity details)
            ViewUtils.fadeToIndicateInitialLoad($("div#details"));

            $.when(app.fetch(), entitySummary.fetch())
                .done(function() {
                    that.showDetails(app, entitySummary);
                })
                .fail(entityLoadFailed);
        },
        displayEntityNotFound: function(id) {
            $("div#details").html(this.notFoundTemplate({"id": id}));
            ViewUtils.cancelFadeOnceLoaded($("div#details"))
        },
    })

    return ApplicationExplorerView
})
