<?php

/**
 * This class configures the parameters advanced
 *
 * @author        Artem Prihodko <webtemyk@yandex.ru>
 * @author        Alexander Kovalev <alex.kovalevv@gmail.com>, GitHub: https://github.com/alexkovalevv
 * @copyright (c) 25.04.2020, Webcraftic
 * @version       1.0
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class WAJS_Configurate {

	/**
	 * @var bool
	 */
	public $enabled = false;

	/**
	 * @var string
	 */
	public $method = 'async';

	/**
	 * @var string
	 */
	public $jquery = 'exclude';

	/**
	 * @var string
	 */
	public $exclusions = '';

	/**
	 * @var string
	 */
	public $async = '';

	/**
	 * @var string
	 */
	public $defer = '';

	/**
	 * @var string
	 */
	public $plugin_exclusions = '';

	/**
	 * @var string
	 */
	public $theme_exclusions = '';

	/**
	 * @param WCL_Plugin $plugin
	 *
	 * @throws \Exception
	 */
	public function __construct( $plugin ) {
		if ( ! $plugin instanceof WCL_Plugin ) {
			throw new \Exception( 'Invalid $plugin argument type passed.' );
		}
		$this->plugin = $plugin;
		$this->init_options();
		$this->registerActionsAndFilters();
	}

	/**
	 * Register actions and filters
	 */
	public function registerActionsAndFilters() {
		if ( ! is_admin() ) {
			add_filter( 'script_loader_tag', [ $this, 'do_async_js' ], 20, 3 );
		}
	}

	/**
	 * Init addon options
	 */
	public function init_options() {
		$this->enabled = $this->plugin->getOption( 'ajs_enabled', false );
		$this->method  = ( $this->plugin->getOption( 'ajs_method', 'async' ) == 'async' ) ? 'async' : 'defer';
		$this->jquery  = $this->plugin->getOption( 'ajs_jquery', 'exclude' );

		$ajs_exclusions   = $this->plugin->getOption( 'ajs_exclusions', '' );
		$this->exclusions = ( $ajs_exclusions != '' ) ? explode( ',', $ajs_exclusions ) : array();

		$ajs_async   = $this->plugin->getOption( 'ajs_async', '' );
		$this->async = ( $ajs_async != '' ) ? explode( ',', $ajs_async ) : array();

		$ajs_defer   = $this->plugin->getOption( 'ajs_defer', '' );
		$this->defer = ( $ajs_defer != '' ) ? explode( ',', $ajs_defer ) : array();

		$ajs_plugin              = $this->plugin->getOption( 'ajs_plugin_exclusions', '' );
		$this->plugin_exclusions = ( $ajs_plugin != '' ) ? explode( ',', $ajs_plugin ) : array();

		$ajs_theme              = $this->plugin->getOption( 'ajs_theme_exclusions', '' );
		$this->theme_exclusions = ( $ajs_theme != '' ) ? explode( ',', $ajs_theme ) : array();
	}

	/**
	 * Check if async or defer is already defined
	 *
	 * @param string $tag
	 * @param string $src
	 *
	 * @return bool
	 */
	public function is_async_or_defer( $tag, $src ) {
		$tag = str_replace( $src, '', $tag );
		if ( false !== strpos( strtolower( $tag ), 'async' ) || false !== strpos( strtolower( $tag ), 'defer' ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Do 'script_loader_tag' filter
	 *
	 * @author Frank Goossens https://profiles.wordpress.org/futtta/
	 */
	public function do_async_js( $tag, $handle, $src ) {
		if ( $this->is_async_or_defer( $tag, $src ) ) {
			return $tag;
		}

		if ( $this->enabled && ! $this->ajs_is_amp() ) {
			if ( is_array( $this->plugin_exclusions ) && ! empty( $this->plugin_exclusions ) ) {
				foreach ( $this->plugin_exclusions as $ajs_plugin_exclusion ) {
					$ajs_plugin_exclusion = trim( $ajs_plugin_exclusion );
					if ( ! empty( $ajs_plugin_exclusion ) ) {
						if ( false !== strpos( strtolower( $src ), strtolower( $ajs_plugin_exclusion ) ) ) {
							return $tag;
						}
					}
				}
			}
			if ( is_array( $this->theme_exclusions ) && ! empty( $this->theme_exclusions ) ) {
				foreach ( $this->theme_exclusions as $ajs_theme_exclusion ) {
					$ajs_theme_exclusion = trim( $ajs_theme_exclusion );
					if ( ! empty( $ajs_theme_exclusion ) ) {
						if ( false !== strpos( strtolower( $src ), strtolower( $ajs_theme_exclusion ) ) ) {
							return $tag;
						}
					}
				}
			}
			if ( is_array( $this->exclusions ) && ! empty( $this->exclusions ) ) {
				foreach ( $this->exclusions as $exclusion ) {
					$exclusion = trim( $exclusion );
					if ( ! empty( $exclusion ) ) {
						if ( false !== strpos( strtolower( $src ), strtolower( $exclusion ) ) ) {
							return $tag;
						}
					}
				}
			}
			if ( false !== strpos( strtolower( $src ), 'js/jquery/jquery.js' ) ) {
				if ( $this->jquery == 'async' || $this->jquery == 'defer' ) {
					$tag = str_replace( 'src=', $this->jquery . "='" . $this->jquery . "' src=", $tag );

					return $tag;
				} else if ( $this->jquery == 'exclude' ) {
					return $tag;
				}
			}
			if ( is_array( $this->async ) && ! empty( $this->async ) ) {
				foreach ( $this->async as $async ) {
					$async = trim( $async );
					if ( ! empty( $async ) ) {
						if ( false !== strpos( strtolower( $src ), strtolower( $async ) ) ) {
							return str_replace( 'src=', "async='async' src=", $tag );
						}
					}
				}
			}
			if ( is_array( $this->defer ) && ! empty( $this->defer ) ) {
				foreach ( $this->defer as $defer ) {
					$defer = trim( $defer );
					if ( ! empty( $defer ) ) {
						if ( false !== strpos( strtolower( $src ), strtolower( $defer ) ) ) {
							return str_replace( 'src=', "defer='defer' src=", $tag );
						}
					}
				}
			}

			$tag = str_replace( 'src="', $this->method . '="' . $this->method . '" src="', $tag );
			$tag = str_replace( "src='", $this->method . "='" . $this->method . "' src='", $tag );

			return $tag;
		}

		return $tag;
	}

	/**
	 * Returns true if given current page is AMP.
	 *
	 * @return bool
	 */
	public static function ajs_is_amp() {
		if ( ! function_exists( 'is_amp_endpoint' ) || ! is_amp_endpoint() ) {
			return false;
		} else {
			return true;
		}
	}

}