function soft_log(v)
{
	//console.log(v);
}

// Requires jQuery 1.2.6 and nicEdit 0.9.0

function SoftSpam()
{
	$sj = jQuery.noConflict();
	
	this.rootId = null;
	this.composedId = -1;
	this.softTags = new Array();
	this.editor = new nicEditor();
	this.storedRootTagsInformation = new Object();

	this.editor.setPanel('softSpamPanel');
}

SoftSpam.prototype.init = function (rootNodeId, composedId)
{
	this.rootId = rootNodeId;
	this.composedId = composedId;
	
	// get all nodes with soft_tags attribute
	var nodes = $sj("[soft_tags]");
	for ( var i=0; i < nodes.length; ++i )
	{
		var tag = new SoftTag();
		tag.parse( nodes[i], $sj(nodes[i]).attr("soft_tags") );
		tag.uid = "softspam_" + this.getUID();
		tag.inst = this;
			
		this.softTags.push( tag );
	}
	
	// setup the proper parentTags, this is not a beatiful way to do it, but the only way I could get it to work
	var repeats = this.getTagsByType( SoftTag.TYPE_REPEAT );
	var abort = false;
	for ( var i=0; i < this.softTags.length; ++i )
	{
		var t = this.softTags[i];
		if ( t.type == SoftTag.TYPE_REPEAT_CHILD_EDIT || t.type == SoftTag.TYPE_REPEAT_CHILD )
		{
			// Now find out which parent TYPE_REPEAT this child belongs to

			// Get a list of all children in this parent and compare them to the node
			parents = $sj( t.node ).parents();
			for ( var x = 0; x < parents.length; ++x )
			{
			for ( var n = 0; n < repeats.length; ++n )
			{
				if ( parents[x] == repeats[n].node )
				{
					t.parentTag = repeats[n];
					soft_log( $sj(t.node).attr("soft_tags") + " has parent " + repeats[n].node + " ("+repeats[n].uid+")");
					abort = true;
				}
			}
			if ( abort )
			{
				abort = false;
				break;
			}
			}
		}
	}
	
	this.attachTools();
}

SoftSpam.prototype.attachTools = function ()
{
	var tag = null;

	for ( var i = 0; i < this.softTags.length; ++i )
	{
		tag = this.softTags[i];
		
		switch ( tag.type )
		{
			case SoftTag.TYPE_EDITABLE:
			{
				this.setEditElement(tag);
			}
			break;
		
			case SoftTag.TYPE_REPEAT:
			{
				this.setRepeatElement(tag);
			}
			break;

			case SoftTag.TYPE_REPEAT_CHILD_EDIT:
			{
				this.setEditElement(tag);
			}
			break;

			case SoftTag.TYPE_REPEAT_CHILD:
			default:
			{
				// Unknown type
			}
			break;
		}
	}
}

SoftSpam.prototype.setRepeatElement = function (tag)
{
	if ( tag.clone == 1 )	return;

	// Append a add button
	this.insertTool(tag.toolsposition+"_add", '<div id="append_'+tag.uid+'" edit_value="+" style="overflow: hidden; width: 12px; height: 12px; cursor: pointer; background-image: url(icons/insert.gif);" >');
	soft_log("inserTool");
	soft_log("\t " + tag.toolsposition+"_add");
	soft_log("\t append_"+tag.uid);
	
	$sj("#append_"+tag.uid).get(0).softInst = this;
	$sj("#append_"+tag.uid).click( function () {
			$sj(this).attr("softInst").onAppendClicked( $sj(this).attr("id") );
	});
	
	// Append the remove button to each repeated sibling
	var siblings = $sj(tag.node).parent().children("[soft_tags]");
	for( var i=0; i < siblings.length; ++i)
	{
		var t = this.findSoftTag(null, siblings[i]);
		
		if ( t == null )
		{
			soft_log("Found no tag matching element " + siblings[i] + "("+i+")");
			continue;
		}
		
		this.insertTool(t.toolsposition+"_remove", '<div id="remove_'+t.uid+'" edit_value="-" style="overflow: hidden; width: 12px; height: 12px; cursor: pointer; background-image: url(icons/remove.gif);" />', t.node);
		
		$sj("#remove_"+t.uid).get(0).softInst = this;
		$sj("#remove_"+t.uid).click( function () {
				$sj(this).attr("softInst").onRemoveClicked( $sj(this).attr("id") );
		});
	}
}

