/* please shoot me now for creating all these globals */

var timeoutedMessage = null;
var timeoutId = null;
var visibleButtons = null;
var originalMsgBody = Array;
var lastScrollTime = new Date;
var animatedMessages = Array;
var waitingOnPost = false;
var postTrans = '';
var previewTrans = '';
var shoutWarned = false;
var typeChanged = Array;
var postSubmitSuccess = false;
var postFailedOnce = false;
var threadTitleEdit = false;
var refreshAreaList = false;

jQuery( document ).ready( function() {
    var msgId = document.location.hash.substring( 1 );
    if ( msgId != '' && !isNaN( msgId ) ) {
        if ( !jQuery( '#message_' + msgId ).length ) {
            jQuery.scrollTo( '.unloaded', 500, { easing: 'swing', offset: -20 } );
            if ( jQuery( '.loadsome' ).length ) {
                jQuery( '.loadsome' ).click();
            } else {
                jQuery( '.loadall' ).click();
            }
        }
    } else if ( msgId == 'split' && jQuery( '#titleeditform' ).length ) {
        showTitleEditField();
        jQuery( '#postbox-container' ).prepend( '<p style="padding:10px 20px;color:#fff;background-color:#cfdee5;"><u><b>Split Discussion:</b></u> You have just created this discussion by splitting a message from another discussion.<br />Please <b>(a) <u>post a reply</u></b> and <b>(b) <u>edit and save the title</u></b>.</p>' );
    }

	if ( !jQuery( '#addrecipient' ).size() ) {
        return;
    }

	jQuery( '#addrecipient' ).autocomplete( '/parts/users/contactsautocomplete', {
		extraParams : {
			'recipients': function() {
				return jQuery( '#receivers' ).val();
			}
		}
	}).result( function( event, data, formatted ) {
		addPMRecipient( data );
	});
});

function checkForNewMessages() {    
    if ( undefined !== window.checkingForNew && checkingForNew ) {
        return;
	}

	if ( !jQuery( '#messages_list .message:last' ).length ) {
		lastMessageId = 0;
	} else {
		lastMessageId = jQuery( '#messages_list .message:last' ).attr( 'id' ).substr( 8 );
	}

    checkingForNew = true;

    jQuery( '#toolbox .indicator' ).fadeIn( 3000 );
	setTimeout( 'timeoutNewMessagesCheck()', 20000 );
	
    jQuery.post(
        '/parts/forum/messages/loadnew',
        { 
            last_message_id: lastMessageId,
            thread_id: threadId
        },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                return;
            }

            if ( Result[1].length ) {
				// check see if the last new message is the same as the 
                // last one already on the page. don't show phantom
				// double posts!
				var alreadyThere = false;
				var lastOnPage = jQuery( '#messages_list .message:last' );
				jQuery( Result[1] ).each( function() {
					if ( lastOnPage.length && this.id == lastOnPage.attr( 'id' ) ) {
						alreadyThere = true;
					}
				} );

				if ( !alreadyThere ) {
                	jQuery( Result[1] ).appendTo( '#messages_list' ).slideDown();
                    jQuery( '#SLB-Wrapper' ).remove();
										// Re-Initialize Shadowbox in event of new links.
										Shadowbox.setup("a[rel^=shadowbox]", {
											gallery: "Attachments"
										});
                    
                    jQuery( '.markasread' )
                        .addClass( 'link' ).text( 'Mark as Read' )
                        .click( function() { 
                            markThreadRead( threadId, jQuery( '.markasread' ).get( 0 ) );
                        } );
				}
            }

            jQuery( '#toolbox .indicator' ).stop().fadeOut( 3000 );
            pollLock = false;

            if ( waitingOnPost ) {
                waitingOnPost = false;

                jQuery( '#previewsgohere .message.preview' ).slideUp();
                jQuery( '#postbody' ).attr( 'value', '' );
                jQuery( '#postbutton' ).val( postTrans ).blur();                
                jQuery( '#closednotice' ).slideUp();
            }
            
            checkingForNew = false;
        }
    );
}

function timeoutNewMessagesCheck() {
	if ( !checkingForNew ) {
		return;
	}

	jQuery( '#toolbox .indicator' ).stop().fadeOut( 3000 );
    pollLock = false;
	checkingForNew = false;
}

function doThreadSearch( val ){
	if( jQuery( '#searchscope.dynamic-search' ).length == 1 ) threadSearch.go( val, 1 );
	else jQuery( '#searchbox input[name=fa]' ).val( areaId );
}

var threadSearch = {
    normalView: null,
    showingSearch: false,
    order: 0,
    lastReceived: 0,
    requests: [],
    lastToken: '',
    lastPage: 1,
    lastStateId: null,
    clickedButton: null,
    oldButtonText: '',
    visibleMessagesThreadId: null,
    go: function ( token, page, evt, stateId ) {
        if ( undefined === window.areaId ) {
            return;
        }
        
		if ( 
            token == threadSearch.lastToken && 
            page == threadSearch.lastPage && 
            stateId == threadSearch.lastStateId
        ) return;
        
		if( isNaN( token.length ) || token.length < 2 ) return;
		
        threadSearch.lastToken = token;
        threadSearch.lastPage = page;
        threadSearch.lastStateId = stateId;

        if ( viewType == 'tasks' ) {
            var Container = jQuery( '#tasks' );
            threadSearch.queryUrl = '/parts/forum/threads/taskssearch';
            jQuery( '#toolbox' ).fadeOut();
        } else {
            var Container = jQuery( '#headingsandthreads' );
            threadSearch.queryUrl = '/parts/forum/threads/search';
        }

        // abort all previous search requests
        for ( i = 0; threadSearch.requests[i]; i++ ) {
            threadSearch.requests[i].abort();
        }
        
        // if empty search field, restore the normal threads view
        if ( !token.length ) {
            jQuery( '#searchresults' ).fadeOut( 'normal', function() {
                threadSearch.showingSearch = false;
                Container.append( threadSearch.normalView ).fadeIn();
                threadSearch.normalView = null;
                jQuery( '#threads_pagination' ).fadeIn();
                jQuery( '#searchresults .threads' ).empty();
                jQuery( '#searchresults .pages' ).empty();
            } );
            jQuery( '#toolbox' ).fadeIn();
            return;
        }
        
        // hide normal thread view, replace with search results view
        if ( !threadSearch.showingSearch ) {
            jQuery( '#threads_pagination' ).fadeOut();
            Container.fadeOut( 'normal', function() {
                threadSearch.showingSearch = true;
                if ( threadSearch.normalView == null ) {
                    threadSearch.normalView = Container.children().remove();
                }
                jQuery( '#searchresults h1' ).html( 'Search Results Loading...' );
                jQuery( '#searchresults' ).fadeIn();
                jQuery( '#searchresults .threads' ).fadeTo( 'normal', 0.5 );
            } );
        } else {
            jQuery( '#searchresults .threads' ).fadeTo( 'normal', 0.5 );
        }
        
        if ( typeof page != 'number' ) {
            page = parseInt( jQuery( page ).attr( 'href' ).substr( 8 ) );
            evt.preventDefault();
        }

        threadSearch.requests[threadSearch.order] = jQuery.post( 
            threadSearch.queryUrl, { 
                area_id: areaId, view: viewType, token: token, 
                order: threadSearch.order, page: page, state_id: stateId 
            }, function( responseText ) {
                Result = eval( responseText );

                // ignore late search results
                if ( parseInt( Result[1] ) < threadSearch.lastReceived ) {
                    return;
                }
                threadSearch.lastReceived = parseInt( Result[1] );
               
                // abort any still running earlier searches
                for ( i = 0; i < Result[1]; i++ ) {
                    threadSearch.requests[i].abort();
                }

                jQuery( '#searchresults h1' ).html( 'Search Results for "' + token + '"' );
                jQuery( '#searchresults .threads' ).html( Result[3] );
                jQuery( '#searchresults .pages' ).html( Result[2] );
                jQuery( '#searchresults .threads' ).fadeTo( 'normal', 1 );

                threadSearch.fillCounts( token, page, threadSearch.order, stateId );
            }
        );

        threadSearch.order++;
    },

    fillCounts: function( token, page, order, stateId ) {
        threadSearch.requests[threadSearch.order] = jQuery.post( 
            threadSearch.queryUrl, { 
                area_id: areaId, view: viewType, token: token, 
                order: order, page: page, counts: 1, state_id: stateId
            }, function( responseText ) {
                Result = eval( responseText );

                jQuery( '#searchresults .threads' ).html( Result[3] );
                jQuery( '#searchresults .pages' ).html( Result[2] );
                jQuery( '#searchresults .threads' ).fadeTo( 'normal', 1 );
            }
        );
    },

    showMsgMatches: function( threadId, token, button, author ) {

        // if same button pressed close messages list 
        // and bring all threads back to 1 opacity
        if ( 
            threadSearch.visibleMessagesThreadId != null && 
            threadId == threadSearch.visibleMessagesThreadId 
        ) {
            jQuery( '.messages_list' ).slideUp( 150, function() {
                jQuery( '.messages_list' ).remove();
                jQuery( threadSearch.clickedButton ).html( threadSearch.oldButtonText );
                jQuery( '.thread' ).removeClass( 'showingmatches' ).fadeTo( 'fast', 1 );
                threadSearch.visibleMessagesThreadId = null;
                threadSearch.clickedButton = null;
                threadSearch.oldButtonText = '';
            } );
            return;
        }

        if ( threadSearch.clickedButton ) {
            jQuery( threadSearch.clickedButton ).html( threadSearch.oldButtonText );
        }
        

        jQuery( '.messages_list' ).slideUp( 150, function() {
            jQuery( '.messages_list' ).remove();
            jQuery.scrollTo( '#thread_' + threadId, 200, 
                { easing: 'swing', offset: -20 } );
        } );
        
        threadSearch.visibleMessagesThreadId = threadId;
        threadSearch.clickedButton = button;
        threadSearch.oldButtonText = jQuery( button ).html();
        jQuery( button ).html( 'loading...' );

        jQuery( '.thread' ).removeClass( 'showingmatches' );
        jQuery( '#thread_' + threadId ).addClass( 'showingmatches' )
            .fadeTo( 'fast', 1 );
        jQuery( '.thread:not(.showingmatches)' ).fadeTo( 'fast', 0.5 );

        jQuery.post( 
            '/parts/forum/messages/search',
            { area_id: areaId, thread_id: threadId, token: token, author: author },
            function( responseText ) {
                Result = eval( responseText );
                
                jQuery( button ).html( Result[2] + ' of ' + Result[3] + ' matches' );
                jQuery( '#thread_' + threadId ).after( Result[1] );
                jQuery( '.messages_list' ).slideDown( 'fast' );
            }
        );
    }
}

