( function( api, $, l10n ) {
	'use strict';

	// Font Smoothing.
	api( 'enable_font_smoothing', function( value ) {
		value.bind( function( newval ) {
			if ( newval ) {
				document.body.classList.add( 'wpex-antialiased' );
			} else {
				document.body.classList.remove( 'wpex-antialiased' );
			}
		} );
	} );

	// Live Typography CSS.
	var wpexCustomizerTypography = {

		init: function() {
			var self = this;

			// Loop through settings.
			_.each( l10n.settings, function( settingArgs, settingKey ) {
				// Loop through available attributes.
				_.each( l10n.properties, function( property ) {
					if ( settingArgs.exclude && $.inArray( property, settingArgs.exclude ) > -1 ) {
						return;
					}
					// Hook into the customizer api to listen to changes to our settings.
					api( settingKey + '_typography[' + property + ']', function( value ) {
						// Do things when the value of a setting changes.
						value.bind( function( newval ) {
							/* Generate CSS variable :root styles - @todo var
							if ( settingArgs.css_var ) {
								self.generateSettingStyles( settingKey, ':root', settingArgs.css_var + property, newval );
							}*/
							// Generate standard styles.
							if ( settingArgs.target ) {
								self.generateSettingStyles( settingKey, settingArgs.target, property, newval );
							}
						} );
					} );
				} );
			} );
		},

		/**
		 * Loop through setting to add style tags.
		 */
		generateSettingStyles: function( settingKey, selector, property, value ) {
			if ( ! selector || ! property ) {
				return;
			}

			const self = this;
			var styleId = 'wpex-customizer-' + settingKey + '-' + property;
			var style = '';

			// Remove style whenever the value is empty or undefined.
			if ( '' === value || 'undefined' === typeof value ) {
				let styleEl = $( '#' + styleId );
				if ( styleEl.length ) {
					styleEl.remove();
				}
				return;
			}

			// Convert selector to string if it's an array.
			if ( '[object Array]' === Object.prototype.toString.call( selector ) ) {
				selector = selector.toString();
			}

			// Target a single property.
			if ( 'string' === typeof property ) {

				// Load Google font scripts and parse font family.
				if ( 'font-family' === property ) {
					self.appendGoogleFonts( settingKey, value );
					if ( 'system-ui' === value ) {
						value = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
					}
				}

				// Font size needs to do it's own thing for responsiveness.
				if ( 'font-size' === property ) {
					if ( self.isJSON( value ) ) {
						value = JSON.parse( value );
						$.each( value, function( index, value ) {
							value = self.parseFontSize( value );
							if ( 'd' === index ) {
								style += selector + '{' + property + ':' + value + ';}';
							} else if ( 'tl' === index ) {
								style += '@media(max-width:1024px){' + selector + '{' + property + ':' + value + ';}}';
							} else if ( 'tp' === index ) {
								style += '@media(max-width:959px){' + selector + '{' + property + ':' + value + ';}}';
							} else if ( 'pl' === index ) {
								// Technically the media query should be at 767px but this is  a fix because of the Customizer preview responsive toggles.
								style += '@media(max-width:600px){' + selector + '{' + property + ':' + value + ';}}';
							} else if ( 'pp' === index ) {
								style += '@media(max-width:479px){' + selector + '{' + property + ':' + value + ';}}';
							}
						} );
					} else {
						style += self.getCSS( selector, property, self.parseFontSize( value ) );
					}
				}

				// All other fields.
				else {

					// Letter Spacing sanitization.
					if ( 'letter-spacing' === property ) {
						if ( $.isNumeric( value ) ) {
							value = value + 'px'; // add px
						}
					}

					// Recursive margin.
					if ( 'margin' === property && -1 !== value.indexOf(':') ) {
						value.split('|').forEach( ( item ) => {
							let itemSplit = item.split(/:/);
							if ( 2 === itemSplit.length ) {
								style += self.getCSS( selector, 'margin-' + itemSplit[0], itemSplit[1] );
							}
						} );
					} else {
						style += self.getCSS( selector, property, value );
					}

				}

			}

			// Target multiple properties.
			else {

				$.each( property, function( index, value ) {
					style += self.getCSS( selector, value, value );
				} );

			}

			if ( style ) {
				if ( $( '#' + styleId ).length !== 0 ) {
					$( '#' + styleId ).replaceWith( '<style id="' + styleId + '">' + style + '</style>' );
				} else {
					$( '<style id="' + styleId + '">' + style + '</style>' ).appendTo( $( 'head' ) );
				}
			}

		},

		/**
		 * Return CSS for standard target.
		 */
		getCSS: function( selector, property, val ) {
			return selector + '{' + property + ':' + val + ';}';
		},

		/**
		 * Parse font size.
		 */
		isJSON: function( str ) {
			try {
				return (JSON.parse(str) && !!str);
			} catch (e) {
				return false;
			}
		},

		/**
		 * Parse font size.
		 */
		parseFontSize: function( val ) {
			if ( $.isNumeric( val ) ) {
				val = val + 'px';
			}
			return val;
		},

		/**
		 * Load Google Font.
		 */
		appendGoogleFonts: function( settingKey, value ) {
			var fontScriptID = 'wpex-customizer-' + settingKey + '-font-stylesheet';
			var link = $( '#' + fontScriptID );

			// Remove script if it already exists.
			if ( link.length ) {
				link.remove();
			}

			// Return if value is empty.
			if ( ! value ) {
				return;
			}

			// Custom or standard fonts.
			if ( ( $.inArray( value, l10n.customFonts ) > -1 ) || ( $.inArray( value, l10n.stdFonts ) > -1 ) ) {
				return;
			}

			var fontScriptHref = value.replace( " ", "%20" );
			fontScriptHref = fontScriptHref.replace( ",", "%2C" );
			fontScriptHref = l10n.googleFontsUrl + "/css?family=" + value +  ":" + l10n.googleFontsSuffix;

			// Append Google Font if value isn't empty.
			if ( value ) {
				$( 'head' ).append( '<link id="' + fontScriptID +'" rel="stylesheet" href="'+ fontScriptHref +'">' );
			}
		}

	};

	wpexCustomizerTypography.init();

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