# Source: src/js/views/DataPackageView.js

    ﻿/* global define */
    define([
        'jquery',
        'underscore',
        'backbone',
        'localforage',
        'collections/DataPackage',
        'models/DataONEObject',
        'models/metadata/ScienceMetadata',
        'models/metadata/eml211/EML211', 'views/DataItemView',
        'text!templates/dataPackage.html',
        'text!templates/dataPackageStart.html'],
        function($, _, Backbone, LocalForage, DataPackage, DataONEObject, ScienceMetadata, EML211, DataItemView,
        		DataPackageTemplate, DataPackageStartTemplate) {
            'use strict';

            /**
             * @class DataPackageView
             * @classdesc The main view of a Data Package in the editor.  The view is
             *  a file/folder browser
             * @classcategory Views
             * @screenshot views/DataPackageView.png
             */
            var DataPackageView = Backbone.View.extend(
              /** @lends DataPackageView.prototype */{

                tagName: "table",

                className: "table table-striped table-hover",

                id: "data-package-table",

                events: {
                    "click .toggle-rows" 		   : "toggleRows", // Show/hide rows associated with event's metadata row
                    "click .message-row .addFiles" : "handleAddFiles"
                },

                subviews: {},

                /**
                * A reference to the parent EditorView that contains this view
                * @type EditorView
                * @since 2.15.0
                */
                parentEditorView: null,

                template: _.template(DataPackageTemplate),
                startMessageTemplate: _.template(DataPackageStartTemplate),

                // Models waiting for their parent folder to be rendered, hashed by parent id:
                // {'parentid': [model1, model2, ...]}
                delayedModels: {},

                /* Flag indicating the open or closed state of the package rows */
                isOpen: true,

                initialize: function(options) {
                	//Get the options sent to this view
                	if(typeof options == "object"){
                		//The edit option will allow the user to edit the table
                		this.edit = options.edit || false;

                		//The data package to render
                		this.dataPackage = options.dataPackage || new DataPackage();

                    this.parentEditorView = options.parentEditorView || null;
                	}
                	//Create a new DataPackage collection if one wasn't sent
                	else if(!this.dataPackage){
                		this.dataPackage = new DataPackage();
                	}

                    return this;

                },

                /**
                 *  Render the DataPackage HTML
                 */
                render: function() {
                    this.$el.append(this.template({
                    	loading: MetacatUI.appView.loadingTemplate({msg: "Loading files table... "}),
                    	id: this.dataPackage.get("id")
                    }));

                    // Listen for  add events because models are being merged
                    this.listenTo(this.dataPackage, 'add', this.addOne);
                    this.listenTo(this.dataPackage, "fileAdded", this.addOne);

                    // Render the current set of models in the DataPackage
                    this.addAll();

                    //If this is a new data package, then display a message and button
                    if((this.dataPackage.length == 1 && this.dataPackage.models[0].isNew()) || !this.dataPackage.length){

                    	var messageRow = this.startMessageTemplate();

                    	this.$("tbody").append(messageRow);

                    	this.listenTo(this.dataPackage, "add", function(){
                    		this.$(".message-row").remove();
                    	});
                    }

                    //Render the Share control(s)
                    this.renderShareControl();

                    return this;
                },

                /**
                 * Add a single DataItemView row to the DataPackageView
                 */
                addOne: function(item) {
                	if(!item) return false;

                    //Don't add duplicate rows
                    if(this.$(".data-package-item[data-id='" + item.id + "']").length)
                    	return;

                    var dataItemView, scimetaParent, parentRow, delayed_models;

                    if ( _.contains(Object.keys(this.subviews), item.id) ) {
                        return false; // Don't double render

                    }

                    dataItemView = new DataItemView({
                      model: item,
                      parentEditorView: this.parentEditorView
                    });
                    this.subviews[item.id] = dataItemView; // keep track of all views

                    //Get the science metadata that documents this item
                    scimetaParent = item.get("isDocumentedBy");

                    //If this item is not documented by a science metadata object,
                    // and there is only one science metadata doc in the package, then assume it is
                    // documented by that science metadata doc
                    if( typeof scimetaParent == "undefined" || !scimetaParent ){

                    	//Get the science metadata models
                    	var metadataIds = this.dataPackage.sciMetaPids;

                    	//If there is only one science metadata model in the package, then use it
                    	if( metadataIds.length == 1 )
                    		scimetaParent = metadataIds[0];
                    }
                    //Otherwise, get the first science metadata doc that documents this object
                    else{
                        scimetaParent = scimetaParent[0];
                    }

                    if((scimetaParent == item.get("id")) || (!scimetaParent && item.get("type") == "Metadata")) {
                    	// This is a metadata folder row, append it to the table
                        this.$el.append(dataItemView.render().el);

                        // Render any delayed models if this is the parent
                        if ( _.contains(Object.keys(this.delayedModels), dataItemView.id) ) {

                            delayed_models = this.delayedModels[dataItemView.id];
                            _.each(delayed_models, this.addOne, this);

                        }
                    }
                    else{
                        // Find the parent row by it's id, stored in a custom attribute
                    	if(scimetaParent)
                    		parentRow = this.$("[data-id='" + scimetaParent + "']");

                        if ( typeof parentRow !== "undefined" && parentRow.length ) {
                            // This is a data row, insert below it's metadata parent folder
                            parentRow.after(dataItemView.render().el);

                            // Remove it from the delayedModels list if necessary
                            if ( _.contains(Object.keys(this.delayedModels), scimetaParent) ) {
                                delayed_models = this.delayedModels[scimetaParent];
                                var index = _.indexOf(delayed_models, item);
                                delayed_models = delayed_models.splice(index, 1);

                                // Put the shortened array back if delayed models remains
                                if ( delayed_models.length > 0 ) {
                                    this.delayedModels[scimetaParent] = delayed_models;

                                } else {
                                    this.delayedModels[scimetaParent] = undefined;

                                }
                            }

                            this.trigger("addOne");

                        } else {
                            console.warn("Couldn't render " + item.id + ". Delayed until parent is rendered.");
                            // Postpone the data row until the parent is rendered
                            delayed_models = this.delayedModels[scimetaParent];

                            // Delay the model rendering if it isn't already delayed
                            if ( typeof delayed_models !== "undefined" ) {

                                if ( ! _.contains(delayed_models, item) ) {
                                    delayed_models.push(item);
                                    this.delayedModels[scimetaParent] = delayed_models;

                                }

                            } else {
                                delayed_models = [];
                                delayed_models.push(item);
                                this.delayedModels[scimetaParent] = delayed_models;
                            }
                        }

                    }

                },

                /**
                 * Add all rows to the DataPackageView
                 */
                addAll: function() {
                    this.$el.find('#data-package-table-body').html(''); // clear the table first
                    this.dataPackage.sort();
                    this.dataPackage.each(this.addOne, this);

                },

                /**
                    Remove the subview represented by the given model item.

                    @param item The model representing the sub view to be removed
                */
                removeOne: function(item) {
                    if (_.contains(Object.keys(this.subviews), item.id)) {
                        // Remove the view and the its reference in the subviews list
                        this.subviews[item.id].remove();
                        delete this.subviews[item.id];

                    }
                },

                handleAddFiles: function(e){
                	//Pass this on to the DataItemView for the root data package
                	this.$(".data-package-item.folder").first().data("view").handleAddFiles(e);
                },

                /**
                * Renders a control that opens the AccessPolicyView for editing permissions on this package
                * @since 2.15.0
                */
                renderShareControl: function(){

                  if( this.parentEditorView && !this.parentEditorView.isAccessPolicyEditEnabled() ){
                    this.$("#data-package-table-share").remove();
                  }

                },

                /**
                 * Close subviews as needed
                 */
                onClose: function() {
                    // Close each subview
                    _.each(Object.keys(this.subviews), function(id) {
        				var subview = this.subviews[id];
                        subview.onClose();

                    }, this);

                    //Reset the subviews from the view completely (by removing it from the prototype)
                    this.__proto__.subviews = {};
                },

                /**
                 Show or hide the data rows associated with the event row science metadata
                 */
                toggleRows: function(event) {

                    if ( this.isOpen ) {

                        // Get the DataItemView associated with each id
                        _.each(Object.keys(this.subviews), function(id) {

                            var subview = this.subviews[id];

                            if ( subview.model.get("type") === "Data" && subview.remove ) {
                                // Remove the view from the DOM
                                subview.remove();
                                // And from the subviews list
                                delete this.subviews[id];

                            }

                        }, this);

                        // And then close the folder
                        this.$el.find(".open")
                            .removeClass("open")
                            .addClass("closed")
                            .removeClass("icon-chevron-down")
                            .addClass("icon-chevron-right");

                        this.$el.find(".icon-folder-open")
                            .removeClass("icon-folder-open")
                            .addClass("icon-folder-close");

                        this.isOpen = false;

                    } else {

                        // Add sub rows to the view
                        var dataModels =  this.dataPackage.where({type: "Data"});
                        _.each(dataModels, function(model) {
                                this.addOne(model);
                        }, this);

                        // And then open the folder
                        this.$el.find(".closed")
                            .removeClass("closed")
                            .addClass("open")
                            .removeClass("icon-folder-close")
                            .addClass("icon-chevron-down");

                        this.$el.find(".icon-folder-close")
                            .removeClass("icon-folder-close")
                            .addClass("icon-folder-open");

                        this.isOpen = true;

                    }

                    event.stopPropagation();
                    event.preventDefault();
                },

            });
            return DataPackageView;
    });