function updateAreaLists() {
	// DON'T refresh the lists immediately after the page has loaded
	// Cos they're already current. Duh.
	if( refreshAreaList ){
		jQuery.post( '/parts/forum/areas/getlist', { group: 'all' }, function( responseText ) { 
			Result = eval( responseText );
            for( i = 0; i < Result[1].length; i++ ){ 
	            jQuery( Result[1][i] ).find( '.area' ).each( function() {
	                var areaId = this.id.substr( 5 );
	                var newCounts = jQuery( this ).find( '.counts' ).text();
	                var oldCounts = jQuery( '#area_' + areaId + ' .counts' ).text();
                
	                if ( newCounts == oldCounts ) {
	                    return true;
	                }
                
	                var Area = jQuery( '#area_' + areaId );
	                var Counts = jQuery( '#area_' + areaId + ' .counts' );
	                var Desc = jQuery( '#area_' + areaId + ' .description' );
                
	                Counts.fadeOut( 150, function() { 
	                    Counts.text( newCounts ).fadeIn( 150 );
	                } );
                
	                var newNew = newCounts.search( 'new' );
	                var oldNew = oldCounts.search( 'new' );

	                if ( newNew == oldNew ) {
	                    return true;
	                }

	                if ( newNew > -1 ) {
	                    if ( site == 'serato' ) {
	                        Area.css( 'backgroundColor', '#fff' ).animate( 
	                            { backgroundColor: '#cfdee5', borderBottomColor: '#bbb' }, 
	                            { queue: false, duration: 300 }
	                        );
	                        Desc.animate( { color: '#000' }, { queue: false, duration: 300 } );
	                        Counts.animate( 
	                            { color: '#000', backgroundColor: '#cfdee5' }, 
	                            { queue: false, duration: 300 } 
	                        );
	                    } else if ( site == 'whitelabel' ) {
	                        Area.css( 'backgroundColor', '#fff' ).animate( 
	                            { 
	                                color: '#444', backgroundColor: '#eee',
	                                borderTopColor: '#ddd', borderRightColor: '#ddd',
	                                borderBottomColor: '#ddd', borderLeftColor: '#ddd',
	                                '-moz-border-radius-bottomleft': '6px',
	                                '-moz-border-radius-topright': '6px',
	                                '-webkit-border-bottom-left-radius': '6px',
	                                '-webkit-border-top-right-radius': '6px'
	                            }, { queue: false, duration: 300 }
	                        );
	                        Counts.animate( { backgroundColor: '#eee' }, 
	                            { queue: false, duration: 300 } );
	                    } else {
	                        Area.css( 'backgroundColor', '#fff' ).animate( 
	                            { backgroundColor: '#cfdee5', borderBottomColor: '#bbb' }, 
	                            { queue: false, duration: 300 }
	                        );
	                        Counts.animate( { backgroundColor: '#cfdee5' }, 
	                            { queue: false, duration: 300 } );
	                    }
	                } else {
	                    Area.animate( 
	                        { backgroundColor: '#fff', borderBottomColor: '#bbb' }, 
	                        { queue: false, duration: 300 }
	                    );
	                    Counts.animate( { backgroundColor: '#fff' }, 
	                        { queue: false, duration: 300 } );
	                    if ( site == 'serato' ) {
	                        Desc.animate( { color: '#666' }, { queue: false, duration: 300 } );
	                        Counts.animate( { color: '#666' }, { queue: false, duration: 300 } );
	                    }
	                    if ( site == 'whitelabel' ) {
	                        Desc.animate( { color: '#525252' }, { queue: false, duration: 300 } );
	                        Counts.animate( { color: '#525252' }, 
	                            { queue: false, duration: 300 } );
	                        Area.animate( 
	                            { 
	                                borderTopColor: '#fff', borderLeftColor: '#fff',
	                                borderRightColor: '#fff', borderBottomColor: '#eee',
	                                '-moz-border-radius-bottomleft': '0px',
	                                '-moz-border-radius-topright': '0px',
	                                '-webkit-border-bottom-left-radius': '0px',
	                                '-webkit-border-top-right-radius': '0px'
	                            }, { queue: false, duration: 300 } 
	                        );
	                    }
	                }
	            } );
			}
		} );
	}
	refreshAreaList = true;
}

function updateThreadsList() {
	if ( threadSearch.showingSearch ) {
		return;
	}
	
	if ( jQuery( '#sticky_threads' ).length ) {
		updateThreads( 'sticky_threads' );
	}
	updateThreads( viewType );
   
	function updateThreads( type ) {
		jQuery.post(
			'/parts/forum/threads/updatedlist', 
			{ area_id: areaId, type: type },
			function( updatedList ) {
				var UpdatedThreads = jQuery( updatedList );
				
				// scan updated list for new threads
				var newThreads = 0;
				UpdatedThreads.find( '.thread' ).each( function() {
					if ( !jQuery( '#' + this.id ).length ) {
						newThreads++;
					}
				} );
				if ( newThreads ) {
					if ( newThreads == 1 ) {
						newThreads += ' new discussion';
					} else {
						newThreads += ' new discussions';
					}
					jQuery( '.list_updated.' + type ).text( newThreads ).fadeIn();
					return;
				}

				// fix the thread list heights to avoid slight page height 
				// jitter when threads move
				jQuery( '#' + type + ' .threads_list' )
					.css( 'height', jQuery( '#' + type + ' .threads_list' ).height() );
				
				// step through updated list and move/update
				UpdatedThreads.find( '.thread' ).each( function( i ) {
					var NewThread = jQuery( this );
					var OldThread = jQuery( '#' + NewThread.attr( 'id' ) );
					var newCounts = NewThread.find( '.counts' ).html();
					var oldCounts = OldThread.find( '.counts' ).html();

					if ( newCounts != oldCounts ) {
						updateCountAndColour( 
							NewThread, OldThread, newCounts, oldCounts, i + 1 );
					}
				} );
			} 
		);

		function updateCountAndColour( NewThread, OldThread, newCounts, oldCounts, newOrder ) {
			var Counts = OldThread.find( '.counts' );
			var Starter = OldThread.find( '.starter' );

			var classes = OldThread.attr( 'class' ).split( ' ' );
			for ( j = 0; classes[j]; j++ ) {
				if ( classes[j].search( 'pos' ) != -1 ) {
					var oldOrder = classes[j].substr( 3 );
					break;
				}
			}

			Counts.fadeOut( 150, function() { 
				Counts.html( newCounts ).fadeIn( 150, function() {
					if ( newOrder != oldOrder ) {
						move( NewThread, OldThread, newOrder, oldOrder, type );
					}
				} );
			} );

			var newNew = newCounts.search( 'new' );
			var oldNew = oldCounts.search( 'new' );
			
			if ( newNew == oldNew ) {
				return true;
			}

			if ( newNew > -1 ) {		   
				var threadId = OldThread.attr( 'id' ).substr( 7 );
				var threadURL = OldThread.find( 'a' ).attr( 'href' );
				if( threadURL.indexOf('#new') == -1 ) {
					threadURL += '#new';
				}

				OldThread.find( 'a' )
					.attr( 'href', threadURL )
					.bind( 'click', function() {
						fadeThread( threadId );
					} );
				
				if ( site == 'serato' ) {
					OldThread.css( 'backgroundColor', '#cfdee5' ).animate( 
						{ backgroundColor: '#cfdee5', borderBottomColor: '#bbb' }, 
						{ queue: false, duration: 300 }
					);
					Starter.animate( { 'color': '#666' }, 
						{ queue: false, duration: 300 } );
					Counts.animate( { color: '#666' }, 
						{ queue: false, duration: 300 } );
				} else if ( site == 'whitelabel' ) {
					OldThread.css( 'backgroundColor', '#fff' ).animate( 
						{ 
							'color': '#444', 'backgroundColor': '#eee',
							'borderTopColor': '#ddd', 'borderRightColor': '#ddd',
							'borderBottomColor': '#ddd', 'borderLeftColor': '#ddd',
							'-moz-border-radius-bottomleft': '6px',
							'-moz-border-radius-topright': '6px',
							'-webkit-border-bottom-left-radius': '6px',
							'-webkit-border-top-right-radius': '6px'
						}, { queue: false, duration: 300 }
					);
				} else {
					OldThread.css( 'backgroundColor', '#fff' ).animate( 
						{ backgroundColor: '#cfdee5', borderBottomColor: '#bbb' }, 
						{ queue: false, duration: 300 }
					);
				}
			} else {
				if ( site == 'whitelabel' ) {
				   OldThread.animate( 
						{ 
							borderTopColor: '#fff', borderLeftColor: '#fff',
							borderRightColor: '#fff', borderBottomColor: '#eee',
							color: '#525252', backgroundColor: '#fff',
							'-moz-border-radius-bottomleft': '0px',
							'-moz-border-radius-topright': '0px',
							'-webkit-border-bottom-left-radius': '0px',
							'-webkit-border-top-right-radius': '0px'
						}, 
						{ queue: false, duration: 300 }
					);
				} else {
					OldThread.animate( 
						{ backgroundColor: '#fff', borderBottomColor: '#bbb' }, 
						{ queue: false, duration: 300 }
					);
				}
				OldThread.find( '.prefix' ).hide();
				if ( site == 'serato' ) {
					Starter.animate( { color: '#666' }, 
						{ queue: false, duration: 300 } );
					Counts.animate( { color: '#666' }, 
						{ queue: false, duration: 300 } );
				}
			}
		}

		function move( NewThread, OldThread, newOrder, oldOrder, listType ) {
			var oldPos = OldThread.position();
			var newPos = jQuery( '#' + listType + ' .pos' + newOrder ).position();
			var FinalThread = OldThread.clone( true )
				.insertBefore( '#' + listType + ' .pos' + newOrder );
			OldThread.attr( 'id', '' );
			var MovingThread = OldThread.clone();

			// renumber the threads list
			jQuery( '#' + listType + ' .thread' ).each( function( i ) {
				var newPosClass = 'pos' + ( i + 1 );
				var classes = jQuery( this ).attr( 'class' ).split( ' ' );
				for ( j = 0; classes[j]; j++ ) {
					if ( classes[j].search( 'pos' ) != -1 ) {
						var oldPosClass = classes[j];
						break;
					}
				}
				jQuery( this ).removeClass( oldPosClass ).addClass( newPosClass );
			} );

			// slide the moving clone from old position to new
			MovingThread.attr( 'id', '' ).appendTo( '#' + listType + ' .threads_list' )
				.css( { 
					position: 'absolute', top: oldPos.top + 'px', 
					width: OldThread.css( 'width' ) 
				} )
				.animate( { top: newPos.top + 'px' }, { queue: false, duration: 300 } );

			// shrink the original thread then remove it
			OldThread.css( 'opacity', 0 )
				.animate( { height: 0, paddingTop: 0, paddingBottom: 0, marginBottom: 0 },
					{ queue: false, duration: 300 } );
			
			// expand final to final size, remove old and animated mover
			FinalThread.css( { 
					opacity: 0, height: 0, paddingTop: 0, 
					paddingBottom: 0, marginBottom: 0 
				} ).animate( {
					height: '20px', paddingTop: '5px', 
					paddingBottom: '5px', marginBottom: '0px' 
				}, { queue: false, duration: 300, complete: function() {
					OldThread.remove();
					MovingThread.remove();
					FinalThread.css( 'opacity', 1 );
				} } 
			);
		}
	}
}

