﻿// Prepare Array object for searching
// http://snippets.dzone.com/posts/show/3631
Array.prototype.find = function(searchStr) {
  var returnArray = new Boolean();
  returnArray = false;
  for (i=0; i<this.length; i++) {
    if (typeof(searchStr) == 'object') {
      if (searchStr.test(this[i])) {
        if (!returnArray) { returnArray = [] }
        returnArray.push(i);
      }
    } else {
      if (this[i]===searchStr) {
        if (!returnArray) { returnArray = [] }
        returnArray.push(i);
      }
    }
  }
  return returnArray;
}

// Array Remove - By John Resig (MIT Licensed)
// http://ejohn.org/blog/javascript-array-remove/
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

// Prepare double click event support for DynaTree
DynaTreeNode.prototype.onDblClick = function(event) {	
	// if ( this.data.isFolder && ( this.aChilds || this.data.isLazy )
		// && (this.parent != null || this.tree.options.rootCollapsible)
		// ) {
		// this.toggleExpand();
	// } else if ( this.tree.options.onDblClick ) // Pass element as 'this' (jQuery convention)
	if ( this.tree.options.onDblClick ) // Pass element as 'this' (jQuery convention)
		this.tree.options.onDblClick.call(this.span, this);
}


// Collect cache data while parsing html list to DynaTree
// Overridden DynaTree method
DynaTreeNode.prototype._addNode = function(data) {
//	logMsg ('%o._addNode(%o)', this, data);
	// <performance_optimalization>
	var copofi = new Array();
	var prefix = new String();
	var regexpArr = new Array();
	var regexpStr = new String();
	var searchStr = new String();
	
	copofi = this.tree.options.copofiSelectedCategories;
	prefix = copofi.settings.categoryKeyPrefix;
	data.choosen = new Boolean();
	regexpArr.push("^");
	regexpArr.push(prefix);
	regexpArr.push("(.*)");
	regexpStr = regexpArr.join("");
	var regexpExp = new RegExp(regexpStr);
	searchStr = data.key.replace(regexpExp, "$1");
	
	data.choosen = copofi.selectedCategoryKeys.find(searchStr) ? true : false;
	// </performance_optimalization>
	
	var dtnode = new DynaTreeNode(this.tree, data);
		// prepare cache
		copofi.categoriesNamesCache.push(dtnode.data.title);
		copofi.categoriesKeysCache.push(dtnode.data.key);	
	return this._addChildNode(dtnode);
}

DynaTreeNode.prototype.choose = function() {
	this.data.choosen = true;
	this.span ? jQuery(this.span).children("a").addClass("choosen") : null;
}

DynaTreeNode.prototype.unchoose = function() {
	this.data.choosen = false;
	this.span ? jQuery(this.span).children("a").removeClass("choosen") : null;
}
DynaTreeNode.prototype.getInnerHtml = function() {
	var res = new String();

	// parent connectors
	var bIsRoot = new Boolean();
	bIsRoot = (this.parent==null);
	var bHideFirstConnector = new Boolean();
	bHideFirstConnector = ( !this.tree.options.rootVisible || !this.tree.options.rootCollapsible );

	var p = this.parent;
	var cache = this.tree.cache;
	while ( p ) {
		if ( ! (bHideFirstConnector && p.parent==null ) )
			res = ( p.isLastSibling() ? cache.tagL_ : cache.tagL_ns) + res ;
		p = p.parent;
	}

	// connector (expanded, expandable or simple)
	if ( bHideFirstConnector && bIsRoot  ) {
		// skip connector
	} else if ( this.aChilds && this.bExpanded  ) {
		res += ( this.isLastSibling() ? cache.tagM_ne : cache.tagM_nes );
	} else if (this.aChilds) {
		res += ( this.isLastSibling() ? cache.tagP_ne : cache.tagP_nes );
	} else if (this.data.isLazy) {
		res += ( this.isLastSibling() ? cache.tagD_ne : cache.tagD_nes );
	} else {
		res += ( this.isLastSibling() ? cache.tagL_ne : cache.tagL_nes );
	}
	// folder or doctype icon
	if ( this.data && this.data.icon ) {
		res += '<img src="' + this.tree.options.imagePath + this.data.icon + '" alt="" />';
	} else if ( this.data && this.data.icon == false ) {
		// issue #40: icon == false means 'no icon'
	} else if ( this.data.isFolder ) {
		res += ( this.bExpanded ? cache.tagFld_o : cache.tagFld );
	} else {
		res += cache.tagDoc;
	}

	// node name
	var tooltip = ( this.data && typeof this.data.tooltip == 'string' ) ? ' title="' + this.data.tooltip + '"' : '';
	var choosen = this.data.choosen ? "class=\"" + "choosen" + "\"" : null;
	
	res +=  '<a href="#" ' + tooltip + choosen + '>' + this.data.title + '</a>';
	return res;
}

