/**
 * @fileOverview Takes cares of the collection groping, filtering and showing the right menu bundles
 * @author José Fernández Alameda
 * @date 2010-05-28
 */
 

var Bundles = jQuery.Class.create({
	/**
	 * Stores the ID of the bundles menu selector
	 */
	leftMenuSelector: "#bundles-menu",
	/**
	 * Stores the bundles collections
	 */
	collections: null,
	/**
	 * Elements container
	 */
	container: null,
	/**
	 * Stores the colors associated to ech bundle
	 */
	bundlesColors: null,
	/**
	 * Stores the bundles hash map
	 */
	bundlesHashMap: null,
	/**
	 * Last element selected
	 */
	lastSelected: null,
	/**
	 * Call function to select a bundle
	 */
	callback: null,
	/**
	 * Stores the button to create a new bundle
	 */
	newBundleButton: null,
	/**
	 * Stores the bundle pop up content
	 */
	bundlePopUpContent: null,
	/**
	 * Stores the Id's of the removed bundles
	 */
	removedBundles: null,
	/**
	 * Stores the list of changed bundles
	 */
	changedBundles: null,
	/**
	 * Stores the LIST_ALL element
	 */
	listAll: {id: "LIST_ALL", name: "List all bookmarks"},
	/**
	 * Stores the service name to call to perform actions over the bundles
	 */
	serviceName: null,
	/**
	 * Stores the actions names
	 */
	actionsMap: null,
	/**
	 * Stores the pop up titles
	 */
	textsMap: null,
	/**
	 * Class constructor
 	 */
	init: function(data,callback,fullList) {
		var _this = this;
		this.bundlesColors  = new Object();
		this.bundlesHashMap = new Object();
		this.removedBundles = new Array();
		this.changedBundles = new Array();
		this.serviceName    = "myBookmarks";
		this.actionsMap     = {
			save:   "add_collection",
			edit:   "modify_collection",
			remove: "remove_collection"
		};
		this.textsMap       = {
			addTitle:    "Create a new bundle",
			editTitle:   "Rename bundle",
			removeTitle: "Delete bundle",
			removeText:  "Are you sure you want to delete the bundle"
		};
		this.initCreateNewBundle();
		if(data) {
			this.createLayout();
			this.collections = data.output.collections;
			this.collections = [{id: "LIST_ALL", name: "List all bookmarks"}].concat(this.collections);
			this.renderCollection();
			this.markDefaultValue("LIST_ALL");
			this.callback = callback;
		}
	},
	/**
	 * Marks a bundle on the list
	 * @param id The id of the bunle to mark
	 */
	markDefaultValue: function(id,click) {
		var element = $($(this.container.find("#bundles-menu")).find("#"+id));
		if(click === true)
			element.click();
		else { 
			this.lastSelected = element;
			this.showSelected($(element));
		}
	},
	/**
	 * Displays the modal window with the form to create a new bundle and implements its functionality
	 */
	initCreateNewBundle: function() {
		var _this = this;
		var msg = $('<div>Title: <input type="text" id="bundle-title" maxlength="50"/><div id="ajax-loader" class="ajax-loader clear" style="display: none;"></div><div class="error-display" id="error-display" style="display: none;"></div></div>');
		this.bundlePopUpContent = msg;
		this.bundleCreationPanel = new ConfirmationPopUp({TYPE: "QUESTION", message: msg, title: this.textsMap.addTitle, yesAction: function() { _this.saveBundle(msg); }, noAction: function() { _this.bundleCreationPanel.hide(); }, labels: {yes: "Save", no: "Cancel"}});
		this.newBundleButton = new Dropdown({label: '<div class="addbutton button-add-fix left"></div>Create new bundle', dropdown: false, callback: function() {
			$(_this.bundlePopUpContent.find("input")).val("");
			$(_this.bundlePopUpContent.find("#error-display")).hide();
			_this.bundleCreationPanel.show();
		}});
	},
	saveBundle: function(element) {
		var _this = this;
		var input = element.find("#bundle-title");
		if(this.checkFields(input,  $(this.bundlePopUpContent.find("#error-display")))) {
			$(this.bundlePopUpContent.find("#ajax-loader")).show();
			this.bundleCreationPanel.disableButtons();
			$.ajax({
				url: GlobalConfig.AJAX_DISPATCHER_URL,
				type: GlobalConfig.AJAX_DISPATCHER_METHOD,
				success: function(data) {
					_this.bundleAddedAction(data);
				},
				data: "{ serviceName: '"+this.serviceName+"', action: '"+this.actionsMap.save+"', parameters: {collectionName: {value: '"+input.val().replace(/'/g,"&#39;")+"'}}}}"
			});
		}
	},
	/**
	 * Checks the fields looking for erros
	 */
	checkFields: function(input,err) {
		if(input.val() == "") {
			err.text("The bundle title must be filled in");
			err.fadeIn();
			return false;
		}
		else {
			err.hide();
		}
		return true;
	},
	bundleAddedAction: function(data) {
		var collection = $.parseJSON(data).output.new_collection;
		this.bundleCreationPanel.enableButtons();
		collection["lowerCaseName"] = collection.name.toLowerCase();
		$(this.bundlePopUpContent.find("#ajax-loader")).hide();
		this.collections.push(collection);
		this.collections = qsort(this.collections.splice(1,this.collections.length-1),"lowerCaseName");
		this.collections = [this.listAll].concat(this.collections);
		//var elem = $(this.container.find("#bundles-menu")).find("#"+collection.id);
		this.renderCollection();
		this.selectLastSelectedElement();
		this.bundleCreationPanel.hide(); 
	},
	/**
	 * Creates the collection menu layout
	 */
	createLayout: function() {
		var _this = this;
		this.container = $('<div id="content-right"><div id="bundles-menu"><h2>Bundles</h2></div><div class="bundles-buttons clear"></div></div>');
		$('#bundles').append(this.container);
		var button = $('<a href="#">Create new bundle</a>');
		$(this.container.find(".bundles-buttons")).append(this.newBundleButton.getHtml());
	},
	/**
	 * Paints the collection
	 */
	renderCollection: function() {
		var ul = $('<ul class="clear"></ul>');
		for(i in this.collections) {
			this.collections[i]["lowerCaseName"] = this.collections[i].name.toLowerCase();
			this.bundlesHashMap[this.collections[i].id] = this.collections[i];
			var color = this.getColor(this.collections[i].id,this.collections[i].name);
			this.bundlesColors[this.collections[i].id] = color;
			var colorBox;
			colorBox = '<div class="color-bundle color" style="margin-top: 2px; float: left; width: 10px; height: 12px; background-color: '+color+'; border-width: 1px 0;"><div style="margin: 0; margin-left: -1px; height:10px; width: 12px; margin-top: 1px; background-color: '+color+';" class="color"></div></div>';
			if(this.collections[i].id == "LIST_ALL")
				ul.append(this.createListAllBox(this.collections[i]));
			else {
				ul.append(this.createBundleRow(this.collections[i],colorBox));
			}
		}
		var _this = this;
		ul.bind("click", function(data) {
			if(($(data.target).is("li") || $(data.target).is("span") || $(data.target).is("a")) && typeof _this.callback == "function")
				_this.callback($(data.target).is("li") ? $(data.target).attr("id") : $(data.target).parent().attr("id"));
				_this.showSelected($(data.target));
		});
		$($(this.container.find("#bundles-menu")).find("ul")).remove();
		$(this.container.find("#bundles-menu")).append(ul);
	},
	/**
	 * Creates a bundle LI row and add some observers on it that will perform future actions
	 * @param collection The bundle information to be rendered
	 * @param colorBox The color box
	 */
	createBundleRow: function(collection, colorBox) {
		var row = $('<li id="'+collection.id+'" class="clear">'+colorBox+'<span class="bundle left">'+collection.name+"</span>"+'<div class="icons-hover right" style="display: none;">'+
		       '<div class="icon-edit left"></div><div class="icon-close left">X</div>'+
               '</div></li>');
		this.addMouseOverBehaviour(row,collection);
		return row;
	},
	/**
	 * Adds the functionality that shows and hides the bundles controls when mouseover and mouseout
	 * @param row The row HTML
	 * @param bundle The bundle information
	 */
	addMouseOverBehaviour: function(row,bundle) {
		var _this = this;
		var edit  = row.find(".icon-edit");
		var close = $(row.find(".icon-close"));
		var icons = $(row.find(".icons-hover"));
		row.mouseover(function() {
			icons.show();
		});
		row.mouseout(function() {
			icons.hide();
		});
		close.click(function() {
			_this.startBundleDeletionProcess(bundle);
		});
		edit.click(function() {
			_this.startBundleModificationProcess(bundle);
		});
	},
	/**
	 * Creates the list all button
	 * @param collection The collection item
	 */
	createListAllBox: function(collection) {
		return '<li id="LIST_ALL" class="list-all">'+collection.name+'</li>';
	},
	/**
	 * Show the selected bundle
	 */
	showSelected: function(element) {
		if(element.is("li") || element.is("span")) {
			var target = element.is("span") ? element.parent() : element;
			$.each(target.find(".color"), function(key,val) {
				$(val).css("background-color","#FF9900");
			});
			$(target).attr("style","background-color: #EEEEEE");
			if(this.lastSelected && this.lastSelected.attr("id") != target.attr("id")) {
				$(this.lastSelected).attr("style","background-color: none");
				$.each(this.lastSelected.find(".color"), function(key,val) {
					$(val).css("background-color","#87C44F");
				});
			}
			this.lastSelected = target;
		}
	},
	/**
	 * Gets the bundles marker color
	 */
	getColor: function(index,name) {
		return "#87C44F";
	},
	/**
	 * Returns the collections
	 */
	getCollections: function() {
		return this.collections;
	},
	/**
	 * Returns the bundles list
	 */
	getBundlesHashMap: function() {
		return this.bundlesHashMap;
	},
	/**
	 * Shows all the bundles and mark "All bundles" on the menu
	 */
	markAll: function() {
		$($(this.container.find("#bundles-menu")).find("[id=LIST_ALL]")).click();
	},
	/**
	 * Starts the bundle deletion process
	 * @param bundle An object containing the bundle name and the bundle id
	 */
	startBundleDeletionProcess: function(bundle) {
		var _this = this;
		if(this.confirmationPanel) {
			this.confirmationPanel.hide();
			delete this.confirmationPanel;
		}
		this.confirmationPanel     = new ConfirmationPopUp({TYPE: "QUESTION", message: "<p>"+this.textsMap.removeText+" '"+bundle.name+"'?</p>"+'<div class="ajax-loader" style="display: none;"></div>',
														  title: this.textsMap.removeTitle+" '"+bundle.name+"'?", yesAction: function() { _this.sendAjaxBundleDeletion(bundle); },
			                                              noAction: function() { _this.confirmationPanel.hide(); }, labels: {yes: "Delete", no: "Cancel"}});
		this.confirmationPanel.show();
	},
	/**
	 * Sends an AJAX request to the backend to perform a bundle deletion
	 * @param bundle The bundle information
	 */
	sendAjaxBundleDeletion: function(bundle) {
		var _this = this;
		this.confirmationPanel.getHtml().find(".ajax-loader").show();
		$.ajax({
			url: GlobalConfig.AJAX_DISPATCHER_URL,
			type: GlobalConfig.AJAX_DISPATCHER_METHOD,
			success: function(data) {
				data = $.parseJSON(data);
				if(data.output.removedUUID)
					_this.removedBundles.push(data.output.removedUUID.value);
				_this.confirmationPanel.hide();
				delete this.confirmationPanel;
				_this.removeBundleFromList(bundle.id);
				_this.markAll();
			},
			data: "{ serviceName: '"+this.serviceName+"', action: '"+this.actionsMap.remove+"', parameters: {collectionId: {value: '"+bundle.id+"'}}}}"
		});
	},
	/**
	 * Starts the bundle deletion process
	 * @param bundle An object containing the bundle name and the bundle id
	 */
	startBundleModificationProcess: function(bundle) {
		var _this  = this;
		var msg    = $('<div>Title: <input type="text" id="bundle-title" maxlength="50" value="'+bundle.name+'" /><div id="ajax-loader" class="ajax-loader clear" style="display: none;"></div><div class="error-display" id="error-display" style="display: none;"></div></div>');
		var modify = null;
		modify     = new ConfirmationPopUp({TYPE: "QUESTION", message: msg,
														  title: this.textsMap.editTitle, yesAction: function() { _this.sendAjaxBundleModification(bundle,modify); },
			                                              noAction: function() { modify.hide(); }, labels: {yes: "Save", no: "Cancel"}});
		modify.show();
	},
	/**
	 * Sends an AJAX request to the backend to perform a bundle deletion
	 * @param bundle The bundle information
	 */
	sendAjaxBundleModification: function(bundle,panel) {
		var _this = this;
		var input = $(panel.getHtml().find("input"));
		var collectionName = $(panel.getHtml().find("input")).val();
		if(this.checkFields(input,  $(panel.getHtml().find("#error-display")) )) {
			panel.getHtml().find(".ajax-loader").show();
			$.ajax({
				url: GlobalConfig.AJAX_DISPATCHER_URL,
				type: GlobalConfig.AJAX_DISPATCHER_METHOD,
				success: function(data) {
					data = $.parseJSON(data);
					panel.hide();
					delete panel;
					_this.insertOrReplace(data.output.collection,_this.changedBundles);
					_this.modifyBundleFromList(bundle.id,data.output.collection.name);
				},
				data: "{ serviceName: '"+this.serviceName+"', action: '"+this.actionsMap.edit+"', parameters: {collection: {id: '"+bundle.id+"', name: '"+collectionName+"'}}}"
			});
		}
	},
	/**
	 * Removes a bundle from the bundles list
	 * @param id The bundle id to remove
	 */
	removeBundleFromList: function(id) {
		for(i in this.collections) {
			if(this.collections[i].id == id)
				this.collections.splice(i,1);
		}
		this.renderCollection();
		this.selectLastSelectedElement();
	},
	/**
	 * Modifies a bundle from the list
	 * @param id The bundle ID to modify
	 * @param name The bundle new name
	 */
	modifyBundleFromList: function(id,name) {
		for(i in this.collections) {
			if(this.collections[i].id == id)
				this.collections[i].name = name;
		}
		this.renderCollection();
		this.selectLastSelectedElement();
	},
	/**
	 * Mark as selected the last element select by the user. This function should be called after rendering
	 * the collection
	 */
	selectLastSelectedElement: function() {
		var elem = $($(this.container.find("#bundles-menu")).find("#"+this.lastSelected.attr("id")));
		elem.click();
	},
	/**
	 * Insert or replace an element on an array depending of if it exists or not
	 */
	insertOrReplace: function(item, array) {
		var replaced = false;
		for(i in array) {
			if(array[i].id == item.id) {
				array[i] = item;
				replaced = true;
			}
		}
		if(!replaced)
			array.push(item);
		return array;
	}
});
 