function quickThreadsListUpdate( type ) {
	var ThreadsList = jQuery( '#' + type + ' .threads_list' );
	ThreadsList.fadeTo( 300, 0.8 );
	jQuery( '.list_updated.' + type ).fadeTo( 300, 0.4 )
		.css( 'cursor', 'default' ).unbind( 'click' );
	jQuery.post(
		'/parts/forum/threads/updatedlist', 
		{ area_id: areaId, type: type },
		function( updatedList ) {
			var UpdatedThreads = jQuery( updatedList );
			ThreadsList.fadeTo( 600, 0.1, function() {
				ThreadsList.replaceWith( updatedList );
				jQuery( '#' + type + ' .threads_list' )
					.css( 'opacity', 0.1 ).fadeTo( 600, 1 );
				jQuery( '.list_updated.' + type ).fadeOut( 1000 );
			} );
		}
	);
}

function loadMissingMessages( after, before, allRemaining ) {
	if ( allRemaining ) {
		jQuery( '.unloaded span.loadall' ).text( 'Loading...' );
		jQuery( '.unloaded span.loadsome' ).slideUp( 'fast' );
	} else {
		jQuery( '.unloaded span.loadsome' ).text( 'Loading...' );
		jQuery( '.unloaded span.loadall' ).slideUp( 'fast' );
	}
	
	jQuery( '.unloaded span' )
		.removeClass( 'link' )
		.attr( 'onclick', '' )
		.unbind( 'click' );

	allRemaining = ( allRemaining ) ? 'yes' : 'no';
	
	var msgId = document.location.hash.substring( 1 );
	if ( msgId != '' && !isNaN( msgId ) && !jQuery( '#message_' + msgId ).length ) {
		var mustShow = msgId;
	} else {
		var mustShow = '';
	}

	jQuery.post(
		'/parts/forum/threads/loadfragment',
		{ 
			thread_id: threadId, after_id: after, before_id: before, 
			all_remaining: allRemaining, must_show: mustShow
		},
		function( responseText ) { 
			Result = eval( responseText );

			if ( Result[0] != 'success' ) {
				alert( 'Error: ' + Result[0] );
				return;
			}

			jQuery( '.unloaded' ).slideUp().replaceWith( 
				'<div id="loadedfrom_' + after + '" style="display:none">' +
				Result[1] + '</div>'
			);
			jQuery( '#loadedfrom_' + after ).slideDown( 'normal', function() {
				if ( mustShow ) {
					jQuery.scrollTo( '#message_' + mustShow, 500, 
						{ easing: 'swing', offset: -20 } );
				}
			} );
								
		}
	);

}

function showButtons( messageId ) {
    if ( visibleButtons == messageId ) {
        return;
    }

    if ( timeoutedMessage != messageId ) {
        clearTimeout( timeoutId );
        timeoutId = setTimeout( 'reallyShowButtons(' + messageId + ')', 150 );
        timeoutedMessage = messageId;
    }
}

function reallyShowButtons( messageId ) {
	jQuery( '#message_' + visibleButtons + ' .buttons' )
        .not( '.buttons.alwaysvisible' ).fadeOut( 200 );
    jQuery( '#message_' + visibleButtons + ' .buttons.alwaysvisible .forusers .button' )
        .not( '.button.alwaysvisible' ).hide();
    jQuery( '#message_' + visibleButtons + ' .buttons.alwaysvisible .formods .button' )
        .not( '.button.alwaysvisible' ).hide();
    jQuery( '#message_' + visibleButtons + ' .buttons.alwaysvisible .editing .button' )
        .not( '.button.alwaysvisible' ).hide();
    jQuery( '#message_' + visibleButtons + ' .buttons.alwaysvisible .typeswitch .button' )
        .not( '.button.alwaysvisible' ).hide();


    var buttons = jQuery( '#message_' + messageId + ' .buttons' );
	if ( buttons.css( 'display' ) == 'none' ) {
		buttons.fadeIn( 500 );
	} else {
    	buttons.stop().fadeTo( 500, 1 );
	}
    jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .forusers .button' ).show();
    jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .formods .button' )
        .not( '.edit.disabled' ).show();

    if ( jQuery( '#message_' + messageId + ' .edit.disabled' ).length ) {
        jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .editing .button' ).show();
        jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .typeswitch .button' )
            .show();
    }

    visibleButtons = messageId;
}

function showTitleEditButton() {
    if ( jQuery( '#titleeditbutton' ).css( 'display' ) != 'block' ) {
        jQuery( '#titleeditbutton' ).fadeIn( 'fast' );
    }
}

function hideTitleEditButton() {
    if ( jQuery( '#titleeditbutton' ).css( 'display' ) == 'block' ) {
        jQuery( '#titleeditbutton' ).fadeOut( 'fast' );
    }
}

function showTitleEditField() {
    hideTitleEditButton();
	threadTitleEdit = jQuery( '#titleeditform input' ).val();
    jQuery( '#threadtitle' ).fadeOut( 'fast', function() {
        jQuery( '#titleeditform' ).fadeIn( 'fast' );
        jQuery( '#savecancelbuttons' ).fadeIn( 'fast' );
    } );
}

function cancelTitleEdit() {
    if ( jQuery( '#savecancelbuttons .cancel' ).hasClass( 'disabled' ) ) {
        return;
    }
    jQuery( '#titleeditform input' ).val( threadTitleEdit );
    jQuery( '#titleeditform' ).fadeOut( 'fast', function() {
        jQuery( '#threadtitle' ).fadeIn( 'fast' );
    } );
    jQuery( '#savecancelbuttons' ).fadeOut( 'fast', function() {
        showTitleEditButton();
    } );
}

function saveTitleEdit( threadId ) {
    if ( jQuery( '#savecancelbuttons .save' ).hasClass( 'disabled' ) ) {
        return;
    }

    jQuery( '#savecancelbuttons .save' ).addClass( 'disabled' )
        .text( 'saving...' );
    jQuery( '#savecancelbuttons .cancel' ).addClass( 'disabled' );

    jQuery.post(
        '/parts/forum/threads/edittitle',
        { 
            thread_id: threadId, 
            title: jQuery( '#titleeditform input' ).val()
        },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
			threadTitleEdit = Result[1];
            jQuery( '#threadtitle' ).text( Result[1] );
            jQuery( '#savecancelbuttons .cancel' ).removeClass( 'disabled' );
            jQuery( '#savecancelbuttons .save' ).text( 'Save' ).removeClass( 'disabled' );
            cancelTitleEdit();
        }
    );
}

function isFormFilled( newThread, pm ) {
    var postButtons = jQuery( '#postbuttons input' );
    var complete = false;
    if ( newThread && pm ) {
        complete = ( 
            jQuery( '#postbody' ).val() && 
            jQuery( '#subject' ).val() && 
            jQuery( '#receivers' ).val().length
        );
    } else if ( newThread ) {
        complete = ( jQuery( '#postbody' ).val() && jQuery( '#subject' ).val() );
    } else {
        complete = ( jQuery( '#postbody' ).val() );
    }
        
    postButtons.attr( 'disabled', !complete );
}

function shouting() {
    var body = jQuery( '#postbody' ).val();
    var matches = body.match( /[A-Z]{2,}/g );
    var caps = '';
    
    if ( !matches ) {
        return false;
    }

    for ( i = 0; matches[i]; i++ ) {
        caps += matches[i];
    }

    if ( !caps.length ) {
        return false;
    }

    var matches = body.match( /[a-zA-Z]*/g );
    var allAlpha = '';
    for ( i = 0; matches.length > i; i++ ) {
        allAlpha += matches[i];
    }
    
    return ( caps.length / allAlpha.length ) > 0.5;
}

function previewMessage() {
    if ( shouting() ) {
        jQuery( '#shouting' ).slideDown();
        jQuery( '#shouting .please' ).show();
        if ( !shoutWarned ) {
            shoutWarned = true;
            return;
        }
    } else {
        if ( jQuery( '#shouting' ).css( 'display' ) != 'none' ) {
            jQuery( '#shouting' ).slideUp();
            jQuery( '#shouting .please' ).hide();
            shoutWarned = false;
        }
    }

	// Maybe someone has been *fiddling* with the [quote] and [/quote] tags.
	// Better make sure that we have the same number of each. Otherwise, chaos may ensue.

	var msgBody = jQuery( '#postbody' ).val();
    opening_quote_count = 0;
    closing_quote_count = 0;
	matches = msgBody.match( /\[quote\]/gi );
    if( matches ) opening_quote_count = matches.length;
	matches = msgBody.match( /\[\/quote\]/gi );
    if( matches ) closing_quote_count = matches.length;
	if( opening_quote_count != closing_quote_count ){
		// So, um, now what?
		// I guess we just have to patch things up as best as possible
		if( opening_quote_count > closing_quote_count ){
			// Append additional [/quote] tags to the end of the string
			for( i = 0; i < ( opening_quote_count - closing_quote_count ); i++) msgBody += "\n[/quote]";
		}
		else{
			// Append additional [/quote] tags to the end of the string
			for( i = 0; i < ( closing_quote_count - opening_quote_count ); i++) msgBody = "[quote]\n" + msgBody;
		}
		jQuery( '#postbody' ).val( msgBody );
	}
	
    jQuery( '#postform' ).attr( 'action', '/parts/forum/messages/preview' );
    jQuery( '#postform' ).get( 0 ).submit();
    jQuery( '#postbuttons input' ).attr( 'disabled', true );
    previewTrans = jQuery( '#previewbutton' ).val();
    jQuery( '#previewbutton' ).val( 'loading...' );

    checkForNewMessages();
}

