define(['jquery', 'underscore', 'backbone',
        'models/PackageModel',
        'views/DownloadButtonView',
        'text!templates/downloadContents.html'],
	function($, _, Backbone, Package, DownloadButtonView, Template) {
	'use strict';
	var PackageTable = Backbone.View.extend({
		template: _.template(Template),
		type: "PackageTable",
		tagName : "div",
		className : "download-contents",
		events: {
			"click .expand-control"   : "expand",
			"click .collapse-control" : "collapse"
		},
		initialize: function(options){
			if((options === undefined) || (!options)) var options = {};
			this.packageId  = options.packageId	 || null;
			this.memberId	= options.memberId	 || null;
			this.attributes = options.attributes || null;
			this.className += options.className  || "";
			this.currentlyViewing = options.currentlyViewing || null;
			this.numVisible = options.numVisible || 4;
			this.parentView = options.parentView || null;
			this.title = options.title || "";
			this.nested = (typeof options.nested === "undefined")? false : options.nested;
			//Set up the Package model
			if((typeof options.model === "undefined") || !options.model){
				this.model = new Package();
				this.model.set("memberId", this.memberId);
				this.model.set("packageId", this.packageId);
			}
			if(!(typeof options.metricsModel == "undefined")){
                this.metricsModel = options.metricsModel;
            }
			//Get the members
			if(this.packageId)    this.model.getMembers();
			else if(this.memberId) this.model.getMembersByMemberID(this.memberId);
			 this.onMetadataView = (this.parentView && this.parentView.type == "Metadata");
			 this.hasEntityDetails = (this.onMetadataView && (this.model.get("members") && this.model.get("members").length < 150))? this.parentView.hasEntityDetails() : false;
			this.listenTo(this.model, "changeAll", this.render);
		},
		/*
		 * Creates a table of package/download contents that this metadata doc is a part of
		 */
		render: function(){
			var view = this,
				members = this.model.get("members");
			//If the model isn't complete, we may be still waiting on a response from the index so don't render anything yet
			if(!this.model.complete) return false;
			//Start the HTML for the rows
			var	tbody = $(document.createElement("tbody"));
			//Filter out the packages from the member list
			members = _.filter(members, function(m){ return(m.type != "Package") });
			//Filter the members in order of preferred appearance
			members = this.sort(members);
			this.sortedMembers = members;
			var metadata = this.model.getMetadata();
			//Count the number of rows in this table
			var numRows = members.length;
			//Cut down the members list to only those that will be visible
			members = members.slice(0, this.numVisible);
			this.rowsComplete = false;
			//Create the HTML for each row
			_.each(members, function(solrResult){
				//Append the row element
				$(tbody).append(view.getMemberRow(solrResult));
			});
			var bodyRows = $(tbody).find("tr");
			this.numHidden = numRows - this.numVisible;
			//Draw the footer which will have an expandable/collapsable control
			if(this.numHidden > 0){
				var tfoot        = $(document.createElement("tfoot")),
					tfootRow     = $(document.createElement("tr")),
					tfootCell    = $(document.createElement("th")).attr("colspan", "100%"),
					item         = (this.numHidden == 1)? "item" : "items",
					expandLink   = $(document.createElement("a")).addClass("expand-control control").text("Show " + this.numHidden + " more " + item + " in this data set"),
					expandIcon   = $(document.createElement("i")).addClass("icon icon-caret-right icon-on-left"),
					collapseLink = $(document.createElement("a")).addClass("collapse-control control").text("Show less").css("display", "none"),
					collapseIcon = $(document.createElement("i")).addClass("icon icon-caret-up icon-on-left");
				$(tfoot).append(tfootRow);
				$(tfootRow).append(tfootCell);
				$(tfootCell).append(expandLink, collapseLink);
				$(expandLink).prepend(expandIcon);
				$(collapseLink).prepend(collapseIcon);
			}
			if(bodyRows.length == 0){
				tbody.html("
| This is an empty dataset. | 
");
			}
			if(!this.title && metadata){
				this.title = 'Files in this dataset';
				if(this.model.get("id"))
					this.title += ' Package: ' + this.model.get("id") + '';
				this.title += '';
			}
			else if(!this.title && !metadata){
				this.title = "Files in this dataset";
			}
			this.$el.html(this.template({
					   title   : this.title || "Files in this dataset",
			          metadata : this.nested ? metadata : null,
			           colspan : bodyRows.first().find("td").length,
					 packageId : this.model.get("id"),
					    nested : this.nested
			}));
			//Insert the Download All button
			if(this.model.getURL() && this.model.get("id")){
				var downloadBtn = new DownloadButtonView({ model: this.model });
				downloadBtn.render();
				this.$(".download-container").append(downloadBtn.el);
			}
			//Add the table body and footer
			this.$("thead").after(tbody);
			if(typeof tfoot !== "undefined") this.$(tbody).after(tfoot);
			return this;
		},
		sort: function(models){
			//Default to the package model members as the models to sort
			if(!models){
				var models = this.model.get("members");
				//If this model doesn't have members, return an empty array or a falsey value
				if(!models) return models;
			}
			// One == already sorted!
			if(models.length == 1) return models;
			//If there are too many models to sort (takes too much time) then just get the metadata to display first
			else if(models.length > 150){
				var view = this;
				//Find the metadata doc we are currently viewing
				var currentMetadata = _.find(models, function(m){ return (m.get("id") == view.currentlyViewing) });
				//Add it to the front
				if(currentMetadata){
					models = _.without(models, currentMetadata);
					models.unshift(currentMetadata);
				}
				//Return the newly sorted array
				return models;
			}
			var view = this,
				metadataView = this.onMetadataView? this.parentView : null;
			//** If this is not a nested package AND the parent view is the metadata view, then sort by order of appearance in the metadata **/
			if(!this.nested && (metadataView && !_.findWhere(metadataView.subviews, {type: "MetadataIndex"}))){
				if(metadataView.hasEntityDetails()){
					//If we are currently viewing a metadata document, find it
					if(this.currentlyViewing)
						var currentMetadata = _.find(models, function(m){ return (m.get("id") == view.currentlyViewing) });
					//For each model, find its position on the Metadata View page
					var numNotFound = 0;
					_.each(models, function(model){
						if(currentMetadata == model) return;
						var container = view.parentView.findEntityDetailsContainer(model);
						if(container) model.offsetTop = $(container)[0].offsetTop;
						else{
							model.offsetTop = window.outerHeight;
							numNotFound++;
						}
					});
					//Continue only if we found the entity details section for at least one model, if not, sort by the default method later
					if(numNotFound < models.length-1){ //Minus 1 since we don't count the metadata
						//Sort the models by this position
						models = _.sortBy(models, "offsetTop");
						//Move the metadata model that we are currently viewing in the Metadata view to the top
						if(currentMetadata){
							models = _.without(models, currentMetadata);
							models.unshift(currentMetadata);
						}
						//Flatten the array in case we have nesting
						models = _.flatten(models);
						//Return the sorted array
						return models;
					}
				}
			}
			//** For tables with no accompanying metadata (nested or not on the Metadata View), default to sorting by group then alpha by name**/
			//Split the members of this package into groups based on their format type (metaata, data, image, code, etc)
			var groupedModels = _.groupBy(models, function(m){
					if(!m.get("type") || (typeof m.get("type") == "undefined"))
						return "data";
					return m.get("type");
				}),
				sortedModels = [];
			var rowOrder = ["metadata", "image", "PDF", "program", "data", "annotation"];
			for(var i=0; i/view/" + encodeURIComponent(id))
								.addClass("preview")
								.attr("data-id", id)
								.text("More info");
				$(moreInfoCell).append(moreInfo);
			}
			$(tr).append(moreInfoCell);
			//Format id cell
			var fileTypeCell = $(document.createElement("td")).addClass("formatId wrap-contents");
			$(fileTypeCell).html(memberModel.getFormat());
			$(tr).append(fileTypeCell);
			//File size cell
			var sizeCell = $(document.createElement("td")).addClass("size");
			var size = memberModel.bytesToSize();
			$(sizeCell).text(size);
			$(tr).append(sizeCell);
      if( MetacatUI.appModel.get("displayDatasetMetrics") ){
  			// Retreiving the Package Metrics Counts from the Metrics Model
  			// Adding a Metric Cell for the corresponding DataONE object in the table
  			var readsCell = $(document.createElement("td"))
                          .addClass("metrics-count downloads")
  								        .attr("data-id", id);
        $(tr).append(readsCell);
        if( !memberModel.hideMetrics() ){
    			// If the model has already been fethced.
    			if (this.metricsModel.get("views") !== null) {
    				readsCell.append(this.getMemberRowMetrics(id, formatType));
    			}
    			else {
    				// Update the metrics later on
    				// If the fetch() is still in progress.
    				this.listenTo(this.metricsModel, "sync", function(){
    					var readsCell = this.$('.metrics-count.downloads[data-id="' + id + '"]');
    					readsCell.text(this.getMemberRowMetrics(id, formatType));
    				});
    			}
        }
      }
			//Download button cell
			var downloadBtnCell = $(document.createElement("td")).addClass("download-btn btn-container");
			var downloadButton = new DownloadButtonView({ model: memberModel });
			downloadButton.render();
			$(downloadBtnCell).append(downloadButton.el);
			$(tr).append(downloadBtnCell);
			if(collapsable)
				tr.addClass("collapse");
			if(hidden)
				tr.css("display", "none");
			return tr;
		},
		// Member row metrics for the package table
		// Retrieving information from the Metrics Model's result details
		getMemberRowMetrics: function(id, formatType) {
			if(typeof this.metricsModel !== "undefined"){
				var metricsResultDetails = this.metricsModel.get("resultDetails");
		        if( typeof metricsResultDetails !== "undefined" && metricsResultDetails ){
		          	var metricsPackageDetails = metricsResultDetails["metrics_package_counts"];
	  				var objectLevelMetrics = metricsPackageDetails[id];
	  				if(typeof objectLevelMetrics !== "undefined") {
	  					if(formatType == "METADATA") {
	  						var reads = objectLevelMetrics["viewCount"];
	  					}
	  					else {
	  						var reads = objectLevelMetrics["downloadCount"];
	  					}
	  				}
	  				else{
	  					var reads = 0;
	  				}
		        }
		        else{
		          	var reads = 0;
		        }
			}
			if((typeof reads !== "undefined") && reads){
				// giving labels
				if(formatType == "METADATA" && reads == 1)
					reads += " view";
				else if(formatType == "METADATA")
					reads += " views";
				else if(reads == 1)
					reads += " download";
				else
					reads += " downloads";
			}
			else {
				// returning an empty string if the metrics are 0
				reads = "";
			}
			return reads;
		},
		expand: function(e){
			//Don't do anything...
			e.preventDefault();
			var view = this;
			//If this is a nested dataset, we need to actually draw the remaining rows
			if(!this.rowsComplete){
				var tbody = this.$("tbody");
				//Create the HTML for each row
				var members = this.sortedMembers.slice(this.numVisible);
				_.each(members, function(solrResult){
					//Append the row element
					$(tbody).append(view.getMemberRow(solrResult, { collapsable: true }));
				});
				//Make the view as complete so we don't do this again
				this.rowsComplete = true;
			}
			this.$("tr.collapse").fadeIn();
			this.$(".expand-control").fadeOut(function(){
				view.$(".collapse-control").fadeIn("fast");
				view.$(".tooltip-this").tooltip();
			});
		},
		collapse: function(e){
			//Don't do anything...
			e.preventDefault();
			var view = this;
			this.$("tr.collapse").fadeOut();
			this.$(".collapse-control").fadeOut(function(){
				view.$(".expand-control").fadeIn();
			});
		},
    checkForPrivateMembers: function(){
      try{
        var packageModel      = this.model,
            packageCollection = this.dataPackageCollection;
        if( !packageModel || !packageCollection ){
          return;
        }
        //Get the number of package members found in Solr and parsed from the RDF XML
        var numMembersFromSolr = packageModel.get("members").length,
            numMembersFromRDF  = packageCollection.length;
        //If there are more package members in the RDF XML tthan found in SOlr, we
        // can assume that those objects are private.
        if( numMembersFromRDF > numMembersFromSolr ){
          var downloadButtons = this.$(".btn.download");
          for( var i=0; i -1 ||
                downloadURL.indexOf( encodeURIComponent(packageModel.get("id"))) > -1 ){
              //Disable this download button
              $(btn).attr("disabled", "disabled")
                    .addClass("disabled")
                    .attr("href", "")
                    .tooltip({
                      trigger: "hover",
                      placement: "top",
                      delay: 500,
                      title: "This dataset may contain private data, so each data file should be downloaded individually."
                    });
              i = downloadButtons.length;
            }
          }
        }
      }
      catch(e){
        console.error(e);
      }
    }
		/*showDownloadProgress: function(e){
			e.preventDefault();
			var button = $(e.target);
			button.addClass("in-progress");
			button.html("Downloading... ");
			return true;
		}*/
	});
	return PackageTable;
});