(function() {

// Prevent re-initialization
if(typeof window.Shout != 'undefined')
{
	return;
}
// From jQuery.
// 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);
};

if(window.console === undefined)
{
	window.console = {
		log:function(){
			return true;
		},
		debug:function(){
			return true;
		},
		info:function(){
			return true;
		}
	};
}

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 class="ui-state-info ui-corner-all"><div class="sui-summary-content">'+this+'</div></li>');
            });
        }
        else
        {
            list.push('<li class="ui-state-info ui-corner-all"><div class="sui-summary-content">'+content+'</div></li>');
        }

        return jQuery(list.join(''));
    },
    
    showError: function(selector, content) {
    	var exists = false;
    	// If the error already exists, don't re-add it.
    	jQuery(selector).find('ul li .sui-content-text').each(function(){
    		if(jQuery(this).html() == content)
    		{
    			exists = true;
    			return false;
    		}
    	});
    	
    	if(exists) {
    		return;
    	}
    	
    	jQuery(selector).find('ul').append(Shout.drawErrorItem(content));
    },
    
    hideError: function(selector) {
    	jQuery(selector).find('ul').empty();
    },

    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-alert"></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-alert"></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 && 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');
    },

    showLoadIndicator: function($el)
    {
    	var offset = jQuery($el).offset();

    	var width = jQuery($el).outerWidth();
    	var height = jQuery($el).outerHeight();

    	if(!offset)
    	{
    		return;
    	}
    	var $indicator = jQuery('<div class="sui-load_indicator">');
    	$indicator.html('\
			<div class="sui-load_indicator-bar ui-progressbar-value ui-corner-all">Loading...</div>\
    	');

		$indicator.appendTo('body');
		$indicator.css({
			'position' : 'absolute',
			'top' : offset.top+'px',
			'left' : offset.left+'px',
			'width' : width+'px',
			'height' : height+'px',
			'z-index':5000
		});
		$indicator.show();

		return $indicator;
    },

    hideLoadIndicator: function($el)
    {
    	jQuery('.sui-load_indicator').remove();
    },

    tooltip: function($el, content, tip, corners )
    {
    	$el = jQuery($el);
    	var args = {
			content: {
				'text' : content
			},
			position:{
				corner: {
					tooltip: 'bottomleft',
					target: 'topright'
				},
				adjust: {
					'screen':true
				}
			},
			show: {
				delay: 0
			},
			hide: {
				delay: 200,
				fixed: true
			},
			style : {
				width:500,
				background: '#FFFFFF',
				tip: 'bottomright',
				border: {
					width: 7,
					radius: 5,
					color: '#B7BEC8'
				}
			}
    	};

    	if(corners)
    	{
    		args.position.corner = jQuery.extend(args.position.corner, corners);
    	}

    	if(tip)
    	{
    		args.style.tip = tip;
    	}

    	$el.qtip(args);
    },

    autoSlugify: function($titleField, $slugField)
    {
    	jQuery($titleField).keydown(function()
        {
            var currentTitle = jQuery(this).val();

            var safeTitle = Shout.transformToSlug(currentTitle);

            if( safeTitle == jQuery($slugField).val() )
            {
                jQuery($titleField).one('keyup',function()
                {
                    var currentTitle = jQuery(this).val();

                    var safeTitle = currentTitle.trim().replace(/[^a-zA-Z0-9-]+/gi,'-').replace(/-+/gi,'-').toLowerCase();

                    jQuery($slugField).val(safeTitle);
                });
            }
        });

        jQuery($slugField ).keydown(function()
        {
            var currentTitle = jQuery(this).val();
            jQuery(this).val(currentTitle.trim().replace(/[^a-zA-Z0-9-]+/gi,'-').replace(/-+/gi,'-'));
        });
    },

    transformToSlug: function(str)
    {
    	return str.trim().replace(/[^a-zA-Z0-9-]+/gi,'-').replace(/-+/gi,'-').toLowerCase();
    },

    /**
     * Used to construct a request for our RPC system.
     *
     * @param module the primary module
     * @param an optional secondary module. Should have a handleAction function.
     * @param params Additional parameters. These get flattened into a nested JSON object 'actionParams'.
     */
    buildRequest: function(module, submodule, mode, params)
    {
    	var searchObj = {
            'module' : module,
            'submodule' :submodule,
            'action': Shout.configuration.action,
            'mode' : mode
        };

    	return jQuery.extend(searchObj, Shout.flattenFields(params,'actionParams') );
    }

});

jQuery(document).ready(function(){
if(jQuery.fn.qtip){
	jQuery.fn.qtip.styles.shout = {
		width:'auto',
		background: '#FFFFFF',
		tip: 'bottomright',
		border: {
			width: 7,
			radius: 5,
			color: '#B7BEC8'
		}
	};
}
});

})();