function postMessage() {
    if ( shouting() ) {
        jQuery( '#shouting' ).slideDown();
        if ( !shoutWarned ) {
            jQuery( '#shouting .please' ).show();
            shoutWarned = true;
            return;
        } else {
            jQuery( '#shouting .please' ).hide();
        }
    } else {
        if ( jQuery( '#shouting' ).css( 'display' ) != 'none' ) {
            jQuery( '#shouting' ).slideUp();
            jQuery( '#shouting .please' ).hide();
            shoutWarned = false;
        }
    }
    
    jQuery( '#postform' ).attr( 'action', '/parts/forum/messages/post' );
    jQuery( '#postform' ).get( 0 ).submit();
    jQuery( '#postbuttons input' ).attr( 'disabled', true );
    postTrans = jQuery( '#postbutton' ).val();
    jQuery( '#postbutton' ).val( 'posting...' );

	setTimeout( 'checkIfPostingFailed()', 21000 );
}

function checkIfPostingFailed() {
	if ( postSubmitSuccess ) {
		postSubmitSuccess = false;
		postFailedOnce = false;
		return;
	}
	
	if ( postFailedOnce ) {
		jQuery( '#postingfailed' ).slideDown();
		jQuery( '#postbutton' ).val( postTrans ).blur();
 		isFormFilled();
		postFailedOnce = false;
		return;
	}

	if ( jQuery( '#postbody' ).val().length ) {
    	jQuery( '#postform' ).get( 0 ).submit();
		postFailedOnce = true;
		setTimeout( 'checkIfPostingFailed()', 21000 );
	}
}

function previewThread() {
    jQuery( '#postform' ).attr( 'action', '/parts/forum/threads/preview' );
    jQuery( '#postform' ).get( 0 ).submit();
    jQuery( '#postbuttons input' ).attr( 'disabled', true );
    previewTrans = jQuery( '#previewbutton' ).val();
    jQuery( '#previewbutton' ).val( 'loading...' );
}

function createThread( privateDiscussion ) {
    if ( privateDiscussion ) {
        jQuery( '#postform' ).attr( 'action', '/parts/forum/threads/private/create' );
    } else {
        jQuery( '#postform' ).attr( 'action', '/parts/forum/threads/create' );
    }
    jQuery( '#postform' ).get( 0 ).submit();
    jQuery( '#postbuttons input' ).attr( 'disabled', true );
    postTrans = jQuery( '#postbutton' ).val();
    jQuery( '#postbutton' ).val( 'posting...' );
}

function showPreview( message ) {
	jQuery( '#previewsgohere .message.preview' ).slideUp();
    jQuery( '#previewsgohere' ).append( message );
    jQuery( '.message.preview' )
        .eq( jQuery( '#previewsgohere .message.preview' ).length - 1 )
        .slideDown( "fast" );
    jQuery( '#postbuttons input' ).attr( 'disabled', false );
    jQuery( '#previewbutton' ).val( previewTrans );
}

function showThreadPreview( threadPreview ) {
    jQuery( '#threadpreviewsgohere .thread_preview' ).slideUp();
    jQuery( '#threadpreviewsgohere' ).append( threadPreview );
    jQuery( '#threadpreviewsgohere .thread_preview' )
        .eq( jQuery( '#threadpreviewsgohere .thread_preview' ).length - 1 )
        .slideDown();
    jQuery( '#postbuttons input' ).attr( 'disabled', false );
    jQuery( '#previewbutton' ).val( previewTrans );
    jQuery( '#postbutton' ).show();
}

function gotoNewThread( threadId ) {
    window.location = '/forum/discussion/' + threadId;
}

function showPost( results ) {
	postSubmitSuccess = true;

    if ( results[0] != 'success' ) {
        switch( results[0] ) {
            case 'repost':
                if ( !postFailedOnce ) {
                    alert( 'You have already posted this!' );
                }
                break;  
            case 'banned':
                alert( 'You no longer have permission to post messages.' );
                return;
            case 'locked':
                alert( 'This discussion is now locked. No new messages can be posted.' );
                break;
            case 'closed':
                alert( 'This discussion has been closed. If you are having related problems create a new help request.' );
                break;
            case 'in testing':
                alert( 'We believe we have fixed this bug in the version mentioned, and it now requires verification. Please download the version mentioned, or a later version, and let us know if it has been fixed' );
                break;
            default:
                alert( 'Error: ' + results[0] );
                break;
        }
        waitingOnPost = false;
        jQuery( '#postbutton' ).val( postTrans ).blur();
        isFormFilled();
        return;
    }

	if ( results[2] == 'tracked' ) {
            jQuery( '#tracklink' )
                .addClass( 'link' )
                .text( 'Stop Tracking This Discussion' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    untrackThread( threadId);
                } );
	}

    waitingOnPost = true;
    checkForNewMessages();
}

function messageType( type ) {
    jQuery( '.typebutton' ).removeClass( 'selected' );
    jQuery( '#postbody' ).attr( 'className', '' );
    switch( type ) {
        case 'internal':
            jQuery( '#internalmsgbutton' ).addClass( 'selected' );
            jQuery( '#postbody' ).attr( 'className', 'internalmsg' );
            jQuery( '#msgtype' ).val( 'internal' );
            jQuery( '#message_type_description' ).css( 'display', 'inline-block' ).fadeIn('slow');
            break;
        case 'normal':
            jQuery( '#normalmsgbutton' ).addClass( 'selected' );
            jQuery( '#msgtype' ).val( 'normal' );
            jQuery( '#message_type_description' ).css( 'display', 'none' ).fadeOut('slow');
            break;
    }
}

function quoteMessage( messageId ) {
    var selText = '';
    if ( window.getSelection ) {
        var sel = window.getSelection();
        if ( sel.rangeCount > 0 && window.XMLSerializer ) {
            var From = jQuery( sel.getRangeAt( 0 ).commonAncestorContainer );
            if ( From.closest( '.body' ).length ) {
                selText = new XMLSerializer().serializeToString(
                    sel.getRangeAt( 0 ).cloneContents() );
            }
        }
    }

    if ( selText.length ) {
        var msgBody = convertMessageBody( selText );
    } else {
        var msgBody = convertMessageBody( 
            jQuery( '#message_' + messageId + ' .body' ).html() );
    }
    
    jQuery( '#postbody' ).val( jQuery( '#postbody' ).val() 
        + '[quote]' + msgBody + '[/quote]\n' );
    jQuery.scrollTo( '#postbody', 500, { easing: 'swing' } );
    jQuery( '#postbody' ).focus();
}

function addToPM() {
    if ( jQuery( '#addtopm .button' ).hasClass( 'disabled' ) ) {
        return;
    }
   
    jQuery( '#addtopm .button' ).addClass( 'disabled' );
    jQuery( '#addtopmdialogue' ).fadeIn();
	jQuery( '#groupSelect').val( 'None' );
	jQuery( '#searchFor' ).val( '' );
}

function cancelAddToPM() {
    jQuery( '#addtopmdialogue' ).fadeOut( 'fast' );
    jQuery( '#addtopmresults' ).fadeOut( 'fast' );
    jQuery( '#addtopm .button' ).removeClass( 'disabled' );

}

function addThisPersonToPM( userId ) {
    jQuery( '#memberslist' ).animate( { 'opacity': 0.5 } );

    jQuery.post(
        '/parts/forum/threads/addtopm',
        { 
            user_id: userId, thread_id: threadId 
        },
        function( responseText ) { 
			Result = eval( responseText );
            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }

            jQuery( '#memberslist' ).html( Result[1] ).animate( { 'opacity': 1 } );
        }
    );
}

function removeFromPM( userId ) {
    jQuery( '#memberslist' ).animate( { 'opacity': 0.5 } );

    jQuery.post(
        '/parts/forum/threads/removefrompm',
        { 
            user_id: userId, thread_id: threadId 
        },
        function( responseText ) { 
			Result = eval( responseText );
            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }

            jQuery( '#memberslist' ).html( Result[1] ).animate( { 'opacity': 1 } );
        }
    );
}

function searchForUsers() {
	
    var resultsBox = jQuery( '#addtopmresults' );
    var resultsBoxInner = jQuery( '#addtopmresults .results' );

	var searchFor = jQuery( '#searchFor' ).val();
	var group = jQuery( '#groupSelect' ).val();
	
	if ( group != 'None' ) {
		jQuery( '#orFrom' ).text( 'from' );
	} else {
		jQuery( '#orFrom' ).text( 'or' );
	}

    if ( searchFor == 'Search' && group == 'None' ) {
        resultsBoxInner.text( '' );
        resultsBox.slideUp( 'fast' );
        return;
    }
    
    if ( searchFor.length < 2 && group == 'None') {
        resultsBoxInner.text( '' );
        resultsBox.slideUp( 'fast' );
        return;
    }

	jQuery( '.loading' ).fadeIn('fast');
    
    if ( undefined === window.userSearchOrder ) {
        userSearchOrder = 0;
    }
    userSearchOrder++;

    jQuery.post(
        '/parts/users/pmsearchresults',
		{
			token: searchFor,
			group: group
		}, 
		function( responseText ) { 
			Result = eval( responseText );
            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            if ( undefined === window.lastSearchReceived ) {
                lastSearchReceived = 0;
            }
            
            if ( Result[2] < lastSearchReceived ) {
                return;
            }
            
            lastSearchReceived = parseInt( Result[2] );
            
            if ( resultsBox.attr( 'display' ) != 'none' ) {
                resultsBox.slideUp( 'fast', function() {
                    jQuery( '#addtopmresults .results' ).html( Result[1] );
                    jQuery( '#addtopmresults' ).slideDown( 'fast' );
					jQuery( '.loading' ).fadeOut('fast');
                } );
            } else {
                jQuery( '#addtopmresults .results' ).html( Result[1] );
                jQuery( '#addtopmresults' ).slideDown( 'fast' );
            }
        }
    );
}

// This function is no longer in use.
function showGroupMembers( groupId ) {
    if ( !groupId ) {
        return;
    }
    var resultsBox = jQuery( '#addtopmresults' );
    var resultsBoxInner = jQuery( '#addtopmresults .results' );
	var token = jQuery( '#token' ).val();

    if ( jQuery( '#addtopmresults .results .member' ).length ) {
        resultsBox.slideUp( 'fast', function() {
            resultsBoxInner.html( '<i>Loading...</i>' );
            resultsBox.slideDown( 'fast' );
        } );
    } else {
        resultsBoxInner.html( '<i>Loading...</i>' );
        resultsBox.slideDown( 'fast' );
    }

	// jQuery('body').before('ShowGroupMembers - Run. ');

    jQuery.post(
        '/parts/users/pmsearchresults',
        { token: token, group_id: groupId },
        function( responseText ) { 
			Result = eval( responseText );
            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            if ( resultsBox.attr( 'display' ) != 'none' ) {
                resultsBox.slideUp( 'fast', function() {
                    jQuery( '#addtopmresults .results' ).html( Result[1] );
                    jQuery( '#addtopmresults' ).slideDown( 'fast' );
                } );
            } else {
                jQuery( '#addtopmresults .results' ).html( Result[1] );
                jQuery( '#addtopmresults' ).slideDown( 'fast' );
            }
        }
    );
}

