/**
 * Toggles a tag around the given selection(s)
 * 
 * setup:
 * - tag (string): "strong", "em", etc.
 * 
 * FIXME:
 * - should I implement a logic chain that triggers outside of HTML syntax?
 *   Old action would let you wrap with bold tags even in strings or non-HTML languages.
 */

action.performWithContext = function(context, outError) {
	// Init our variables
	var tag = action.setup.tag,
		targetSelector = new SXSelector("tag.open:not(self-closing):has-child(name[text=='" + tag + "']) *"),
		tagSelector = new SXSelector("tag.open:has-child(name[text=='" + tag + "']), tag.close:has-child(name[text=='" + tag + "'])"),
		recipe = new CETextRecipe(),
		// Loop vars
		range, item, matched, zone, snippet;
	
	// Loop through our selections and process them all
	for (var i = 0, count = context.selectedRanges.length; i < count; i++) {
		range = context.selectedRanges[i];
		item = context.itemizer.itemAtCharacterIndex(range.location);
		matched = false;
		// Look for our target tag
		while (item) {
			zone = context.syntaxTree.zoneAtCharacterIndex(item.range.location);
			if (zone && targetSelector.matches(zone)) {
				matched = true;
				break;
			} else {
				item = item.parentItem;
			}
		}
		if (matched) {
			// The target tag is wrapping our selection, so remove the start and end tags
			recipe.deleteRange(new Range(item.range.location, item.innerRange.location - item.range.location));
			recipe.deleteRange(new Range(item.innerRange.location + item.innerRange.length, (item.range.location + item.range.length) - (item.innerRange.location + item.innerRange.length)));
		} else if (range.length === 0) {
			// The range is zero-lenght, so that means we are inserting a snippet and returning (since there will not be any other ranges)
			snippet = new CETextSnippet('<' + tag + '>$1</' + tag + '>');
			return context.insertTextSnippet(snippet);
		} else if (context.selectedRanges.length === 1) {
			// We are only working with a single range, so we can again use snippets and immediately return
			snippet = new CETextSnippet('<' + tag + '>${1:$EDITOR_SELECTION}</' + tag + '>');
			return context.insertTextSnippet(snippet);
		} else {
			// Working with multiple changes, so queue up all changes in the recipe and we'll apply it after the loop exits
			recipe.replaceRange(range, '<' + tag + '>' + context.substringWithRange(range) + '</' + tag + '>');
		}
	}
	
	// Finalize our changes!
	return context.applyTextRecipe(recipe);
};
