wp.customize.controlConstructor['slider'] = wp.customize.Control.extend({

	ready: function() {

		'use strict';

		var control = this,
		    value,
		    thisInput,
		    inputDefault,
		    changeAction,
		    maxText = control.params.choices && control.params.choices.max_text,
		    maxValue = control.params.choices && control.params.choices.max_value,
		    maxNum = maxText ? parseInt( control.params.choices.max, 10 ) : 0;

		function getDisplayText( val ) {
			if ( maxText && parseInt( val, 10 ) === maxNum ) {
				return maxText;
			}
			return val;
		}

		function updateDisplay( $range, displayVal, isMaxText ) {
			var $rangeValue = $range.closest( 'label' ).find( '.range_value' );
			$rangeValue.empty().append( jQuery( '<span class="value"></span>' ).text( displayVal ) );
			if ( ! isMaxText && control.params.choices.suffix ) {
				$rangeValue.append( document.createTextNode( control.params.choices.suffix ) );
			}
		}

		// Update the text value
		control.container.on( 'mousedown', 'input[type=range]', function() {
			value = this.value;
			jQuery( this ).mousemove( function() {
				value = this.value;
				var isMax = maxText && parseInt( value, 10 ) === maxNum;
				updateDisplay( jQuery( this ), getDisplayText( value ), isMax );
			});
		});

		// Handle the reset button
		control.container.on( 'click', '.slider-reset', function() {
			thisInput = jQuery( this ).closest( 'label' ).find( 'input' );
			inputDefault = thisInput.data( 'reset_input' );
			var resetValue = thisInput.data( 'reset_value' );
			thisInput.val( inputDefault );
			control.setting.set( resetValue );
			var isMax = maxText && ( resetValue === maxValue || parseInt( inputDefault, 10 ) === maxNum );
			updateDisplay( thisInput, getDisplayText( inputDefault ), isMax );
		});

		if ( 'postMessage' === control.setting.transport ) {
			changeAction = 'mousemove change';
		} else {
			changeAction = 'change';
		}

		// Save changes.
		control.container.on( changeAction, 'input', function() {
			var val = jQuery( this ).val();
			var isMax = maxText && parseInt( val, 10 ) === maxNum;
			var settingVal = isMax ? maxValue : val;
			control.setting.set( settingVal );
			updateDisplay( jQuery( this ), getDisplayText( val ), isMax );
		});

		// Sync input when setting changes externally (e.g. refresh, undo).
		if ( maxText ) {
			control.setting.bind( function( val ) {
				var inputVal = ( val === maxValue ) ? maxNum : val;
				var $input = control.container.find( 'input[type=range]' );
				if ( $input.length && parseInt( $input.val(), 10 ) !== parseInt( inputVal, 10 ) ) {
					$input.val( inputVal );
					var isMax = val === maxValue;
					updateDisplay( $input, getDisplayText( String( inputVal ) ), isMax );
				}
			} );
		}
	}

});