function convertMessageBody( msgBody ) {

    // <, > and & character come thru as there respective HTML entites.
    // So strip 'em out
    msgBody = msgBody.replace( /&gt;/gi, ">" );
    msgBody = msgBody.replace( /&lt;/gi, "<" );
    msgBody = msgBody.replace( /&amp;/gi, "&" );
    
    // Firefox XMLSerializer leaves these all over the fucking place
    msgBody = msgBody.replace( / xmlns="[^"]+"/gi, "" );
	
	// code blocks
	msgBody = msgBody.replace( /<pre class="code-block">/gi, '[code]' );
	msgBody = msgBody.replace( /<pre class="code-block line_1">/gi, '[code]' );
	matches = msgBody.match( /<pre class="code-block(.*?)">/gi );
	if( matches ){
		for( i = 0; i < matches.length; i++ ){
			var re = /line_([0-9]+)/gi;
			sub_matches = re.exec( matches[i] );
			var re2 = new RegExp( '<pre class="code-block line_' + sub_matches[1] + '">', "gi" );
			msgBody = msgBody.replace( re2, '[code line=' + sub_matches[1] + ']' );
		}
	}
	
	msgBody = msgBody.replace( /<\/pre>/gi, '[/code]' );
	msgBody = msgBody.replace( /<span class="code-block-line-num">(.+?)<\/span>\s/gi, '' );
	
    // quotes
    msgBody = msgBody.replace( /<div class=("?)quote("?)>/gi, '[quote]' );
    msgBody = msgBody.replace( /<div class=("?)small("?)><b>Quote:<\/b><\/div>/gi, '' );
    msgBody = msgBody.replace( /<\/div>[\r\n]*/gi, '[/quote]' );

    // IE strips out line breaks (WTF?)
    // So replace <br> tags with line breaks in IE.
    // For other browsers just strip them out
	msgBody = msgBody.replace( /(<br>|<br.*\/>)/gi, ( navigator.userAgent.indexOf( "MSIE" ) == -1 ? "" : "\n" ) );
	
    msgBody = msgBody.replace( /<b[^>]*>/gi, '[b]' );
    msgBody = msgBody.replace( /<\/b>/gi, '[/b]' );
    msgBody = msgBody.replace( /<i[^>]*>/gi, '[i]' );
    msgBody = msgBody.replace( /<\/i>/gi, '[/i]' );
    msgBody = msgBody.replace( /<u[^>]*>/gi, '[u]' );
    msgBody = msgBody.replace( /<\/u>/gi, '[/u]' );
    msgBody = msgBody.replace( /<del[^>]*>/gi, '[s]' );
    msgBody = msgBody.replace( /<\/del>/gi, '[/s]' );

    var matches = msgBody.match( /(<a ([^<]*)<\/a>)/gi );

	if( matches ){
		for( i = 0; i < matches.length; i++ ){
			if ( jQuery( matches[i] ).text() != 'view' ) {
				msgBody = msgBody.replace( matches[i], matches[i].match( /<a (?:.*)href="(.*?)"/i )[1] );
			} else {
				msgBody = msgBody.replace( matches[i], '' );				
			}
		}
	}

	msgBody = msgBody.replace( /\[quote\](\s+)/gi, '[quote]' );
	msgBody = msgBody.replace( /(\s+)\[\/quote\](\s+)/gi, '[/quote]' );

    // trim excess whitespace off start and end
    msgBody = msgBody.replace( /^\s+|\s+$/g, "" );

    return msgBody;
}

function deleteMessage( messageId ) {
    var button = jQuery( '#message_' + messageId + ' .button.delete' );
    var message = jQuery( '#message_' + messageId );

    if ( button.hasClass( 'disabled' ) ) {
        return;
    }
    
    if ( message.hasClass( 'deleted') ) {
        var undelete = 1;
        button.addClass( 'disabled' ).text( 'undeleting...' );
    } else {
        var undelete = 0;
        button.addClass( 'disabled' ).text( 'deleting...' );
    }
   
    jQuery.post(
        '/parts/forum/messages/delete',
        { message_id: messageId, undelete: undelete },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            button.removeClass( 'disabled' )
            
            if ( undelete ) {
                button.text( 'delete' );
                message.animate( 
                    { 'opacity': 1 }, 200, 'linear', function() {
                        message.removeClass( 'deleted' );
                    }
                );
            } else {           
                button.text( 'undelete' );
                message.animate( 
                    { 'opacity': 0.5 }, 200, 'linear', function() {
                        message.addClass( 'deleted' );
                    }
                );
            }

            cancelMessageEdit( messageId );
        }
    );
}

var splitMessage = {
    ask: function( messageId ) {
        if ( jQuery( '#message_' + messageId + ' .button.split' ).hasClass( 'disabled' ) ) {
            return;
        }
        
        jQuery( '#message_' + messageId + ' .button.split' ).addClass( 'disabled' );
        jQuery( '#message_' + messageId ).append( 
            '<div class="dialogue">' +
            '<span onclick="splitMessage.yes(' + messageId + ')">' +
            'Create a new discussion from this message</span> ' +
            '<span onclick="splitMessage.cancel(' + messageId + ')">Cancel</span></div>'
        );
    },
    yes: function( messageId ) {
        jQuery( '#message_' + messageId + ' .dialogue' )
            .html( 'Splitting...' )
            .css( 'right', '248px' );

        jQuery.post(
            '/parts/forum/messages/split',
            { message_id: messageId },
            function( responseText ) { 
                Result = eval( responseText );

                if ( Result[0] != 'success' ) {
                    alert( 'Error: ' + Result[0] );
                    return;
                }
                
                window.location.href = '/forum/discussion/' + Result[1] + '#split';
            }
        );
    },
    cancel: function( messageId ) {
        jQuery( '#message_' + messageId + ' .dialogue' ).remove();
        jQuery( '#message_' + messageId + ' .button.split' ).removeClass( 'disabled' );
    }
}

function switchMsgType( button, messageId ) {
    if ( jQuery( button ).hasClass( 'on' ) ) {
        return;
    }

    if ( jQuery( '#message_' + messageId + '.internalmsg' ).length &&
        jQuery( '#message_' + messageId + ' .typeswitch .button.internalmsg.on' ).length &&
        !confirm( "Warning! You are choosing to make an internal message publicly visible! Are you sure that's what you want to do?" ) 
    ) {
        return;
    }

    if ( jQuery( '#message_' + messageId + ' .typeswitch .button.internal.on' ).length ) {
        if ( !confirm( "Warning! You are choosing to make an internal only file downloadable by other users. Please be sure you are selecting the right option. Are you sure you wish to continue?" ) ) {
            return;
        }
    }

    jQuery( '#message_' + messageId + ' .typeswitch .button.on' ).removeClass( 'on' );
    jQuery( button ).addClass( 'on' );

    typeChanged[messageId] = 'yes';   
    jQuery( '#message_' + messageId + ' .button.save' ).removeClass( 'disabled' );
}

function editMessage( messageId ) {
    if ( jQuery( '#message_' + messageId + ' .button.edit' ).hasClass( 'disabled' ) ) {
        return;
    }

    var msgDiv = jQuery( '#message_' + messageId + ' .body' );

    var converted = convertMessageBody( msgDiv.html() );
    
    // save the unedited state for later comparison
    originalMsgBody[messageId] = converted;

    var width = msgDiv.width() ;
    var height = msgDiv.height() - 2;
    if ( navigator.userAgent.indexOf( 'Firefox' ) != -1 ) {
        height = height - 2;
    }

    if ( height < 70 ) {
        height = 70;
    }
    
    msgDiv.fadeOut( 
        'fast',
        function() {
            msgDiv.after(
                '<textarea class="body" style="width:' + width
                + 'px;height:' + height + 'px;margin:0;padding:0;display:none;resize:vertical;overflow:visible;" onkeyup="hasMsgBodyChanged(' 
                + messageId + ')">' + converted + '</textarea>' );
            jQuery( 'textarea.body' ).fadeIn( 'fast' );
            jQuery( '#message_' + messageId + ' .buttons .editing' ).fadeIn( 'fast' );
            jQuery( '#message_' + messageId + ' .buttons .button.edit' )
                .hide().addClass( 'disabled' );
            jQuery( '#message_' + messageId + ' .buttons .typeswitch' ).fadeIn( 'fast' );
            jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .typeswitch .button' )
                .show();
            jQuery( '#message_' + messageId + ' .buttons.alwaysvisible .editing .button' )
                .show();
        }
    );
}

function hasMsgBodyChanged( messageId ) {
    var editedBody = jQuery( '#message_' + messageId + ' textarea' ).val();

    if ( editedBody != originalMsgBody[messageId] || typeChanged[messageId] == 'yes' ) {
        jQuery( '#message_' + messageId + ' .button.save' ).removeClass( 'disabled' );
    } else {
        jQuery( '#message_' + messageId + ' .button.save' ).addClass( 'disabled' );
    }
}

function cancelMessageEdit( messageId ) {
    if ( jQuery( '#message_' + messageId + ' .button.cancel' ).hasClass( 'disabled' ) ) {
        return;
    }

    var msgBodyEdit = jQuery( '#message_' + messageId + ' textarea' )
    
    jQuery( '#message_' + messageId + ' .buttons .editing' ).fadeOut( 'fast' );
    jQuery( '#message_' + messageId + ' .button.edit' ).removeClass( 'disabled' ).show();
    jQuery( '#message_' + messageId + ' .button.save' ).addClass( 'disabled' ).text( 'save' );
    jQuery( '#message_' + messageId + ' .buttons .typeswitch' ).fadeOut( 'fast' );
    
    msgBodyEdit.fadeOut(
        'fast',
        function() {
            jQuery( '#message_' + messageId + ' div.body' ).fadeIn( 'fast' );
            msgBodyEdit.remove();
        }
    );
}

