';
	/**
	 * Printed in HEAD
	 */
	const DEL_SCRIPTS_PRELOADS = '';
	/**
	 * @var array
	 */
	public $preloads = array('styles' => array(), 'scripts' => array());
	/**
	 * @var Preloads|null
	 */
	private static $singleton;
	/**
	 * @return null|Preloads
	 */
	public static function instance()
	{
		if (self::$singleton === null) {
			self::$singleton = new self();
		}
		return self::$singleton;
	}
	/**
	 * Preloads constructor.
	 */
	public function __construct()
	{
	    if (is_admin() || self::preventPreload()) {
	        return;
        }
		$this->preloads = $this->getPreloads();
		add_filter('wpfc_buffer_callback_filter', static function ($buffer) {
			$buffer = str_replace('rel=\'preload\' data-from-rel=\'stylesheet\'', 'rel=\'preload\'', $buffer);
			return $buffer;
		});
	}
	/**
	 *
	 */
	public function init()
	{
	    if (self::preventPreload()) {
	        return;
        }
		if (! is_admin()) { // Trigger only in the front-end
		    add_filter('style_loader_tag', array($this, 'preloadCss'), 10, 2);
		    add_filter('script_loader_tag', array($this, 'preloadJs'), 10, 2);
		} else { // Trigger only within the Dashboard
			if (Misc::getVar('post', 'wpacu_remove_preloaded_assets_nonce')) {
				add_action('admin_init', static function() {
					Preloads::removePreloadFromChosenAssets();
				});
			}
			// Trigger only in "Bulk Changes" -> "Preloaded CSS/JS"
			if (isset($_GET['page']) && $_GET['page'] === WPACU_PLUGIN_ID.'_bulk_unloads'
                && get_transient('wpacu_preloads_just_removed')) {
				add_action('wpacu_admin_notices', array($this, 'noticePreloadsRemoved'));
				delete_transient('wpacu_preloads_just_removed');
			}
		}
	}
	/**
	 * @param $htmlSource
	 *
	 * @return mixed
	 */
	public function doChanges($htmlSource)
    {
        if (self::preventPreload()) {
            return $htmlSource;
        }
	    $this->preloads = $this->getPreloads();
	    if (isset($this->preloads['styles']) && ! empty($this->preloads['styles'])) {
		    $htmlSource = self::appendPreloadsForStylesToHead($htmlSource);
	    }
	    return $htmlSource;
    }
	/**
	 * @param string $for
	 * @return bool
	 */
	public function enablePreloads($for)
	{
	    if (self::preventPreload()) {
	        return false;
        }
	    $assetType = ($for === 'css') ? 'styles' : 'scripts';
	    if (! (isset($this->preloads[$assetType]) && ! empty($this->preloads[$assetType]))) {
			return false;
		}
		// Do not use the preloads if "Optimize CSS Delivery" is enabled in WP Rocket
		if ($for === 'css' && Misc::isPluginActive('wp-rocket/wp-rocket.php') && function_exists('get_rocket_option') && get_rocket_option('async_css')) {
			return false;
		}
		// WP Fastest Cache: Combine CSS/JS is enabled
		if (! Menu::userCanManageAssets() && Misc::isPluginActive('wp-fastest-cache/wpFastestCache.php')) {
			$wpfcOptionsJson = get_option('WpFastestCache');
			$wpfcOptions     = @json_decode($wpfcOptionsJson, ARRAY_A);
			if ($for === 'css' && isset($wpfcOptions['wpFastestCacheCombineCss'])) {
				return false;
			}
			if ($for === 'js' && isset($wpfcOptions['wpFastestCacheCombineJs'])) {
				return false;
			}
		}
		// W3 Total Cache
		if (Misc::isPluginActive('w3-total-cache/w3-total-cache.php')) {
			$w3tcConfigMaster = Misc::getW3tcMasterConfig();
			if ($for === 'css') {
				$w3tcEnableCss = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.css.enable":', ','), '" ');
				if ($w3tcEnableCss === 1) {
					return false;
				}
			}
			if ($for === 'js') {
				$w3tcEnableJs = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.js.enable":', ','), '" ');
				if ($w3tcEnableJs === 1) {
					return false;
				}
			}
		}
		// LiteSpeed Cache
		if (Misc::isPluginActive('litespeed-cache/litespeed-cache.php') && ($liteSpeedCacheConf = apply_filters('litespeed_cache_get_options', get_option('litespeed-cache-conf')))) {
			if ($for === 'css' && isset($liteSpeedCacheConf['css_minify']) && $liteSpeedCacheConf['css_minify']) {
				return false;
			}
			if ($for === 'js' && isset($liteSpeedCacheConf['js_minify']) && $liteSpeedCacheConf['js_minify']) {
				return false;
			}
		}
		return true;
	}
	/**
	 * @return array
	 */
	public function getPreloads()
	{
		$preloadsListJson = get_option(WPACU_PLUGIN_ID . '_global_data');
		if ($preloadsListJson) {
			$preloadsList = @json_decode($preloadsListJson, true);
			// Issues with decoding the JSON file? Return an empty list
			if (Misc::jsonLastError() !== JSON_ERROR_NONE) {
				return $this->preloads;
			}
			// Are new positions set for styles and scripts?
			foreach (array('styles', 'scripts') as $assetKey) {
				if ( isset( $preloadsList[$assetKey]['preloads'] ) && ! empty( $preloadsList[$assetKey]['preloads'] ) ) {
					$this->preloads[$assetKey] = $preloadsList[$assetKey]['preloads'];
				}
			}
		}
		return $this->preloads;
	}
	/**
	 * @param $htmlTag
	 * @param $handle
	 *
	 * @return string
	 */
	public function preloadCss($htmlTag, $handle)
	{
	    if (Plugin::preventAnyFrontendOptimization() || self::preventPreload()) {
	        return $htmlTag;
        }
		if ($wpacuAsyncPreloadHandle = Misc::getVar('get', 'wpacu_preload_css')) {
			// For testing purposes: Check how the page loads with the requested CSS preloaded
			$this->preloads['styles'][$wpacuAsyncPreloadHandle] = 'basic';
		}
		// Only valid for front-end pages with LINKs
		if (is_admin() || (! $this->enablePreloads('css')) || strpos($htmlTag,'preventAssetsSettings()) {
			return $htmlTag;
		}
		if (! isset($this->preloads['styles'])) {
			return $htmlTag;
		}
		if (array_key_exists($handle, $this->preloads['styles']) && $this->preloads['styles'][$handle]) {
            if (isset($_REQUEST['wpacu_no_css_preload_basic'])) { // do not apply it for debugging purposes
	            return str_replace('preloads['scripts'][$wpacuJsPreloadHandle] = 1;
		}
		// Only valid for front-end pages with SCRIPTs
		if (is_admin() || (! $this->enablePreloads('js')) || strpos($htmlTag,'