SoftSpam.prototype.onRemoveClicked = function (uid)
{
	var tag = this.findSoftTag(uid);
	
	var repeats = this.getRepeatTagSiblings( tag );
	if ( repeats.length == tag.min ) {
		alert("Minsta antal är " + tag.min);
		return;
	}

	// If it's not a root tag then store the tag in case of later appendings
	if ( tag.clone == 0 ) {
		this.saveRootInfo(uid, tag, $sj(tag.node).parent().get(0) );
	}
	
	// If the removed tag isn't a clone we need it for later use.
	// Which means we need to reconstruct it
	if ( tag.clone == 0 )
	{
		var html = $sj(tag.node).html();
		$sj(tag.node).remove();
		$sj(tag.node).html( html );
	}
	else
	{
		$sj(tag.node).remove();
	}
	
	
	// remove all of the tags children
	var children = this.getTagChildren( tag );
	for ( var i = 0; i < children.length; ++i )
		this.removeTag( children[i] );
	
	// remove the tag
	this.removeTag( tag );
}

SoftSpam.prototype.onAppendClicked = function (uid)
{
	var tag = this.findSoftTag(uid);
	
	var repeats = this.getRepeatTagSiblings( tag );
	if ( repeats.length >= tag.max ) {
		alert("Max antal är " + tag.max + " ("+repeats.length+")");
		return;
	}
	
	$sj("#"+uid).remove();
		
	// duplicate the HTML node
	var cloned = null;
	if ( this.getRootInfo(uid) ) {
		soft_log("\treuse old node");
		cloned = $sj(tag.node);
	}
	else {
		soft_log("\tclone new tag");
		cloned = $sj(tag.node).clone();
	}
	
	if ( this.getRootInfo(uid) ) {
		cloned.appendTo( $sj(this.getRootInfo(uid).parent) );
	}
	else if ( $sj(tag.node).parent().get(0) ) {
		cloned.appendTo( $sj(tag.node).parent() );
	}
	else {
		alert("Ett knas fel inträffade, inte bra.. inte bra alls. :(");
		return;
	}
		
	cloned.find("div[edit_value]").remove(); // remove all of the input buttons
	
	//remove the - buttons
	$sj("#"+this.rootId).find("[soft_tool='"+tag.toolsposition+"_remove']").children().remove();
	
	// add a new tag for this repeat element
	var t = tag.createClone();
	t.node = cloned.get(0);
	t.uid = "softspam_" + this.getUID();
	this.softTags.push(t);
	
	// If this was a reused root node we set this to the new rootnode and delete the old one 
	if ( this.getRootInfo(uid) )
	{
		t.clone = 0;
		this.clearRootInfo(uid);
			
		// Root node has been reused, now swap append button id
		tag = t;
	}
	
	// set the soft_tags
	cloned.attr("soft_tags", t.toString() );
	
	this.appendNewChildren( cloned.get(0), t );
		
	this.setRepeatElement(tag);
	
	this.invalidateButtonPositions();
}

SoftSpam.prototype.setEditElement = function (tag)
{
	this.editor.addInstance(tag.node);
}

SoftSpam.prototype.extractUID = function ( uid )
{
	if ( uid && uid.indexOf("_") != -1 ) {
		return "softspam_" + uid.substr( uid.lastIndexOf("_") + 1 );
	}

	return uid;
}

SoftSpam.prototype.saveRootInfo = function ( uid, tag, parent )
{ 
	uid = this.extractUID(uid);
	this.storedRootTagsInformation[uid] = {
		tag: tag,
		parent: parent
	};
}

SoftSpam.prototype.getRootInfo = function ( uid )
{ 
	uid = this.extractUID(uid);
	return this.storedRootTagsInformation[uid];
}

SoftSpam.prototype.clearRootInfo = function ( uid )
{ 
	uid = this.extractUID(uid);
	this.storedRootTagsInformation[uid] = null;
}

