(function() {

// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,

// Is it a simple selector
	isSimple = /^.[^:#\[\.]*$/,

// IsPHPArray
	phpVariable = /([^\[\]]*)(\[.*\])*/;

var objectCache = [];
var elementCache = [];

var jQuery = window.jQuery;

var _maxZ = 1000;
var _nextId = 0;
var dropArray = {};

var Shout = window.Shout = function(selector)
{
	return new Shout.fn.init(selector);
};

Shout.fn = Shout.prototype = {
	nextId: function()
	{
		return 'Shout-Gen-' + _nextId++;
	},
	init: function(selector) {

		if(!selector)
		{
			return this;
		}
		else if(selector && selector.nodeEl)
		{
			return selector;
		}
		else if ( typeof selector == "string" )
		{
			// Use jquery expression to determine if we've got
			// and id string.

			var match = quickExpr.exec( selector );

			if(match && match[3] !== undefined)
			{
				if(objectCache[match[3]])
				{
					return objectCache[match[3]];
				}
				else
				{
					objectCache[match[3]] = this;
				}
			}
			this.nodeEl = jQuery(selector);
		}
		else if(selector)
		{
			this.nodeEl = jQuery(selector);
		}
		else
		{

		}

		this.attachParams = null;
		this.inherittedMove = false;
		this.shoutId = '';
		this.attachments = [];
		this.constraints = {};

		this.dragProxy = null;
		this.dropProxy = null;

		this.shoutId = this.nextId();

		this.nodeEl.data('shoutObj',this);

		return this;

	}
};

// Give the init function the Shout prototype

Shout.fn.init.prototype = Shout.fn;

jQuery.extend(Shout, {

	configure: function(params)
	{
		this.configuration = params;
	},

	objSerialize: function(fields)
	{
		var returnObj = {};

		jQuery.each(jQuery(fields),function()
		{
			var field = jQuery(this);
			returnObj[field.attr('name')] = field.val();
		});

		return returnObj;
	},

	loadFields: function(region,dataArray,prefix)
	{
		var params = [];

		if(dataArray)
		{
			jQuery.each(dataArray, function(e,obj) {
				jQuery.each(obj, function(j, data)
				{
					var match = phpVariable.exec(j);
					if(match[2])
					{
						var str = '['+e+']';

						if(match[1])
						{
							str += '['+match[1]+']';
						}

						str += ''+match[2]+'='+data;

						params.push(str);
					}
					else
					{
						params.push('['+e+']['+j+']='+data);
					}
				});
			});
		}

		jQuery.each(params,function(i)
		{

			region.find('[name='+prefix+i+']').val(this);
		});
	},

	flattenFields: function(data, prefix,depth)
	{
		if(!prefix)
		{
			prefix = '';
		}

		if(!depth)
		{
			depth = 1;
		}

		var returnFields = {};

		var additionalFields = {};

		if(jQuery.isArray(data) || typeof data == 'object')
		{
			jQuery.each(data,function(i, obj)
			{
				if(jQuery.isFunction(obj))
				{
					return true;
				}

				if(obj && ( jQuery.isArray(obj) || typeof obj  == 'object') )
				{
					if(depth > 0)
					{
						name = prefix + '[' + i + ']';
					}
					else
					{
						name = prefix + i;
					}

					jQuery.extend(additionalFields, Shout.flattenFields(obj,name,depth+1) );
				}
				else
				{
					if(depth > 0)
					{
						name = prefix + '[' + i + ']';
					}
					else
					{
						name = prefix + i;
					}

					returnFields[name] = obj;
				}
			});
		}
		else
		{
			return data;
		}

		jQuery.extend(returnFields,additionalFields);

		return returnFields;
	},

	phpSerialize: function(dataArray)
	{
	    var params = [];


		if(dataArray.length)
		{
			jQuery.each(dataArray, function(e,obj) {
				jQuery.each(obj, function(j, data)
				{
					var match = phpVariable.exec(j);
					if(match[2])
					{
						var str = 'actions['+e+']';

						if(match[1])
						{
							str += '['+match[1]+']';
						}

						str += ''+match[2]+'='+data;

						params.push(str);
					}
					else
					{
						params.push('actions['+e+']['+j+']='+data);
					}
				});
			});
		}

		return params.join('&');
	},

	drawInfoItem: function(content)
	{
		var list = [];
		if(jQuery.isArray(content))
		{
			jQuery.each(content,function()
			{
				list.push('<li class = "ui-state-info ui-corner-all"><span class = "ui-icon ui-icon-lightbulb"></span><span class="sui-content-text">'+this+'</span></li>');
			});
		}
		else
		{
			list.push('<li class = "ui-state-info ui-corner-all"><span class = "ui-icon ui-icon-lightbulb"></span><span class="sui-content-text">'+content+'</span></li>');
		}

		return jQuery(list.join(''));
	},

	drawInfo: function(content)
	{
		return jQuery('<div class = "sui-info"></div>').append(jQuery(this.drawInfoItem(content)).wrap('<ul></ul>'));
	},

	drawSummaryItem: function(content)
	{
		var list = [];
		if(jQuery.isArray(content))
		{
			jQuery.each(content,function()
			{
				list.push('<li><input readonly disabled class="sui-summary-content" value = "'+this+'"></span></li>');
			});
		}
		else
		{
			list.push('<li><input readonly disabled class="sui-summary-content" value = "'+content+'"></span></li>');
		}

		return jQuery(list.join(''));
	},

	drawErrorItem: function(content)
	{
		var list = [];
		if(jQuery.isArray(content))
		{
			jQuery.each(content,function()
			{
				list.push('<li class = "ui-state-error ui-corner-all"><span class = "ui-icon ui-icon-info"></span><span class="sui-content-text">'+this+'</span></li>');
			});
		}
		else
		{
			list.push('<li class = "ui-state-error ui-corner-all"><span class = "ui-icon ui-icon-info"></span><span class="sui-content-text">'+content+'</span></li>');
		}

		return jQuery(list.join(''));
	},

	pathToId: function(path)
	{
		var pathElements = path.split('/');

		return pathElements.join('-');
	},

	pathToName: function(path)
	{
		var pathElements = path.split('/');

		var elementString = '';

		jQuery.each(pathElements,function()
		{
			if(elementString.length == 0)
            {
				elementString = this;
            }
            else
            {
            	elementString += '['+this+']';
            }
		});

		return elementString;
	},

	parseCommonParams: function(params)
	{
		if(!params)
		{
			params = {};
			return params;
		}

		results = {};

		if(params.value)
        {
			results.value = "value = \""+params.value+"\"";
        }
        else
        {
        	results.value = "";
        }

        if(params.reset != undefined && params.reset == false)
        {
        	results.reset = "";
        }

        if(params.css)
        {
        	results.css = params.css;
        }
        else
        {
        	results.css = '';
        }

		if(params.type)
        {
			results.type = 'type = "'+params.type+'" ';
        }
        else
        {
        	results.type = '';
        }

	    if(params.style)
        {
	    	results.style = 'style = "'+params.style+'" ';
        }
        else
        {
        	results.style = '';
        }

	    if(params.multiple)
        {
	    	results.multiple = 'multiple';
        }
        else
        {
        	results.multiple = '';
        }

	    if(params.selected)
        {
	    	results.selected = 'selected';
        }
        else
        {
        	results.selected = '';
        }

	    if(params.checked)
        {
	    	results.checked = 'checked';
        }
        else
        {
        	results.checked = '';
        }

        if(params.icon)
        {
        	results.icon = '<span class = "sui-icon '+params.icon+'"></span>';
        }
        else
        {
        	results.icon = '';
        }


        if(params.href)
        {
            results.href = "href = \""+params.href+"\"";
        }

        if(params.target)
        {
        	results.target = "target = \""+params.target+"\"";
        }

        if(params.title)
        {
        	results.title = "title = \""+params.title+"\"";
        }

        return results;
	},

	drawButton: function(path, label, fieldIconClass, params)
	{
        var fieldId = this.pathToId(path);
        var fieldName = this.pathToName(path);

        var pp = this.parseCommonParams(params);

		if(params && params.type)
		{
            pp.type = 'hidden';
		}
		else if(params && params.type == 'submit')
		{
		    // Well, we could be using buttons but IE 7 renders them incorrectly,
            // depriving us of a semantically useful element.
            var hackScript   = 'onclick = "jQuery(this).next(\'input\').click();"';
            pp.type   = 'submit';
        }
        else
        {
            pp.type = 'hidden';
		}

		if(params && params.type == 'submit')
		{
		    pp.name = 'name = "'+fieldName+'"';
		}
		else
		{
		    pp.name = '';
		}

		if(params && params.click)
		{
		    jQuery('#'+fieldId).click(pp.click);
		}

        var HTML = '\
        <div class = "sui-control sui-control-button">\
            <a id = "'+fieldId+'" class = "ui-state-default ui-corner-all sui-button '+pp.css+'"\
            '+pp.style+'  '+pp.href+' '+pp.title+' '+pp.target+'>\
		';

        if(fieldIconClass.length)
        {
            HTML += '\
                <span class = "ui-icon '+fieldIconClass+'"></span>\
			';
        }

        if(label.length)
        {
            HTML += '\
                <span class = "sui-button-label">'+label+'</span>\
			';
        }

		HTML += '\
            </a>\
            <input type="'+pp.type+'" '+pp.name+' '+pp.value+' style = "display:none" />\
	    </div>';

    	return HTML;
	},

	addHeaderButton: function(element, icon, callback)
	{
		//jQuery(element).find('ui-dialog')
	},

	multiPaste: function(content, pasteElement, parentSelector, rowSelector, columnSelector)
	{
		var rowDelimeter = '\n';
		var columnDelimeter = '\t';

		var columnQuery = '.sui-form-field input[type!=hidden], .sui-form-field textarea';
		var rowQuery = '.sui-tree-node';
		var parentQuery = '.sui-tree-root ul > .sui-tree-node';

        var rows = content.split(rowDelimeter);

    	var resultObj = {};

    	jQuery.each(rows,function(i)
    	{
    		resultObj[i] = {};
    		resultObj[i] = this.split(columnDelimeter);
    	});

    	var rowIndex = 0;

    	var $parent = jQuery(parentSelector);

    	// In case we're not in the top right corner of a 2d array of input boxes, we offset the pasting from the cursor position.
    	var rowOffset = -1;
    	var columnOffset = -1;

    	$parent.find(rowSelector).each(function(index)
    	{
    		var $currentRow = jQuery(this);

    		if( ( columnOffset = $currentRow.find(columnSelector).index(pasteElement)  ) >= 0 )
    		{
    			rowOffset = index;

    			return false;
    		}

    	});

    	var $rows = null;

    	if(rowOffset != -1)
    	{
    		$rows = jQuery(parentSelector).find(rowSelector).slice(rowOffset);
    	}
    	else
    	{
    		$rows = jQuery(parentSelector).find(rowSelector);
    	}

    	$rows.each(function()
    	{
    		var columnIndex = 0;
    		var $columns = null;

    		if(columnOffset != -1)
    		{
    			$columns = jQuery(this).find(columnSelector).slice(columnOffset);
    		}
    		else
    		{
    			$columns = jQuery(this).find(columnSelector);
    		}

    		$columns.each(function()
    		{
    			if(!resultObj[rowIndex])
    			{
    				return false;
    			}
    			else if(resultObj[rowIndex] == 'undefined')
    			{
    				return false;
    			}

				jQuery(this).val(resultObj[rowIndex][columnIndex]);

				if(columnIndex > resultObj[rowIndex].length)
				{
					return false;
				}

				columnIndex++;
    		});

    		rowIndex++;
    	});
	},

	toggleCollapse: function($el)
	{
		var $el = jQuery($el);

		if($el.hasClass('sui-expanded'))
		{
			Shout.collapse($el);
			return false;
		}
		else if($el.hasClass('sui-collapsed'))
		{
			Shout.expand($el);
			return true;
		}
	},

	collapse: function($el)
	{
		var $el = jQuery($el);
		$el.removeClass('sui-expanded').addClass('sui-collapsed');
		$el.find(' > .sui-fieldset').hide();
		$el.find(' > .sui-toggle-icon').addClass('ui-icon-triangle-1-e').removeClass('ui-icon-triangle-1-se');

	},

	expand: function($el)
	{
		var $el = jQuery($el);
		$el.addClass('sui-expanded').removeClass('sui-collapsed');

		$el.find(' > .sui-fieldset').show();
		$el.find(' > .sui-toggle-icon').removeClass('ui-icon-triangle-1-e').addClass('ui-icon-triangle-1-se');
	}

});




})();