function saveMessageEdit( messageId ) {
    if ( jQuery( '#message_' + messageId + ' .button.save' ).hasClass( 'disabled' ) ) {
        return;
    }

    jQuery( '#message_' + messageId + ' .button.save' ).addClass( 'disabled' )
        .text( 'saving...' );
    jQuery( '#message_' + messageId + ' .button.cancel' ).addClass( 'disabled' );

    var typeButton = jQuery( '#message_' + messageId + ' .typeswitch .button.on' );
    if ( typeButton.hasClass( 'normal' ) ) {
        var type = 'normal';
    } else if ( typeButton.hasClass( 'system' ) ) {
        var type = 'system';
    } else if ( typeButton.hasClass( 'internalmsg' ) ) {
        var type = 'internalmsg';
    } else if ( typeButton.hasClass( 'all' ) ) {
        var dlType = 'all';
    } else if ( typeButton.hasClass( 'area' ) ) {
        var dlType = 'area';
    } else if ( typeButton.hasClass( 'internal' ) ) {
        var dlType = 'internal';
    }
   
    jQuery( '#message_' + messageId ).append( 
        '<div class="touch"><span onclick="touch(' + messageId + 
        ')">Click to update message time to now</span> <span onclick="closeTouch(' + 
        messageId + ')">Close</span></div>' );

    jQuery.post(
        '/parts/forum/messages/savebodyedit',
        { 
            message_id: messageId, 
            body: jQuery( '#message_' + messageId + ' textarea' ).val(),
            type: type, download: dlType
        },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#message_' + messageId + ' div.body' ).html( Result[1] );
            jQuery( '#message_' + messageId + ' .button.cancel' ).removeClass( 'disabled' );
            cancelMessageEdit( messageId );

            switch ( type ) {
                case 'normal':
                    jQuery( '#message_' + messageId )
                        .removeClass( 'internalmsg' )
                        .removeClass( 'system' );
                    break;
                case 'system':
                    jQuery( '#message_' + messageId )
                        .removeClass( 'internalmsg' )
                        .addClass( 'system' );
                    break;
                case 'internalmsg':
                    jQuery( '#message_' + messageId )
                        .removeClass( 'system' )
                        .addClass( 'internalmsg' );
                    break;
            }
        }
    );
}

function touch( messageId ) {
    var Message = jQuery( '#message_' + messageId );
    var Button = jQuery( '#message_' + messageId + ' .touch' );
    
    if ( Button.hasClass( 'disabled' ) ) {
        return;
    }

    Button.addClass( 'disabled' ).fadeTo( 'normal', 0.4 );

    jQuery.post(
        '/parts/forum/messages/touch',
        { message_id: messageId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }

            Button.fadeOut( 'normal', function() { 
                Button.remove();
                Message.slideUp( 'normal', function() {
                    Message.appendTo( '#messages_list' );
                    jQuery.scrollTo( '#postbox', 500, { 
                            easing: 'swing', 
                            onAfter: function() {
                                Message.slideDown();
                            } 
                        }
                    );
                } );
            } );
        }
    );
}

function closeTouch( messageId ) {
    var Button = jQuery( '#message_' + messageId + ' .touch' );
    Button.fadeOut( 'normal', function() { Button.remove(); } );
}


function markAreaRead( areaId ) {
    jQuery( '.markarearead' )
        .removeClass( 'link' )
        .text( 'Marking discussions...' );
    jQuery.post(
        '/parts/forum/areas/markread',
        { area_id: areaId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '.markarearead' )
                .text( 'All discussions marked as read' )
                .attr( 'onclick', '' );
            jQuery( '.thread .newcounts' ).hide();
            jQuery( '.thread .allcounts' ).show();

            if ( site == 'serato' ) {
				jQuery( '.thread.newmessages' ).animate( {
					'backgroundColor': '#fff',
					'borderBottomColor': '#bbb'
				}, 600, 'linear', function(){
					jQuery( '.thread.newmessages' ).removeClass( 'newmessages' );
                } );
				jQuery( '.thread .starter' ).animate( { 'color': '#666' } );
				jQuery( '.thread .counts' ).animate( { 'color': '#666' } );
            } else if ( site == 'whitelabel' ) {
                jQuery( '.thread.newmessages' ).animate( {
                    'borderTopColor': '#fff', 'borderRightColor': '#fff',
                    'borderBottomColor': '#eee', 'borderLeftColor': '#fff',
                    'backgroundColor': '#fff', 'color': '#525252',
                    '-moz-border-radius-bottomleft': '0px',
                    '-moz-border-radius-topright': '0px',
                    '-webkit-border-bottom-left-radius': '0px',
                    '-webkit-border-top-right-radius': '0px'
                }, 600, 'linear', function() {
                    jQuery( '.thread.newmessages' ).removeClass( 'newmessages' );
                } );
            }
        }
    );
}

function trackThread( threadId ) {
    jQuery( '#tracklink' ).removeClass( 'link' ).text( 'Tracking...' );
    jQuery.post(
        '/parts/forum/threads/track',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#tracklink' )
                .addClass( 'link' )
                .text( 'Stop Tracking This Discussion' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    untrackThread( threadId);
                } );
        }
    );
}

function untrackThread( threadId ) {
    jQuery( '#tracklink' ).removeClass( 'link' ).text( 'Untracking...' );
    jQuery.post(
        '/parts/forum/threads/untrack',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#tracklink' )
                .addClass( 'link' )
                .text( 'Track This Discussion' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    trackThread( threadId);
                } );
        }
    );
}

function markThreadRead( threadId, link ) {
    jQuery( link ).removeClass( 'link' ).text( 'Marking as read...' );
    jQuery.post(
        '/parts/forum/threads/markread',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( link )
                .text( 'Marked as read' )
                .attr( 'onclick', '' );
            
            if ( site == 'serato' ) {
                jQuery( '.message.new:not(.system,.internalmsg)' ).animate( {
                    'backgroundColor': '#fff',
                    'borderBottomColor': '#bbb'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .quote' ).animate( {
                    'backgroundColor': '#eee',
                    'borderTopColor': '#ddd',
                    'borderRightColor': '#ddd',
                    'borderLeftColor': '#ddd',
                    'borderBottomColor': '#aaa'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .buttons .forusers' ).animate( {
                    'backgroundColor': '#ddd'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .buttons .formods' ).animate( {
                    'backgroundColor': '#ddd'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .buttons .editing' ).animate( {
                    'backgroundColor': '#ddd'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .details' ).animate( { 'color': '#666' } );
            } else if ( site == 'whitelabel' ) {
                jQuery( '.message.new:not(.system,.internalmsg)' ).animate( {
                    'backgroundColor': '#fff',
                    'borderTopColor': '#fff',
                    'borderRightColor': '#fff',
                    'borderLeftColor': '#fff',
                    'borderBottomColor': '#eee'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .quote' ).animate( {
                    'backgroundColor': '#eee',
                    'borderTopColor': '#ddd',
                    'borderRightColor': '#ddd',
                    'borderLeftColor': '#ddd',
                    'borderBottomColor': '#ccc'
                } );
                jQuery( '.message.new:not(.system,.internalmsg) .details' ).animate( { 'color': '#666' } );
            } else {
                jQuery( '.message.new:not(.system,.internalmsg)' ).animate( { 'backgroundColor': '#ffd' } );
                jQuery( '.message.new:not(.system,.internalmsg) .quote' ).animate( {
                    'backgroundColor': '#ffc',
                    'borderTopColor': '#666',
                    'borderRightColor': '#666',
                    'borderLeftColor': '#666',
                    'borderBottomColor': '#666'
                } );
            }
        }
    );
}

function markThreadUnread( threadId, link ) {
    jQuery( link ).removeClass( 'link' ).text( 'Marking as unread...' );
    jQuery.post(
        '/parts/forum/threads/markunread',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( link )
                .text( 'Marked as unread' )
                .attr( 'onclick', '' );

            MessagesList.stop().animate( {
                'backgroundColor': '#cfdee5',
                'borderBottomColor': '#bbb'
            }, 1500 );

            jQuery( '.message.new .quote' ).animate( {
                'backgroundColor': '#ea0',
                'borderTopColor': '#ec7',
                'borderRightColor': '#ec7',
                'borderBottomColor': '#ba7',
                'borderLeftColor': '#ec7'
            }, 1500 );
        }
    );
}

function lockThread( threadId ) {
    jQuery( '#lockbutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/lock',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#lockbutton' )
                .removeClass( 'loading' )
                .addClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    unlockThread( threadId );
                } );
        }
    );
}

function unlockThread( threadId ) {
    jQuery( '#lockbutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/unlock',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#lockbutton' )
                .removeClass( 'loading' )
                .removeClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    lockThread( threadId );
                } );
        }
    );
}

function hideThread( threadId ) {
    jQuery( '#hidebutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/hide',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#hidebutton' )
                .removeClass( 'loading' )
                .addClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    unhideThread( threadId );
                } );
        }
    );
}

function unhideThread( threadId ) {
    jQuery( '#hidebutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/unhide',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#hidebutton' )
                .removeClass( 'loading' )
                .removeClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    hideThread( threadId );
                } );
        }
    );

}

function hideDeleted() {
    jQuery( '#delbutton' ).attr( 'onclick', '' ).unbind( 'click' );

    if ( !jQuery( '.message.deleted' ).length ) {
        switchButton();
    } else {
        jQuery( '.message.deleted' ).slideUp( 'normal', function() {
            switchButton();
        } );
    }

    function switchButton() {
        jQuery( '#delbutton' ).removeClass( 'on' )
            .attr( 'title', 'Show Deleted Messages' )
            .bind( 'click', function() {
                unhideDeleted();
            } );
    }
}

function unhideDeleted() {
    jQuery( '#delbutton' ).attr( 'onclick', '' ).unbind( 'click' );

    if ( !jQuery( '.message.deleted' ).length ) {
        switchButton();
    } else {
        jQuery( '.message.deleted' ).slideDown( 'normal', function() {
            switchButton();
        } );
    }

    function switchButton() {
        jQuery( '#delbutton' ).addClass( 'on' )
            .attr( 'title', 'Hide Deleted Messages' )
            .bind( 'click', function() {
                hideDeleted();
            } );
    }
}

function makeSticky( threadId ) {
    jQuery( '#stickybutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/sticky',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#stickybutton' )
                .removeClass( 'loading' )
                .addClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    makeUnsticky( threadId );
                } );
        }
    );
}

function makeUnsticky( threadId ) {
    jQuery( '#stickybutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/unsticky',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#stickybutton' )
                .removeClass( 'loading' )
                .removeClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    makeSticky( threadId );
                } );
        }
    );

}

function makeCompulsory( threadId ) {
    jQuery( '#compulsbutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/makecompulsory',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#compulsbutton' )
                .removeClass( 'loading' )
                .addClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    makeNotCompulsory( threadId );
                } );
        }
    );
}