SoftSpam.prototype.findSoftTag = function ( uid, node )
{
	// might need to extract the number from the uid, not very nice but easier to do here than many other places
	if ( uid != null ) {
		uid = this.extractUID(uid);
		 
		// Try to recreate the root tag
		if( this.storedRootTagsInformation[uid] )
		{
			return this.storedRootTagsInformation[uid].tag;
		}
	}
	
	for ( var i=0; i < this.softTags.length; ++i )
	{
		if ( uid != null )
		{
			if ( uid == this.softTags[i].uid )
				return this.softTags[i];
		}
		else if ( node != null )
		{
			if ( node == this.softTags[i].node )
				return this.softTags[i];
		}
	}
	
	return null;
}

SoftSpam.prototype.removeTag = function ( tag )
{
	this.editor.removeInstance(tag.node);

	for ( var i=0; i < this.softTags.length; ++i )
	{
		if ( this.softTags[i] == tag ) {
			this.softTags.splice(i, 1);
		}
	}
}

SoftSpam.prototype.getTagsByType = function (type)
{
	var a = new Array();
	
	for ( var i = 0; i < this.softTags.length; ++i )
	{
		if ( this.softTags[i].type == type )
			a.push( this.softTags[i] );
	}
	
	return a;
}

SoftSpam.prototype.getRepeatTagSiblings = function ( tag )
{
	var a = new Array();
	
	var repeats = this.getTagsByType( SoftTag.TYPE_REPEAT );
	for ( var i = 0; i < repeats.length; ++i )
	{
		if ( repeats[i].key == tag.key )
			a.push( repeats[i] );
	}
	
	return a;
}

SoftSpam.prototype.getTagChildren = function ( parentTag )
{
	var children = new Array(); 
	for ( var i = 0; i < this.softTags.length; ++i )
	{
		if ( this.softTags[i].parentTag == parentTag )
			children.push( this.softTags[i] );
	}
	
	return children;
}

SoftSpam.prototype.appendNewChildren = function ( node, parentTag )
{
	var c = $sj(node).find("[soft_tags]");
	soft_log("\tfound " + c.length + " children");
	for ( var i = 0; i < c.length; ++i )
	{
		var t = new SoftTag();
		t.parse( c[i], $sj(c[i]).attr("soft_tags") );
		t.uid = "softspam_" + this.getUID();
		t.parentTag = parentTag;
		this.softTags.push(t);
		
		this.setEditElement( t );
		
		$sj(c[i]).html( t.defaultvalue );
	}
}

SoftSpam.prototype.saveComposed = function ( url, cbFunc )
{
	var inst = this;
	var data = "";
	
	this.imageAttributeFix();
	
	var repeatparents = this.getTagsByType( SoftTag.TYPE_REPEAT );
	for ( var n = 0; n < repeatparents.length; ++n )
	{
		if ( repeatparents[n].clone == 0 )
		{
			var repeats = this.getRepeatTagSiblings( repeatparents[n] );
			for ( var i = 0; i < repeats.length; ++i )
				repeats[i].repeatCounter = i;
		}
	}
	
	$sj( this.softTags ).each( function (i) {
			data += inst.extractTagKeyPair(this);
		});
		
	data += "composed_id=" + this.composedId;
	
	//alert(data);
	$sj.post(url, data, cbFunc, "json");
}

		
SoftSpam.prototype.imageAttributeFix = function ()
{
	// Set the proper image attributes so that Outlook doesn't get sad
	var images = $j("#"+this.rootId+" img");
	for( var i=0; i < images.length; ++i )
	{
		var w = $j(images[i]).css("width")
		var h = $j(images[i]).css("height");
		
		w = w.slice(0, w.length-2);
		h = h.slice(0, h.length-2);
		
		$j(images[i]).attr("width", w);
		$j(images[i]).attr("height", h);
		$j(images[i]).attr("border", 0); // Need this for Thunderbird
		
		images[i].src = images[i].src;
	}
	
	// Remove the Mso classes, this will totally mess up the mail
	// when viewing in Outlook
	$j("#"+this.rootId+" .MsoNormal").attr("class", "");
}

SoftSpam.prototype.extractTagKeyPair = function ( tag )
{
	switch ( tag.type )
	{
		case SoftTag.TYPE_REPEAT_CHILD_EDIT:
		case SoftTag.TYPE_REPEAT_CHILD:
		{
			return tag.key + "_"+ tag.parentTag.repeatCounter +"=" + escape(tag.value()) + "&";
		}
		break;
	
		case SoftTag.TYPE_REPEAT:
		case SoftTag.TYPE_EDITABLE:
		{
				return tag.key + "=" + escape(tag.value()) + "&";
		}
		break;

		default:
		{
			return "";
		}
		break;
	}
	
}

