var wpKeywords, coreKeywordList;

(function($){

	coreKeywordList = {
		'has-patch' : 'Proposed solution attached and ready for review.',
		'needs-patch' : 'Ticket needs a new patch.',
		'needs-refresh' : 'Patch no longer applies cleanly and needs to be updated.',
		'reporter-feedback' : 'Feedback is needed from the reporter.',
		'dev-feedback' : 'Feedback is needed from a core developer.',
		'2nd-opinion' : 'A second opinion is desired for the problem or solution.',
		'close' : 'The ticket is a candidate for closure.',
		'needs-testing' : 'Patch has a particular need for testing.',
		'ui-feedback' : 'Feedback is needed from the user interface perspective, generally from the UI team.',
		'ux-feedback' : 'Feedback is needed from the user experience perspective, generally from the UX lead.',
		'needs-ui' : 'Needs user interface work, generally from the UI team.',
		'needs-unit-tests' : 'Ticket has a particular need for unit tests.',
		'needs-docs' : 'Inline documentation is needed.',
		'rtl-feedback' : 'Feedback or work is needed from the RTL perspective.',
		'needs-codex' : 'The Codex needs to be updated or expanded',
		'commit' : 'Patch is a suggested commit candidate.',
		'early' : 'Ticket should be addressed early in the next dev cycle.',
		'i18n-change' : 'A string change, used only after string freeze.'
	};

	wpKeywords = {

		keywords : {},
		originalKeywords : {},

		init : function() {

			wpKeywords.hiddenEl = $('#field-keywords');
			if ( ! wpKeywords.hiddenEl.length )
				return;

			// Designed so the list could have come from another file.
			if ( typeof coreKeywordList === 'undefined' )
				return;

			// Generate the workflow template.
			wpKeywords.template();

			wpKeywords.addField = $('#keyword-add');

			// Load up the initial keywords and the dropdown.
			wpKeywords.populate();

			// Save these for later.
			wpKeywords.originalKeywords = $.merge([], wpKeywords.keywords);

			// Catch the submit to see if keywords were simply reordered.
			wpKeywords.hiddenEl.parents('form').submit( wpKeywords.submit );

			// Keyword removal.
			$('#keyword-bin').delegate('a', 'click', function(e) {
				e.preventDefault();
				wpKeywords.remove( $(this).parent() );
			});

			// Keyword adds.
			$('#keyword-add').bind('change keypress', function(e) {
				if ( e.type === 'keypress' ) {
					if ( e.which === 13 ) {
						e.stopPropagation();
						e.preventDefault();
					} else {
						return;
					}
				}
				wpKeywords.add( $(this).val() );
				$(this).val('');		
			});

			// Manual link.
			$('#edit-keywords').click( function() {
				wpKeywords.hiddenEl.show().focus();
				$(this).hide();
				wpKeywords.hiddenEl.change( wpKeywords.populate );
			});
		},

		// Generates the workflow template.
		template : function() {
			var container = wpKeywords.hiddenEl.parent(), html, labelWidth, ownerField;

			// Necessary to keep everything in line. The + 4 is a careful CSS balance.
			labelWidth = container.prev().width() + 4;

			// Rearrange the table to suit our needs.
			// If the owner field exists, then we're on /newticket, so adjust that.
			container.prev().detach().end()
				.attr('colspan', '2').addClass('has-js')
				.parents('table').css('table-layout', 'fixed');

			ownerField = container.parents('table').find('#field-owner');
			if ( ownerField.length ) {
				// Switch the Owner and Keyword spots, so Keyword is on the bottom.
				ownerField.parent().attr('colspan', '1');
				$('#field-cc').parents('td').prev().appendTo( ownerField.parents('tr') );
				$('#field-cc').parents('td').appendTo( ownerField.parents('tr') );
				container.parent().insertAfter( container.parent().next() );
				container.parent().append( '<th class="col2" colspan="2"></th>' );
			}

			html = '<a id="edit-keywords">manual</a>';
			html += '<div><label id="keyword-label" for="keyword-add" style="width:' + labelWidth + 'px">Workflow Keywords:</label>';
			html += '<select id="keyword-add"><option value=""> - Add - </option></select></div>';
			html += '<div id="keyword-bin"></div>';
			container.prepend( html );

			// Walk in the footsteps of Firefox autocomplete's trail of destruction,
			// tidying the radio buttons in its wake. See WP#17051.
			$.browser.mozilla && $('#action input:radio').each( function() {
				this.checked = this.defaultChecked;
			});
		},

		// Populates the keywords and dropdown.
		populate : function() {
			var html = '', bin = $('#keyword-bin');

			// For repopulation. Starting over.
			if ( bin.find('span').length )
				bin.empty();

			// Replace commas, collapse spaces, trim, then split by space.
			wpKeywords.keywords = $.trim( wpKeywords.hiddenEl.val().replace(',', ' ').replace(/ +/g, ' ') ).split(' ');

			// Put our cleaned up version back into the hidden field.
			wpKeywords.hiddenEl.val( wpKeywords.keywords.join(' ') );

			// If we have a non-empty keyword, let's go through the process of adding the spans.
			if ( 1 !== wpKeywords.keywords.length || wpKeywords.keywords[0] !== '' ) {
				$.each( wpKeywords.keywords, function( k, v ) {
					html = $('<span />').text(v);
					if ( v in coreKeywordList )
						html.attr('title', coreKeywordList[v]);
					html.prepend('<a href="#" />').appendTo( bin );
				});
			}

			// Populate the dropdown.
			$.each( coreKeywordList, function( k, v ) {
				// Don't show special (permission-based) ones.
				if ( typeof wpKeywordsHide === 'undefined' || -1 === $.inArray( k, wpKeywordsHide ) )
					wpKeywords.addField.append( '<option value="' + k + ( -1 !== $.inArray( k, wpKeywords.keywords ) ? '" disabled="disabled">* ' : '">' ) + k + '</option>' );
			});
		},

		// Add a keyword. Takes a sanitized string.
		add : function( keyword ) {
			if ( ! keyword )
				return;
			var title = '';
			// Don't add it again.
			if ( -1 !== $.inArray( keyword, wpKeywords.keywords ) )
				return;
			wpKeywords.keywords.push( keyword );

			// Update the dropdown. Core keywords also get a title attribute with their description.
			if ( keyword in coreKeywordList ) {
				wpKeywords.addField.find('option[value=' + keyword + ']').attr('disabled', 'disabled').text('* ' + keyword);
				title = ' title="' + coreKeywordList[keyword] + '"';
			}

			// Add it to the bin, and refresh the hidden input.
			$('#keyword-bin').append( '<span' + title + '><a href="#"></a>' + keyword + "</span>\n" );
			wpKeywords.hiddenEl.val( wpKeywords.keywords.join(' ') );
		},

		// Remove a keyword. Takes a jQuery object.
		remove : function( object ) {
			var keyword = object.text();
			wpKeywords.keywords = $.grep(wpKeywords.keywords, function(v) {
				return v != keyword;
			});
			// Update the core keyword dropdown.
			if ( keyword in coreKeywordList )
				wpKeywords.addField.find('option[value=' + keyword + ']').attr('disabled', '').text( keyword );
			wpKeywords.hiddenEl.val( wpKeywords.keywords.join(' ') );
			object.remove();
		},

		// Check on submit that we're not just re-ordering keywords.
		// Otherwise, Trac flips out and adds a useless 'Keywords changed from X to X' marker.
		submit : function(e) {
			if ( wpKeywords.keywords.length !== wpKeywords.originalKeywords.length )
				return;
			var testKeywords = $.grep(wpKeywords.keywords, function(v) {
				return -1 === $.inArray( v, wpKeywords.originalKeywords );
			});
			// If the difference has no length, then restore to the original keyword order.
			if ( ! testKeywords.length )
				wpKeywords.hiddenEl.val( wpKeywords.originalKeywords.join(' ') );
		}

	};

	$(document).ready( wpKeywords.init );

})(jQuery);