// Initialize CopofiSelectCategories as instance of Class function from dynatree library
CopofiSelectCategories = Class.create();

// Renders interface for selecting category component on Liferay edit article journal form
// liferay-ext/ext-web/docroot/html/potlet/journal/edit_article.jsp
// to properly initialize component you need to correctly pass settings
(function($) {
CopofiSelectCategories.prototype = {
	initialize: function(component_container_id, settings) {
		// create Category tree component specific defaults
		$.ui.dynatree.defaults.onDblClick = null;
		
		this.settings = settings;
		
		// Prepare quick search functionality for DynaTree
		this.categoriesNamesCache = new Array();
		this.categoriesKeysCache = new Array();
		
		this.selected_categories_el = $($("#" + component_container_id + " > .selected_categories_area")[0]);
		this.jTree_el = $($("#" + component_container_id + " > .selection_tree > .tree_wrapper > .tree")[0]);
		this.categories_component = $($("#" + component_container_id)[0]);
		this.selection_tree_el = $("#" + component_container_id + " > .selection_tree")[0];
		
		var thisInstance = this;
		
		
		
		// initialize toggling selection tree		
		$("#" + component_container_id + " > .toggle_selection_tree").bind("click",{selection_tree_el: this.selection_tree_el},this.toggleSelectionTree);
		//this.toggleSelectionTree.call($("#" + component_container_id + " > .toggle_selection_tree")[0],{data:{selection_tree_el: this.selection_tree_el}});
		
		// initialize array with already selected categories
		this.selected_categories_field_el = $($("#" + component_container_id + " > .selected_categories_field")[0]);
		var selected_string = this.selected_categories_field_el.val();
		this.selectedCategoryKeys = selected_string.length == 0 ? [] : selected_string.split(this.settings.separator);
				//this.selectedCategoryKeys = selected_string.split(";");
		
		// render DynaTree on #tree container with following options
		if (this.settings.children != null) { // use children definition instead of parsing html
			this.jTree_el.dynatree({
				title: component_container_id,
				rootVisible: false,
				imagePath: this.settings.imagePath,
				selectExpandsFolders: false,
				onDblClick: function(dtnode) {
					// TODO: add duoble clicked category to selected category list
					// TODO: add checking if category is already selected
					//alert(dtnode.data.title + " " + dtnode.data.key);
					thisInstance.addCategory(dtnode.data.title,dtnode.data.key);				
				},
				copofiSelectedCategories: this,
				children: this.settings.children
			});
		} else {
			this.jTree_el.dynatree({
				title: component_container_id,
				rootVisible: false,
				imagePath: this.settings.imagePath,
				selectExpandsFolders: false,
				onDblClick: function(dtnode) {
					// TODO: add duoble clicked category to selected category list
					// TODO: add checking if category is already selected
					//alert(dtnode.data.title + " " + dtnode.data.key);
					thisInstance.addCategory(dtnode.data.title,dtnode.data.key);				
				},
				copofiSelectedCategories: this
			});
		}
		
		// render selected categories in gray field over Quick search
		var key = new String();
		var title = new String();
		for(var i=0; i < this.selectedCategoryKeys.length; i=i+1) {			
			key = this.settings.categoryKeyPrefix + this.selectedCategoryKeys[i];
			title = this.categoriesNamesCache[this.categoriesKeysCache.find(key)];
			this.renderSelectedCategory(title,key);
		}
		
		// make DynaTree resizable through it's wrapper, it's done due to jQuery UI resizable feature which is not compatible with overflow: auto css property
		$($("#" + component_container_id + " >  .selection_tree > .tree_wrapper")[0]).resizable({
			knobHandles: true,
			stop: function(e,ui) {
				thisInstance.jTree_el.height(ui.size.height-5);
				thisInstance.jTree_el.width(ui.size.width-5);
				thisInstance.categories_component.width(ui.size.width);
			}
		});
		
		// get instance of dynatree initialized for #tree container
		this.dynatree = this.jTree_el.dynatree("getTree");
		
		// attach keyup listener to Quick search input field above the tree
		$($("#" + component_container_id + " > .selection_tree > .search_query")[0]).keyup(function(e){
			var key = thisInstance.categoriesKeysCache[thisInstance.categoriesNamesCache.find(new RegExp("^" + $(e.target).val() + ".*$","i"))[0]]
			if (key != null) thisInstance.dynatree.selectKey(key);
			$(e.target).focus();
		});
	},
	toggleSelectionTree: function(e) {
		$(this).toggleClass("closed");
		$(e.data.selection_tree_el).toggle();
	},
	// attach remove listener to span button inside selected category
	removeCategory: function(e) {
		var selected_category = $(this).parent();
		selected_category.fadeOut("medium",function(){
			//alert($(this).attr("id"));
			var copofi = e.data.copofiObj;
			var key = e.data.key;
			var selectedStr = copofi.selected_categories_field_el.val();
			var keyId = key.replace(new RegExp("^" + copofi.settings.categoryKeyPrefix + "(.*)"),"$1");
			copofi.selected_categories_field_el.val(
				selectedStr.match( new RegExp("^"+ keyId + copofi.settings.separator + "?") ) ? 
					selectedStr.replace(new RegExp(keyId + copofi.settings.separator + "?"),"") : 
					selectedStr.replace(new RegExp(copofi.settings.separator + "?"+keyId),"")
			);
			copofi.selectedCategoryKeys.remove(copofi.selectedCategoryKeys.find(key));
			var dtnode = copofi.dynatree.getNodeByKey(key);
			dtnode ? dtnode.unchoose() : null;
			$(this).remove();
		});
	},
	// create visual representation for selected category
	addCategory: function(title, key) {		
		if (this.selectedCategoryKeys.find(key)) {
			//alert("category already selected");
		} else {
			var selectedStr = this.selected_categories_field_el.val();
			var keyId = key.replace(new RegExp("^" + this.settings.categoryKeyPrefix + "(.*)"),"$1");
			selectedStr.length == 0 ? this.selected_categories_field_el.val(keyId) : this.selected_categories_field_el.val(selectedStr + this.settings.separator + keyId);
			this.selectedCategoryKeys[this.selectedCategoryKeys.length] = key;
			var dtnode = this.dynatree.getNodeByKey(key);
			dtnode ? dtnode.choose() : null;			
			this.renderSelectedCategory(title,key);
		}
	},
	
	renderSelectedCategory: function(title,key) {
		var li = document.createElement('li');
		var span = document.createElement('span');
		//span.innerHTML = "X";
		li.id = this.settings.selectedIdPrefix + key;
		li.className = "selected_category";
		li.innerHTML = "<p>" + title + "</p>";
		$(li).append(span);
		this.selected_categories_el.prepend(li);
		$(span).bind("click", {copofiObj: this, key: key}, this.removeCategory);		
	}
}
})(jQuery);