/**
 * Reposition all the edit buttons so they match the new layout
 */
SoftSpam.prototype.invalidateButtonPositions = function () 
{
	var buttons = $sj("div[edit_value]");
	
	for( var i = 0; i < buttons.length; ++i)
	{
		var id = $sj(buttons[i]).attr("id");
		var t = this.findSoftTag( id );
		if ( t )
		{
				var offset = $sj(t.node).offset();
				offset.left -= 14;
				
				$sj( buttons[i] ).css("left", offset.left+"px");
				$sj( buttons[i] ).css("top", offset.top+"px");
		}
		else
		{
			soft_log("Found no tag matching: " + id);
		}
	}
}

/**
 * Insert a tools html into the specified position of the node
 */
SoftSpam.prototype.insertTool = function (position, value, parent)
{
	if ( parent )
	{
		$sj(parent).find("[soft_tool='"+position+"']").append(value);
	}
	else
	{
		$sj("[soft_tool='"+position+"']").append(value);
	}
}

var _global_uid = 0;
SoftSpam.prototype.getUID = function ()
{
	return _global_uid++;
}

/**
 * SoftTag class
 */
function SoftTag()
{
	SoftTag.TYPE_EDITABLE 						= 'editable';
	SoftTag.TYPE_REPEAT 							= 'repeat';
	SoftTag.TYPE_REPEAT_CHILD 				= 'repeat_child';
	SoftTag.TYPE_REPEAT_CHILD_EDIT 		= 'repeat_child_edit';
	
	this.type = 'editable';
	this.key = "";
	this.max = 1;
	this.min = 1;
	this.parent = "";
	this.parentTag = null;
	this.defaultvalue = "";
	this.toolsposition = "";
	this.node = null; // HTMLNode
	this.repeatCounter = 0; // Parent counter
	this.clone = 0;
	
	this.isEmpty = false;
	this.inst = null;
	
	this.uid = 0;
}

SoftTag.prototype.createClone = function ()
{
	var t = new SoftTag();
	
	t.type = this.type;
	t.key = this.key;
	t.max = this.max;
	t.min = this.min;
	t.parent = this.parent;
	t.defaultvalue = this.defaultvalue;
	t.toolsposition = this.toolsposition;
	t.node = this.node;
	t.inst = this.inst;
	t.clone = 1;
			
	return t;
}

SoftTag.prototype.parse = function ( node, tags )
{
	this.node = node;
	
	if ( tags == "empty" ) {
		this.isEmpty = true;
		return;
	}
	
	var pairs = tags.split("|");
	for( var i = 0; i < pairs.length; ++i )
	{
		var attrs = pairs[i].split("=");
		
		if ( attrs.length == 1 )
			this.type = attrs[0];
		else
			this[attrs[0]] = attrs[1];
	}
}

SoftTag.prototype.value = function ()
{
	switch ( this.type )
	{
		case SoftTag.TYPE_REPEAT_CHILD_EDIT:
		case SoftTag.TYPE_EDITABLE:
		case SoftTag.TYPE_REPEAT_CHILD:
		{
			return $sj(this.node).html();
		}
		break;
	
		case SoftTag.TYPE_REPEAT:
		{
			var cnt = 0; 
			// find out how many repat tags there are with this key
			for ( var i = 0; i < this.inst.softTags.length; ++i )
			{
				if ( this.inst.softTags[i].key == this.key )
					++cnt;
			}
			return cnt;
		}
		break;

		default:
		{
			return "";
		}
		break;
	}
}

SoftTag.prototype.toString = function ()
{
	switch ( this.type )
	{
		case SoftTag.TYPE_REPEAT_CHILD_EDIT:
		case SoftTag.TYPE_EDITABLE:
		case SoftTag.TYPE_REPEAT_CHILD:
		{
			return "";
		}
		break;
	
		case SoftTag.TYPE_REPEAT:
		{
			return SoftTag.TYPE_REPEAT + "|max=" + this.max + "|min=" + this.min + "|key=" + this.key + "|clone=" + this.clone + "|toolsposition=" + this.toolsposition;
		}
		break;

		default:
		{
			return "";
		}
		break;
	}
} 