function makeNotCompulsory( threadId ) {
    jQuery( '#compulsbutton' ).addClass( 'loading' );
    jQuery.post(
        '/parts/forum/threads/makenotcompulsory',
        { thread_id: threadId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            jQuery( '#compulsbutton' )
                .removeClass( 'loading' )
                .removeClass( 'on' )
                .attr( 'onclick', '' )
                .unbind( 'click' )
                .bind( 'click', function() {
                    makeCompulsory( threadId );
                } );
        }
    );
}

function showMoveArea() {
    jQuery( '#areas' ).show();
    jQuery( '#move' ).hide();
    jQuery( '#moveareablock br' ).hide();
    jQuery( '#moveareablock .cancel' ).show();
}

function cancelMoveArea() {
    jQuery( '#areas' ).hide();
    jQuery( '#move' ).show();
    jQuery( '#moveareablock br' ).show();
    jQuery( '#moveareablock .cancel' ).hide();
}

function moveArea( currentAreaId, threadId ) {
    var selectedArea = jQuery( '#areas option:selected' );
    var areasSelect = jQuery( '#areas' );
    var areaId = areasSelect.val();
    
    if ( areasSelect.val() == currentAreaId ) {
        return;
    }

    if ( !confirm( 
        "Are you sure you want to move this discussion to the '" 
        + selectedArea.text() + "' area?"
    ) ) {
        areasSelect.val( currentAreaId );
        return;
    }

    jQuery( '#areas option' ).each( function() {
        this.innerHTML = this.innerHTML.replace( /\.+/, '' );
    } );
    areasSelect.css( 'font-style', 'italic' );
    selectedArea.html( selectedArea.html() + '...' );
    
    jQuery.post(
        '/parts/forum/threads/movearea',
        { thread_id: threadId, area_id: areaId },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
            
            history.go( 0 );
        }
    );
}

function showChangeProduct() {
    jQuery( '#products' ).show();
    jQuery( '#changeproduct' ).hide();
    jQuery( '#changeproductblock br' ).hide();
    jQuery( '#changeproductblock .cancel' ).show();
}

function cancelChangeProduct() {
    jQuery( '#products' ).hide();
    jQuery( '#changeproduct' ).show();
    jQuery( '#changeproductblock br' ).show();
    jQuery( '#changeproductblock .cancel' ).hide();
}

function changeProduct( threadId ) {
    var productsSelect = jQuery( '#products' );
    var selectedProduct = jQuery( '#products option:selected' );
    var productName = selectedProduct.val();

    jQuery( '#products option' ).each( function() {
        this.innerHTML = this.innerHTML.replace( /\.+/, '' );
    } );
    productsSelect.css( 'font-style', 'italic' );
    selectedProduct.html( selectedProduct.html() + '...' );
    
    jQuery.post(
        '/parts/forum/threads/changeproduct',
        { thread_id: threadId, product: productName },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
           
            productsSelect.css( 'font-style', 'normal' );
            jQuery( '#products option' ).each( function() {
                this.innerHTML = this.innerHTML.replace( /\.+/, '' );
            } );
            jQuery( '#changeproductblock .product' ).text( productName );
            cancelChangeProduct();
        }
    );
}

function showChangeHardware() {
    jQuery( '#hardware' ).show();
    jQuery( '#changehardware' ).hide();
    jQuery( '#changehardwareblock br' ).hide();
    jQuery( '#changehardwareblock .cancel' ).show();
}

function cancelChangeHardware() {
    jQuery( '#hardware' ).hide();
    jQuery( '#changehardware' ).show();
    jQuery( '#changehardwareblock br' ).show();
    jQuery( '#changehardwareblock .cancel' ).hide();
}

function changeHardware( threadId ) {
    var hardwareSelect = jQuery( '#hardware' );
    var selectedHardware = jQuery( '#hardware option:selected' );
    var hardwareName = selectedHardware.val();


    jQuery( '#hardware option' ).each( function() {
        this.innerHTML = this.innerHTML.replace( /\.+/, '' );
    } );
    hardwareSelect.css( 'font-style', 'italic' );
    selectedHardware.html( selectedHardware.html() + '...' );
    
    jQuery.post(
        '/parts/forum/threads/changehardware',
        { thread_id: threadId, hardware: hardwareName },
        function( responseText ) { 
			Result = eval( responseText );

            if ( Result[0] != 'success' ) {
                alert( 'Error: ' + Result[0] );
                return;
            }
           
            hardwareSelect.css( 'font-style', 'normal' );
            jQuery( '#hardware option' ).each( function() {
                this.innerHTML = this.innerHTML.replace( /\.+/, '' );
            } );
            jQuery( '#changehardwareblock .sethardware' ).text( hardwareName );
            cancelChangeHardware();
        }
    );
}


function showHideToolbox() {
    var inner = jQuery( '#toolbox .inner' );
    if ( inner.css( 'display' ) == 'none' ) {
        inner.slideDown( 150 );
        var state = 'open';
    } else {
        inner.slideUp( 150 );
        var state = 'closed';
    }
    jQuery.post( '/parts/forum/threads/remembertoolboxstate', { state: state } );
}

function collapseGroup( name, title ) {
    var group = jQuery( '#' + name + 'group' );

    jQuery.post( '/parts/forum/grouphide', { group: name, state: 'hide' } );

    group.animate( { 'opacity': 0.5 }, 'fast', 'linear', function() {
        jQuery( title ).find( 'span' ).html( '&#x25b6;' );
        group.slideUp( 'fast', function() {
            group.empty();
			group.parents('.area-container').removeClass('expanded');
			group.parents('.area-container').addClass('collapsed');
        } );
    } );

    jQuery( title ).attr( 'onclick', '' )
        .unbind( 'click' )
        .bind( 'click', function() {
            expandGroup( name, title );
        } );
}

function expandGroup( name, title ) {
    var group = jQuery( '#' + name + 'group' );

    jQuery.post( '/parts/forum/grouphide', { group: name, state: 'show' } );

    if ( !group.children().length ) {
        group.html( '<div style="margin:0 0 14px 20px">Loading...</div>' )
            .hide()
            .css( 'opacity', 1 )
            .slideDown( 100 );

	        jQuery.post(
	            '/parts/forum/areas/getlist',
	                { group: name },
	                function( responseText ) { 
	                Result = eval( responseText );

	                if ( Result[0] != 'success' ) {
	                    alert( 'Error: ' + Result[0] );
	                    return;
	                }
					
                    group.hide()
	                    .html( Result[1][0] )
	                    .css( 'opacity', 0.5 )
	                    .slideDown( 200, function() {
	                        jQuery( title ).find( 'span' ).html( '&#x25bc;' );

							group.parents('.area-container').removeClass('collapsed');
							group.parents('.area-container').addClass('expanded');

	                        group.animate( { 'opacity': 1 }, 100 );
	                    } );
	            }
	        );

    } else {
        group.slideDown( 200, function() {
            jQuery( title ).find( 'span' ).html( '&#x25bc;' );
            group.animate( { 'opacity': 1 }, 100 );a

        } );
    }
    jQuery( title ).attr( 'onclick', '' )
        .unbind( 'click' )
        .bind( 'click', function() {
            collapseGroup( name, title );
        } );
}

function attachFile() {
    jQuery( '#attachbox form' ).submit();
    jQuery( '#attachbox .attach' ).fadeOut( 500, function() { 
        jQuery( '#attachbox .attach' )
            .removeClass( 'link' )
            .text( 'Attaching...' )
            .fadeIn( 500 );
    } );
    jQuery( '#attachbox .explain' ).fadeOut( 500, function() {
        jQuery( '#attachbox .explain' )
            .text( 'Your file is uploading. Depending on the file size this may take some time.' )
            .fadeIn( 500 );
    } );
    jQuery( '#attachbox input[type=file]' ).css( 'display', 'none' );
}

function attachFinished( Results ) {
    if ( Results[0] != 'success' ) {
        jQuery( '#attachbox .attach' ).fadeOut( 500, function() { 
            jQuery( '#attachbox .attach' )
                .text( 'Error' )
                .fadeIn( 500 );
        } );
        jQuery( '#attachbox .explain' ).fadeOut( 500, function() {
            jQuery( '#attachbox .explain' )
                .text( Result[0] )
                .fadeIn( 500 );
        } );
        return;
    }

    jQuery( '#attachbox .attach' ).fadeOut( 500, function() { 
        jQuery( '#attachbox .attach' )
            .text( 'Complete' )
            .fadeIn( 500 );
    } );
    jQuery( '#attachbox .explain' ).fadeOut( 500, function() {
        jQuery( '#attachbox .explain' )
            .text( 'Your file has been uploaded and staff have been notified.' )
            .fadeIn( 500 );
	    setTimeout( 'resetAttachForm()', 5000 );
    } );

    checkForNewMessages();
}

function resetAttachForm() {
    jQuery( '#attachbox form' ).get( 0 ).reset();
    jQuery( '#attachbox .attach' ).fadeOut( 500, function() { 
        jQuery( '#attachbox .attach' )
            .addClass( 'link' )
            .text( 'Attach A File' )
            .fadeIn( 500 );
    } );
    jQuery( '#attachbox .explain' ).fadeOut( 500, function() {
        jQuery( '#attachbox .explain' )
            .text( 'Attach a relevant file to this discussion.' )
            .fadeIn( 500 );
    } );
    jQuery( '#attachbox input[type=file]' ).css( 'display', '' );
}

function showHideAttachments() {
    var Attachments = jQuery( '#attachments' );

    if ( Attachments.css( 'display' ) == 'none' ) {
        Attachments.slideDown( 'fast' );
    } else {
        Attachments.slideUp( 'fast' );
    }
}

function positionAttachButton() {
    var link = jQuery( '#attachbox .attach' );
    var right = ( jQuery( '#attachbox' ).width() + 40 ) - 
    	( link.position().left + link.width() + 100 );
    jQuery( '#attachbox input[type=file]' ).css( 'right', right + 'px' );
}

function removePMRecipient( userId ) {
    var receivers = jQuery( '#receivers' ).val().split( ',' );
    var newReceivers = '';
    for ( i = 0; receivers[i]; i++ ) {
        if ( receivers[i] != userId ) {
            newReceivers += receivers[i] + ',';
        }
    }
    newReceivers = newReceivers.replace( /,$/, '' );
    jQuery( '#receivers' ).val( newReceivers );

    jQuery( '#recipient_' + userId ).animate( 
        { width: 'hide', opacity: 0, paddingLeft: 0, paddingRight: 0 }, 
        { duration: 400, complete: function() { 
            jQuery( '#recipient_' + userId ).remove(); 
        } } );
    
    isFormFilled( true, true );
}

