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

    /*global define */
    define(['jquery', 'underscore', 'backbone', 'collections/UserGroup', 'views/GroupListView', 'text!templates/userGroup.html', 'text!templates/alert.html'],
    	function($, _, Backbone, UserGroup, GroupListView, Template, AlertTemplate) {
    		'use strict';

    		/**
    		 * @class UserGroupView
    		 * @classdesc A subview that displays group management. View controls creation of groups and addition
    		 * of members to groups
    		 * @classcategory Views
    		 * @screenshot views/UserGroupView.png
    		 */
    		var UserGroupView = Backbone.View.extend(
    			/** @lends UserGroupView.prototype */ {

    			tagName: "div",
    			className: "span8 subsection",
    			attributes: {'data-section': 'groups'},
    			type: "UserGroupView",
    			events: {
    				"blur #add-group-name"    : "checkGroupName",
    				"click #add-group-submit" : "createGroup"
    			},

    			template: _.template(Template),
    			alertTemplate: _.template(AlertTemplate),

    			initialize: function(options){
    				if((typeof options == "undefined"))
    					var options = {};
    				this.model = options.model;
    				this.subviews = new Array();
    			},

    			render: function(){
    				this.$el.html(this.template());
    				this.insertCreateGroupForm();
    				this.listenTo(this.model, "change:isMemberOf", this.getGroups);
    				this.getGroups();
    				this.delegateEvents();
    				return this;
    			},

    				/**
    				 * Creates a view of a list of groups that the User is a member of
    				 *
    				 * @param {UserGroup} userGroup A user group model
    				 * @param {Object} viewOptions an object of options for the view
    				 */
    				createGroupList: function(userGroup, viewOptions) {
    				//Only create a list for new groups that aren't yet on the page
    				var existingGroupLists = _.where(this.subviews, {type: "GroupListView"});
    				if(existingGroupLists)
    					var groupIds = _.pluck(existingGroupLists, "groupId");
    				if(groupIds && (_.contains(groupIds, userGroup.groupId)))
    					return;

    				//Create a list of the view options
    				if(typeof viewOptions == "object")
    					viewOptions.collection = userGroup;
    				else
    					viewOptions = { collection: userGroup };

    				//Create the view and save it as a subview
    				var groupView = new GroupListView(viewOptions);
    				this.subviews.push(groupView);

    				//Collapse the views if need be
    				if((userGroup.get("isMemberOf") && (userGroup.get("isMemberOf").length > 3)) || (userGroup.length > 3))
    					groupView.collapseMemberList();

    				//Finally, render it and return
    				return groupView.render().el;
    			},

    				/**
    				 * Gets the groups the this user is a part of and creates a UserGroup collection for each
    				 */
    				getGroups: function(){
    				var view = this,
    					groups = [],
    					model = this.model;
    				//Create a group Collection for each group this user is a member of
    				_.each(_.sortBy(model.get("isMemberOf"), "name"), function(group){
    					var userGroup = new UserGroup([model], group);
    					groups.push(userGroup);

    					view.listenTo(userGroup, "sync", function(){
    						var list = this.createGroupList(userGroup);
    						this.$("#group-list-container").append(list);
    					});
    					userGroup.getGroup();
    				});
    			},

    				/**
    				 * Inserts a new form for this user to create a new group.
    				 * The form container is grabbed from the template
    				 */
    				insertCreateGroupForm: function(){
    				//Reset the form
    				$("#add-group-form-container").find("input[type='text']").val("").removeClass("has-error");
    				$("#group-name-notification-container").empty().removeClass("notification success error");

    				//Create a pending group that is stored locally until the user submits it
    				this.pendingGroup = new UserGroup([this.model], { pending: true });
    				var groupView = new GroupListView({ collection: this.pendingGroup });
    				this.subviews.push(groupView)
    				groupView.setElement(this.$("#add-group-container .member-list"));
    				groupView.render();
    			},

    				/**
    				 * Returns a container that includes a view of the user's group membership
    				 * @param {UserGroup[]} groups An array of UserGroup models
    				 * @param {String} listContainer An html string template of a container that will get appended
    				 * @returns {String} HTML string filled with groups information
    				 */
    				insertMembership: function(groups, listContainer){
    				var	model  = this.model,
    					list   = $(document.createElement("ul")).addClass("list-group member-list"),
    					listHeader = $(document.createElement("h5")).addClass("list-group-item list-group-header").text("Member of " + groups.length + " groups")

    				_.each(groups, function(group, i){
    					var name = group.name || "Group",
    						listItem = $(document.createElement("li")).addClass("list-group-item"),
    						groupLink = group.groupId? $(document.createElement("a")).attr("href", MetacatUI.root + "/profile/" + group.groupId).text(name).appendTo(listItem) : "<a></a>";

    					$(list).append(listItem);
    				});

    				if(this.model.get("username") == MetacatUI.appUserModel.get("username")){
    					var link = $(document.createElement("a")).attr("href", MetacatUI.root + "/profile/" + MetacatUI.appUserModel.get("username") + "/s=settings/s=groups").text("Create New Group"),
    						icon = $(document.createElement("i")).addClass("icon icon-on-left icon-plus"),
    						listItem = $(document.createElement("li")).addClass("list-group-item create-group").append( $(link).prepend(icon) );

    					$(list).append(listItem);
    				}

    				listContainer.html(list);
    				list.before(listHeader);
    				return listContainer;
    			},

    				/**
    				 * Will send a request for info about this user and their groups, and redraw the group lists.
    				 * Will also reset the "Create New Group" form
    				 */
    				refreshGroupLists: function(){
    				this.insertCreateGroupForm();
    				this.model.getInfo();
    			},

    				/**
    				 * Gets the group name the user has entered and attempts to get this group from the server
    				 * If no group is found, then the group name is marked as available. Otherwise an error msg is displayed
    				 * @param {Event} e
    				 */
    				checkGroupName: function(e){
    				if(!e || !e.target) return;

    				var view = this,
    					$notification = $("#group-name-notification-container"),
    					$input = $(e.target);

    				//Get the name typed in by the user
    				var name = $input.val().trim();
    				if(!name) return;

    				this.listenToOnce(this.pendingGroup, "nameChecked", function(collection){
    					//If the group name/id is available, then display so
    					if(collection.nameAvailable){
    						var icon = $(document.createElement("i")).addClass("icon icon-ok"),
    							message = "The name " + collection.name + " is available",
    							container = $(document.createElement("div")).addClass("notification success");

    						$notification.html($(container).append(icon, message));
    						$input.removeClass("has-error");
    					}
    					else{
    						var icon = $(document.createElement("i")).addClass("icon icon-remove"),
    							message = "The name " + collection.name + " is already taken",
    							container = $(document.createElement("div")).addClass("notification error");

    						$notification.html($(container).append(icon, message));
    						$input.addClass("has-error");
    					}

    				});

    				this.pendingGroup.checkName(name);
    			},

    				/**
    				 * Syncs the pending group with the server
    				 * @param {Event} e
    				 */
    				createGroup: function(e){
    				e.preventDefault();

    				//If there is no name specified, give warning
    				if(!this.pendingGroup.name){
    					var $notification = $("#group-name-notification-container"),
    						$input = $("#add-group-name");

    					var icon = $(document.createElement("i")).addClass("icon icon-exclamation"),
    						message = "You must enter a group name",
    						container = $(document.createElement("div")).addClass("notification error");

    					$notification.html($(container).append(icon, message));
    					$input.addClass("has-error");

    					return;
    				}
    				//If this name is not available, exit
    				else if(this.pendingGroup.nameAvailable == false) return;

    				var view = this,
    					group = this.pendingGroup;
    				var success = function(data){
    					view.showAlert("Success! Your group has been saved. View it <a href='" + MetacatUI.root + "/profile/" + group.groupId + "'>here</a>", "alert-success", "#add-group-alert-container");
    					view.refreshGroupLists();
    				}
    				var error = function(xhr){
    					var response = xhr? $.parseHTML(xhr.responseText) : null,
    						description = "";
    					if(response && response.length)
    						description = $(response).find("description").text();

    					if(description) description = "(" + description + ").";
    					else description = "";

    					view.showAlert("Your group could not be created. " + description + " Please try again.", "alert-error", "#add-group-alert-container")
    				}

    				//Create it!
    				if(!this.pendingGroup.save(success, error))
    					error();
    			},

    				/**
    				 * Displays an alert message to the user
    				 * @param {String} msg Message of the alert
    				 * @param {String} classes A class tag
    				 * @param {String} container The container tag
    				 */
    				showAlert: function(msg, classes, container) {
    				if(!classes)
    					var classes = 'alert-success';
    				if(!container || !$(container).length)
    					var container = this.$el;

    				//Remove any alerts that are already in this container
    				if($(container).children(".alert-container").length > 0)
    					$(container).children(".alert-container").remove();

    				$(container).prepend(
    					this.alertTemplate({
    						msg: msg,
    						classes: classes
    					})
    				);
    			},

    				/**
    				 * Closes the view and clears any subviews
    				 */
    				onClose: function() {
    				this.$el.html("");
    				this.stopListening(this.model)
    				this.subviews = new Array();
    			},

    		});

    		return UserGroupView;
    	});