/* global twentyTwentyBgColors, twentyTwentyPreviewEls, jQuery, _, wp */

/**

 * Customizer enhancements for a better user experience.

 *

 * Contains handlers to make Theme Customizer preview reload changes asynchronously.

 *

 * @since Twenty Twenty 1.0

 */



( function( $, api, _ ) {

	/**

	 * Return a value for our partial refresh.

	 *

	 * @param {Object} partial  Current partial.

	 *

	 * @return {jQuery.Promise} Resolved promise.

	 */

	function returnDeferred( partial ) {

		var deferred = new $.Deferred();



		deferred.resolveWith( partial, _.map( partial.placements(), function() {

			return '';

		} ) );



		return deferred.promise();

	}



	// Selective refresh for "Fixed Background Image".

	api.selectiveRefresh.partialConstructor.cover_fixed = api.selectiveRefresh.Partial.extend( {



		/**

		 * Override the refresh method.

		 *

		 * @return {jQuery.Promise} Resolved promise.

		 */

		refresh: function() {

			var partial, cover, params;



			partial = this;

			params = partial.params;

			cover = $( params.selector );



			if ( cover.length && cover.hasClass( 'bg-image' ) ) {

				cover.toggleClass( 'bg-attachment-fixed' );

			}



			return returnDeferred( partial );

		}



	} );



	// Selective refresh for "Image Overlay Opacity".

	api.selectiveRefresh.partialConstructor.cover_opacity = api.selectiveRefresh.Partial.extend( {



		/**

		 * Input attributes.

		 *

		 * @type {Object}

		 */

		attrs: {},



		/**

		 * Override the refresh method.

		 *

		 * @return {jQuery.Promise} Resolved promise.

		 */

		refresh: function() {

			var partial, ranges, attrs, setting, params, cover, className, classNames;



			partial = this;

			attrs = partial.attrs;

			ranges = _.range( attrs.min, attrs.max + attrs.step, attrs.step );

			params = partial.params;

			setting = api( params.primarySetting );

			cover = $( params.selector );



			if ( cover.length ) {

				classNames = _.map( ranges, function( val ) {

					return 'opacity-' + val;

				} );



				className = classNames[ ranges.indexOf( parseInt( setting.get(), 10 ) ) ];



				cover.removeClass( classNames.join( ' ' ) );

				cover.addClass( className );

			}



			return returnDeferred( partial );

		}



	} );



	// Add listener for the "header_footer_background_color" control.

	api( 'header_footer_background_color', function( value ) {

		value.bind( function( to ) {

			// Add background color to header and footer wrappers.

			$( 'body:not(.overlay-header)#site-header, #site-footer' ).css( 'background-color', to );



			// Change body classes if this is the same background-color as the content background.

			if ( to.toLowerCase() === api( 'background_color' ).get().toLowerCase() ) {

				$( 'body' ).addClass( 'reduced-spacing' );

			} else {

				$( 'body' ).removeClass( 'reduced-spacing' );

			}

		} );

	} );



	// Add listener for the "background_color" control.

	api( 'background_color', function( value ) {

		value.bind( function( to ) {

			// Change body classes if this is the same background-color as the header/footer background.

			if ( to.toLowerCase() === api( 'header_footer_background_color' ).get().toLowerCase() ) {

				$( 'body' ).addClass( 'reduced-spacing' );

			} else {

				$( 'body' ).removeClass( 'reduced-spacing' );

			}

		} );

	} );



	// Add listener for the accent color.

	api( 'accent_hue', function( value ) {

		value.bind( function() {

			// Generate the styles.

			// Add a small delay to be sure the accessible colors were generated.

			setTimeout( function() {

				Object.keys( twentyTwentyBgColors ).forEach( function( context ) {

					twentyTwentyGenerateColorA11yPreviewStyles( context );

				} );

			}, 50 );

		} );

	} );



	// Add listeners for background-color settings.

	Object.keys( twentyTwentyBgColors ).forEach( function( context ) {

		wp.customize( twentyTwentyBgColors[ context ].setting, function( value ) {

			value.bind( function() {

				// Generate the styles.

				// Add a small delay to be sure the accessible colors were generated.

				setTimeout( function() {

					twentyTwentyGenerateColorA11yPreviewStyles( context );

				}, 50 );

			} );

		} );

	} );



	/**

	 * Add styles to elements in the preview pane.

	 *

	 * @since Twenty Twenty 1.0

	 *

	 * @param {string} context The area for which we want to generate styles. Can be for example "content", "header" etc.

	 *

	 * @return {void}

	 */

	function twentyTwentyGenerateColorA11yPreviewStyles( context ) {

		// Get the accessible colors option.

		var a11yColors = window.parent.wp.customize( 'accent_accessible_colors' ).get(),

			stylesheedID = 'twentytwenty-customizer-styles-' + context,

			stylesheet = $( '#' + stylesheedID ),

			styles = '';

		// If the stylesheet doesn't exist, create it and append it to <head>.

		if ( ! stylesheet.length ) {

			$( '#twentytwenty-style-inline-css' ).after( '<style id="' + stylesheedID + '"></style>' );

			stylesheet = $( '#' + stylesheedID );

		}

		if ( ! _.isUndefined( a11yColors[ context ] ) ) {

			// Check if we have elements defined.

			if ( twentyTwentyPreviewEls[ context ] ) {

				_.each( twentyTwentyPreviewEls[ context ], function( items, setting ) {

					_.each( items, function( elements, property ) {

						if ( ! _.isUndefined( a11yColors[ context ][ setting ] ) ) {

							styles += elements.join( ',' ) + '{' + property + ':' + a11yColors[ context ][ setting ] + ';}';

						}

					} );

				} );

			}

		}

		// Add styles.

		stylesheet.html( styles );

	}

	// Generate styles on load. Handles page-changes on the preview pane.

	$( document ).ready( function() {

		twentyTwentyGenerateColorA11yPreviewStyles( 'content' );

		twentyTwentyGenerateColorA11yPreviewStyles( 'header-footer' );

	} );

}( jQuery, wp.customize, _ ) );