function addPMRecipient( recipient ) {
    jQuery( '#addrecipient' ).val( '' );
    
    if ( recipient.length < 2 ) {
        return;
    }
    
    var name = recipient[0];
    var id = recipient[1];
    var userPage = ( recipient[2].length ) ? recipient[2] : 'id:' + id;

    var width = jQuery( '<div class="recipient" id="recipient_' + id + '" style="display:none"><a href="/user/' + userPage + '">' + name + '</a> <span class="link" onclick="removePMRecipient(' + id + ')">x</span></div>' ).appendTo( '#recipients_list' ).width();
    jQuery( '#recipients .recipient:last' )
        .css( { width: 0, opacity: 0, paddingLeft: 0, paddingRight: 0, display: 'block' } )
        .animate( { 
            width: width + 'px', opacity: 1, 
            paddingLeft: '7px', paddingRight: '7px' 
        }, 400 );

    var receiverIds = jQuery( '#receivers' ).val().replace( /,$/, '' );
    if ( receiverIds.length ) {
        jQuery( '#receivers' ).val( receiverIds + ',' + id );
    } else {
        jQuery( '#receivers' ).val( id );
    }

    isFormFilled( true, true );
}

function fadeThread( threadId ) {
    jQuery( '#thread_' + threadId + ' .newcounts' ).remove();
    jQuery( '#thread_' + threadId + ' .allcounts' ).fadeIn();
    jQuery( '#thread_' + threadId + ' .prefix' ).hide();
    if ( site == 'serato' ) {
        jQuery( '#thread_' + threadId + ' .starter' ).animate( { 'color': '#666' }, 600 );
        jQuery( '#thread_' + threadId + ' .counts' ).animate( { 'color': '#666' }, 600 );
        jQuery( '#thread_' + threadId ).animate( { 'background-color': '#fff' }, 600 );
    }
}

function showReleaseFeedbackDialog( release_id, message_id, display_name ){
	var boxTop = ( jQuery( window ).height() / 2 ) - 75;
	jQuery( '#release_feedback_dialog .release_id' ).val( release_id );
	jQuery( '#release_feedback_dialog .message_id' ).val( message_id );
	jQuery( '#release_feedback_dialog .display_name' ).html( display_name );
	jQuery( '#release_feedback_dialog textarea' ).val(
						convertMessageBody( jQuery( '#message_' + message_id + ' .body' ).html() )
			  );
	
    jQuery( '#release_feedback_dialog' ).css( 'top', boxTop + 'px' ).fadeIn();
}

function closeReleaseFeedbackDialog(){
	jQuery( '#release_feedback_dialog' ).fadeOut();
}

function submitReleaseDefaultFeedback(){
	if( jQuery( '#release_feedback_dialog textarea' ).val() != '' ){
		jQuery( '#release_feedback_dialog .buttons .submit' ).hide();
		jQuery( '#release_feedback_dialog .buttons .submitting' ).show();
		params = {};
		params.release_id = jQuery( '#release_feedback_dialog .release_id' ).val();
		params.message_id = jQuery( '#release_feedback_dialog .message_id' ).val();
		params.message_text = jQuery( '#release_feedback_dialog textarea' ).val();
		jQuery.post(
			'/parts/releases/savedefaultfeedback',
			params,
			function( responseText ) { 
				Result = eval( responseText );
				if( Result[0] != 'success' ){
					alert( Result[0] );
					return;
				}
				jQuery( '#wl_release_feedback_current .button a' ).attr( 'href', '#' + jQuery( '#release_feedback_dialog .message_id' ).val() );
				jQuery( '#wl_release_feedback_current .poster').html( Result[1] );
				jQuery( '#release_feedback_dialog .poster').html( Result[1] );
				jQuery( '#wl_release_feedback_current .quote_text').html( Result[2] );
				jQuery( '#release_feedback_dialog .quote_text').html( Result[2] );
				jQuery( '#release_feedback_dialog textarea').val( '' );
				jQuery( '#wl_release_feedback_current' ).show();
				jQuery( '#release_feedback_dialog .current' ).show();
				jQuery( '#release_feedback_dialog .buttons .submitting' ).hide();
				jQuery( '#release_feedback_dialog .buttons .submit' ).show();
				closeReleaseFeedbackDialog();
			}
		);
	}
}

var SetDisplayName = {
	redirectURL: '',
    showOverlay: function( url ) {
		if( url ) SetDisplayName.redirectURL = url;
        jQuery( '.overlay.displayname' ).remove().appendTo( '#footer' ).show();
    },
    save: function( needAgreement, threadId ) {
        if ( !jQuery( '#newdisplayname' ).val().length ) {
            return false;
        }
        
        var Error = jQuery( '.overlay.displayname .error' );
        var Button = jQuery( '.overlay.displayname input[type=submit]' );

        if ( Button.val() != 'Save' ) {
            alert( Button.val() );
            return false;
        }
        
        Error.text( '' );
        Button.val( 'Saving...' );

		jQuery.post(
			'/parts/users/setdisplayname',
			{ display_name: jQuery( '#newdisplayname' ).val() },
			function( responseText ) { 
				Result = eval( responseText );

                if ( Result[0] == 'already taken' ) {
                    Error.text( 'Already taken!' );
                    Button.val( 'Save' );
                    return;
                }

				if ( Result[0] != 'success' ) {
					alert( 'Error: ' + Result[0] );
                    Button.val( 'Save' );
					return;
				}

                successHTML  = '<h1>Your display name has been set</h1>';
                
                if ( needAgreement ) {
                    successHTML += '<div class="instructions"><p>Thanks! You must now accept the terms and conditions.</p></div>';
                } else {
                    successHTML += '<div class="instructions"><p>Thanks! You can now post replies.</p></div>';
                }

                jQuery( '.overlay.displayname .message' ).fadeOut( 'normal', function() {
                    jQuery( '.overlay.displayname .message' ).html( successHTML );
                } ).fadeIn();
                setTimeout( function() {
                    jQuery( '.overlay.displayname' ).fadeOut( 'normal', function( ) {
                        jQuery( '.overlay.displayname' ).remove();
                        if( !SetDisplayName.redirectURL || SetDisplayName.redirectURL == '' )
							SetDisplayName.redirectURL = '/forum/discussion/' + threadId + '#reply';
                        if ( needAgreement ) {
                            window.location = '/legal/website-forum-rules?redirect=' + escape( SetDisplayName.redirectURL );
                        } else {
                            window.location = SetDisplayName.redirectURL;
                            window.location.reload( true );
                        }
                    } );
                }, 3000 );
            }
        );

        return false;
    },

    cancel: function() {
        jQuery( '.overlay.displayname' ).hide();
    }
}

function deleteRelatedThread( thread_id, link_id ) {
	if( !confirm( 'Are you sure you want to remove this Related Thread?\nThis cannot be undone.' ) ){
		return;
	}
	jQuery.post(
		"/parts/forum/threads/relatedthreads/ajax",
		{ action: 'delete', thread_id: thread_id, thread_related_id: link_id  },
		function( responseText ){
			Result = eval( responseText );
			if( Result[0] != 'success' )
				return showRelatedThreadError( Result[0] );
			jQuery( '#related_link_summary' ).html( Result[1] );
		}
	);	
	return false;	
}

function addRelatedThread( threadId ) {
	var threadLinkId = jQuery( '#thread_link_id' ).val();
	
	if( threadId == '' || threadLinkId == '' || threadLinkId == 'Discussion ID / URL' ) return;
	if( parseInt( threadId ) == parseInt( threadLinkId ) )
		return showRelatedThreadError( 'You cannot relate a thread to itself :-)' );
	
	jQuery( '#check_thread' ).text( 'Adding...' ).attr( 'disabled', true );
	jQuery.post(
		"/parts/forum/threads/relatedthreads/ajax",
		{ action: 'add', thread_link_id: threadLinkId, thread_id: threadId },
		function( responseText ) {
			Result = eval( responseText );
			if( Result[0] != 'success' ) {
				showRelatedThreadError( Result[0] );
				jQuery( '#check_thread' ).text( 'Add' ).attr( 'disabled', false );
				return;
			}
			jQuery( '#check_thread' ).text( 'Add' ).attr( 'disabled', false );
			jQuery( '#thread_link_id' ).val( 'Discussion ID / URL' ).css( 'color', '#aaa' );
			jQuery( '#related_link_summary' ).html( Result[1] );
		}
	);
	return false;	
}

function showHelpRequestHistory( section, thread_id, refresh ){
	// Could easily add a 'Refresh' GUI element and add a value of true to
	// the 'refresh' argument of this function. But this is currently
	// not implemented
	jQuery( '#help-request-history .related-threads-header .show-link' ).css( { 'color' : '#006C99', 'border-bottom' : '1px solid #6EA6C1', 'font-weight' : 'normal' } );
	jQuery( '#help-request-history .related-threads-header .show-' + section ).css( { 'color' : '#666', 'font-weight' : 'bold', 'border' : '0 none' } );
	jQuery( '#help-request-history .history-list' ).hide();
	jQuery( '#help-request-history .history-list.' + section ).show();
	if( jQuery( '#help-request-history .history-list.' + section + ' .rows' ).html() == '' ) refresh = true;
	
	if( refresh ){
		jQuery( '#help-request-history .history-list.' + section + ' .msg' ).hide();
		jQuery( '#help-request-history .history-list.' + section + ' .loading' ).show();
		showHelpRequestHistoryThreadList( section, thread_id, 1 );
	}
}

function showHelpRequestHistoryThreadList( section, thread_id, page ){
	jQuery( '#help-request-history .history-list.' + section + ' .rows' ).addClass( 'loading' );
	jQuery.post(
		"/parts/forum/threads/historythreads/ajax",
		{ section: section, thread_id: thread_id, page: page },
		function( responseText ) {
			Result = eval( responseText );
			if( Result[0] != 'success' ) {
				showRelatedThreadError( Result[0] );
				return;
			}
			jQuery( '#help-request-history .history-list.' + section + ' .rows' ).html( Result[1] ).removeClass( 'loading' );
			jQuery( '#help-request-history .history-list.' + section + ' .msg' ).hide();
		}
	);
}

function showRelatedThreadError( text ){
	jQuery( '.related-threads-header .add-box .error-msg' ).text( text ).show();
	setTimeout( "jQuery( '.related-threads-header .add-box .error-msg' ).fadeOut( 3000 )", 3000 );
	//setTimeout fadeOut( 3000 );
}

